This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Hello,
I am trying to have an SPI communication setup between MSP430FR5994 (Master) and CC1352R (Slave). I am trying to replicate the SPI example given in the TI Resource explorer/TI Drivers of CC1352R. The CC1352R master and slave example works for me on two CC1352R boards. Now, I want to replace the CC1352R master with the MSP430FR5994 master. And I think I have some configuration issues, I suspect halHwi1Params.arg = 3. My application stuck when the SPI_transfer is in progress.
Compiler version - 16.9.11.LTS
TI-RTOS version - 2.20.0.06
XDCTools version - 3.32.0.06_core
My configuration -
var halHwi0Params = new halHwi.Params(); halHwi0Params.arg = 0; halHwi0Params.instance.name = "halHwi0"; halHwi0Params.priority = 1; Program.global.halHwi0 = halHwi.create(48, "&UARTEUSCIA_hwiIntFxn", halHwi0Params); var halHwi1Params = new halHwi.Params(); halHwi1Params.instance.name = "halHwi1"; halHwi1Params.arg = 3; halHwi1Params.priority = 3; Program.global.halHwi1 = halHwi.create(24, "&MSP_EXP430FR5994_isrDMA", halHwi1Params); var halHwi2Params = new halHwi.Params(); halHwi2Params.arg = 4; halHwi2Params.priority = 5; Program.global.halHwi2 = halHwi.create(32, "&GPIO_hwiIntFxn", halHwi2Params);
And in msp430fr5994.c, MSP_EXP430FR5994_isrDMA looks like this
/* * =============================== DMA =============================== */ /* * ======== MSP_EXP430FR5994_isrDMA ======== * This is a application defined DMA ISR. This ISR must map and call the * appropriate Driver_event(handle) API to indicate completed DMA transfers. */ Void MSP_EXP430FR5994_isrDMA(UArg arg) { /* Call the SPI DMA function, passing the SPI handle used for WiFi */ SPI_serviceISR((SPI_Handle) &(SPI_config[0])); }
My SPI master tasks looks like this:
void spiMasterFxn(UArg arg0, UArg arg1) { uint32_t i; bool transferOK; char uartStr[10]; /* Configure spi master and slave ready gpio pins */ GPIO_setConfig(CONFIG_SPI_MASTER_READY, GPIO_CFG_OUTPUT | GPIO_CFG_OUT_LOW); GPIO_setConfig(CONFIG_SPI_SLAVE_READY, GPIO_CFG_INPUT); /* Set master ready pin */ GPIO_write(CONFIG_SPI_MASTER_READY, 1); UART_write(uart, "CONFIG_SPI_MASTER_READY\n", sizeof("CONFIG_SPI_MASTER_READY\n")); /* Wait for slave to be ready */ while (GPIO_read(CONFIG_SPI_SLAVE_READY) == 0) {} UART_write(uart, "handshake complete! \n", sizeof("handshake complete! \n")); /* Handshake complete; now configure interrupt on CONFIG_SPI_SLAVE_READY */ GPIO_setConfig(CONFIG_SPI_SLAVE_READY, GPIO_CFG_IN_PU | GPIO_CFG_IN_INT_FALLING); GPIO_setCallback(CONFIG_SPI_SLAVE_READY, slaveReadyFxn); GPIO_enableInt(CONFIG_SPI_SLAVE_READY); UART_write(uart, "configure interrupt on slave\n", sizeof("configure interrupt on slave\n")); /* Create a semaphore; the master will wait on this semaphore * until the slave is ready. */ Semaphore_Params params; Error_Block eb; /* Init params */ Semaphore_Params_init(¶ms); Error_init(&eb); /* Create semaphore instance */ masterSem = Semaphore_create(0, ¶ms, &eb); if(masterSem == NULL) { System_printf("Semaphore creation failed"); System_flush(); } /* Open SPI as master */ SPI_Params_init(&spiParams); spiParams.frameFormat = SPI_POL0_PHA1; spiParams.mode = SPI_MASTER; spiParams.bitRate = 1000000; masterSpi = SPI_open(Board_SPI0, &spiParams); if (masterSpi == NULL) { UART_write(uart, "Error initializing master SPI\n", sizeof("Error initializing master SPI\n")); while (1); } else { UART_write(uart, "Master SPI initialized\n", sizeof("Master SPI initialized\n")); } /* * Master has opened CONFIG_SPI_MASTER; set CONFIG_SPI_MASTER_READY low to * inform the slave. */ GPIO_write(CONFIG_SPI_MASTER_READY, 0); /* Copy message to transmit buffer */ strncpy((char *) masterTxBuffer, MASTER_MSG, SPI_MSG_LENGTH); for (i = 0; i < MAX_LOOP; i++) { /* * Wait until slave is ready for transfer; slave will pull * CONFIG_SPI_SLAVE_READY low. */ UART_write(uart, "Waiting for master_sem\n", sizeof("Waiting for master_sem\n")); Semaphore_pend(masterSem, BIOS_WAIT_FOREVER); UART_write(uart, "Create transaction\n", sizeof("Create transaction\n")); /* Initialize master SPI transaction structure */ masterTxBuffer[sizeof(MASTER_MSG) - 1] = (i % 10) + '0'; memset((void *) masterRxBuffer, 0, SPI_MSG_LENGTH); transaction.count = SPI_MSG_LENGTH; transaction.txBuf = (void *) masterTxBuffer; transaction.rxBuf = (void *) masterRxBuffer; /* Toggle user LED, indicating a SPI transfer is in progress */ UART_write(uart, "Transfer in progress\n", sizeof("Transfer in progress\n")); GPIO_toggle(Board_LED1); /* Perform SPI transfer */ transferOK = SPI_transfer(masterSpi, &transaction); sprintf(uartStr, "%d", transferOK ); UART_write(uart, "transfer ok = ", sizeof("transfer ok = ")); UART_write(uart, uartStr, sizeof(uartStr)); if (transferOK) { UART_write(uart, "\nMaster received\n", sizeof("Master received\n")); } else { UART_write(uart, "\nUnsuccessful Master received\n", sizeof("Unsuccessful Master received\n")); } /* Sleep for a bit before starting the next SPI transfer */ Task_sleep(100); } SPI_close(masterSpi); /* Example complete - set pins to a known state */ GPIO_disableInt(CONFIG_SPI_SLAVE_READY); GPIO_setConfig(CONFIG_SPI_SLAVE_READY, GPIO_CFG_OUTPUT | GPIO_CFG_OUT_LOW); GPIO_write(CONFIG_SPI_MASTER_READY, 0); UART_write(uart, "Done!\n", sizeof("Done!\n")); }
Let me know if you need more information. Thanks.
Another piece of information -
When I debugged the code, I found it is waiting on a semaphore because I am using a BLOCKING transfer mode.
Stuck on - Semaphore_pend(Semaphore_handle(&(object->transferComplete)), BIOS_WAIT_FOREVER);
* ======== SPIEUSCIADMA_transfer ======== * @pre Function assumes that handle and transaction is not NULL */ bool SPIEUSCIADMA_transfer(SPI_Handle handle, SPI_Transaction *transaction) { unsigned int key; SPIEUSCIADMA_Object *object = handle->object; SPIEUSCIADMA_HWAttrs const *hwattrs = handle->hwAttrs; /* Check the transaction arguments */ if ((transaction->count == 0) || !(transaction->rxBuf || transaction->txBuf) || (!(transaction->rxBuf && transaction->txBuf) && !hwattrs->scratchBufPtr)) { return (false); } /* Check if a transfer is in progress */ key = Hwi_disable(); if (object->transaction) { Hwi_restore(key); Log_error1("SPI:(%p) transaction still in progress", hwattrs->baseAddr); /* Transfer is in progress */ return (false); } else { /* Save the pointer to the transaction */ object->transaction = transaction; } Hwi_restore(key); SPIEUSCIADMA_configDMA(handle, transaction); if (object->transferMode == SPI_MODE_BLOCKING) { Log_print1(Diags_USER1, "SPI:(%p) transfer pending on transferComplete semaphore", hwattrs->baseAddr); Semaphore_pend(Semaphore_handle(&(object->transferComplete)), BIOS_WAIT_FOREVER); } return (true); }
It is suggested to simplify the code to check just MSP430FR5994 (Master) and CC1352R (Slave).
1. Do you have checked the difference between MSP430FR5994 (Master) and CC1352R (Master)? The clock setting and register setting may be different.
2. It is possible to try to make MSP430FR5994 (Master) and MSP430FR5994 (Slave) to work firstly and replace MSP430FR5994 (Slave) with CC1352R (Slave).
Hello Lixin,
I have tried to make settings in MSP430FR5994 (master) and CC1352R (master) be the same.
1. Let me check the clock setting.
2. I am going to try to set up MSP430FR5994 (Master) and MSP430FR5994 (Slave) today and check if that works.
I will come back to you. Thanks.
Vishal
So I have tried MSP430FR5994 (Master) and MSP430FR5994 (Slave) setup, both running the same TI-RTOS version.
It still doesn't work and it is stuck at the same location as I have shown earlier.
I still suspect it to be a configuration issue.
I am not sure what is wrong with my current configuration or I need to add some more configuration.
Here is the screenshot of Master when it is inside the
bool SPIEUSCIADMA_transfer(SPI_Handle handle, SPI_Transaction *transaction)
Another update: I have modified the register level examples of SPI to work with e_USCIA3 on MSP430FR5994 and it works fine between MSP430FR5994 (Master) and MSP430FR5994 (Slave).
Now I am pretty sure it is either an issue with TI-RTOS drivers or the configuration that I am using.
Please help me here a little bit. Thanks.
Vishal
Could you check the SPI waveform for the issue and see what signal has problems?
Hi,
I am not sure if it because that you can't enable DMA and CPU to work at the same time on MSP430. I advice you first not use DMA to run SPI.
My advice is that you can check the SPI wave or the SPI registers in debug mode to know what the SPI peripherals have done.
Eason
I found the problem.
In the MSP430-TI-RTOS empty example, the DMA channel configuration was reversed for TX and RX buffer. Here is what I did to solve it.
First, I updated my configuration in the .cfg file to use DMA interrupt vector number which is 42 for MSP430FR5994.
var halHwi1Params = new halHwi.Params(); halHwi1Params.instance.name = "halHwi1"; halHwi1Params.arg = 0; halHwi1Params.priority = 3; Program.global.halHwi1 = halHwi.create(42, "&MSP_EXP430FR5994_isrDMA", halHwi1Params);
Then in the MSP_EXP430FR5994.c file, I reversed the DMA channel and trigger for RX and TX buffer.
const SPIEUSCIADMA_HWAttrs spiEUSCIADMAHWAttrs[MSP_EXP430FR5994_SPICOUNT] = { { .baseAddr = EUSCI_A3_BASE, .clockSource = EUSCI_A_SPI_CLOCKSOURCE_SMCLK, .bitOrder = EUSCI_A_SPI_MSB_FIRST, .scratchBufPtr = &spiEUSCIADMAscratchBuf[0], .defaultTxBufValue = 0, /* DMA */ .dmaBaseAddr = DMA_BASE, /* Rx Channel */ .rxDMAChannelIndex = DMA_CHANNEL_4, .rxDMASourceTrigger = DMA_TRIGGERSOURCE_16, /* Tx Channel */ .txDMAChannelIndex = DMA_CHANNEL_5, .txDMASourceTrigger = DMA_TRIGGERSOURCE_17 } };
Now, I have a working MSP430FR5994 (Master and Slave) working. Next, I am moving on to work on MSP430FR5994 as Master and CC1352R as Slave.
Update: The above configuration fixed things on MSP430. Now, I have a working example of SPI communication between MSP430FR5994 (Master) and CC1352R (slave) both running TI-RTOS. If anyone needs a solution they can look at this GitHub repo.
**Attention** This is a public forum