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.
Hi,
I have configured SSI to get data from DMA and I have attached the code for reference. Sometimes I am observing that I am missing data in DMABuffer. My data contains sequence number which can be validated but its missing in DMABuffer.
I have conducted a test as below:
I had made sure that DMABuffer is not accessed and modified elsewhere I have commented other part of code and had it only in interrupt (SSI0_dma_int). If I run the code for some time and watch this buffer in watch window I am seeing that some data missing.
DMABuffer buffer will be filled only by DMA and why it is not in proper order?
Regards
/* DMA is Inialized on power up. */ void initDMA (void) { Error_Block eb; Hwi_Params hwiParams; ULONG lnTemp; if(!DMA_initialized){ Error_init(&eb); Hwi_Params_init(&hwiParams); Hwi_construct(&(hwiStruct), INT_UDMAERR, errorDMAHwi, &hwiParams, &eb); if (Error_check(&eb)) { System_abort("Couldn't construct DMA error hwi"); } SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA); uDMAEnable(); uDMAControlBaseSet(DMAControlTable); DMA_initialized = TRUE; } } power_up_init() { /* On power up, GPIOs are configured. */ // *** SSI Module(FLASH) *** MAP_GPIOPinConfigure(GPIO_PA2_SSI0CLK); MAP_GPIOPinConfigure(GPIO_PA3_SSI0FSS); MAP_GPIOPinConfigure(GPIO_PA4_SSI0XDAT0); MAP_GPIOPinConfigure(GPIO_PA5_SSI0XDAT1); // Configure the GPIO pins for the SSI module MAP_GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5); } /* This function is called after power up routines. During power up, SPI0 is working fine, its reading data from flash. We change SPI0 from master to slave and want to read data from SSI0 using DMA. */ void run_time() { /* On power on I am having same SPI configured as Master hence, closing it and later configuring as slave.. On power on we are reading data from FLASH, it is working fine. but here we are not using DMA. */ SPI_close(spiHandles[TM4C129X_SPI0]); /* Reset the SPI */ lnTemp = HWREG(SYSCTL_BASE + 0x51C); lnTemp = (lnTemp | SYSCTL_SRSSI_R0); HWREG(SYSCTL_BASE + 0x51C) = lnTemp; lnTemp = HWREG(SYSCTL_BASE + 0x51C); lnTemp = (lnTemp & ~(SYSCTL_SRSSI_R0) ); HWREG(SYSCTL_BASE + 0x51C) = lnTemp; while ((HWREG(SYSCTL_BASE + 0xA1C) & SYSCTL_PRSSI_R0) == 0); SPI_init(); SPI_Params_init(¶ms); params.dataSize = 16; params.mode = SPI_SLAVE; params.transferMode = SPI_MODE_CALLBACK; params.bitRate = 10000000; params.frameFormat = SPI_POL1_PHA1; params.transferCallbackFxn = UserCallbackFxn; spiHandles[TM4C129X_SPI0] = SPI_open(TM4C129X_SPI0, ¶ms); if (spiHandles[TM4C129X_SPI0] == NULL) { System_abort("Error initializing SPI\n"); } else { System_printf("SPI 0 initialized\n"); } MAP_GPIOPinTypeSSI(SSI_CS_GPIO_BASE, SSI_CS); IntDisable(SSI_MODULE_INT); SSIDisable(SSI_MODULE_BASE); SSIConfigSetExpClk(SSI_MODULE_BASE, 120000000 /* SysCtlClockGet() */, SSI_FRF_MOTO_MODE_1, SSI_MODE_SLAVE_OD, 6250000, 16); IntEnable(SSI_MODULE_INT); SSIDMAEnable(SSI_MODULE_BASE, SSI_DMA_RX); SSIEnable(SSI_MODULE_BASE); initDMA_control_table(); SPI_Master = FALSE; // Set a global variable to indicate that SPI slave inialization is complete. /* SPI initialization is done. */ } /* This is my slave task. */ void SPI_slave_t(void) { /* Sleep till SPI is configured as Master */ while(SPI_Master == TRUE) { Task_sleep(100); } while (1) { /* Doing a dummy write to clear SSI data register.*/ transferOK = SPI_transfer(spiHandles[TM4C129X_SPI0], &slaveTransaction); dummyWrite++; /* Wait for data from DMA. */ Semaphore_pend(SEM_dma_data, BIOS_WAIT_FOREVER); /* Process the data. */ } } SPI_Callback UserCallbackFxn(SPI_Handle handle, SPI_Transaction * transaction) { callbackCount++; /* I have a brekpoint at below printf statement, Immediately after initiating transfer from MASTER, control comes to this statment and stops. */ System_printf("I am at %s\n", __FUNCTION__); /* If I enable this SSI0_dma_int(), system crashes. */ SSI0_dma_int(); return 0; } /* Function to configure the ping pong mode and initiate DMA transfer. */ #define DAQ_BUFFER_PAGES 2 #define DAQ_BUFFER_PAGE_SZ_WORDS 160 UWORD DMABuffer[BUFFER_PAGES][BUFFER_PAGE_SZ_WORDS]; void SSI0_dma_int(void) { ULONG ulMode; #define BUFFER_PAGE_SZ_WORDS 160 //check primary channel ulMode = MAP_uDMAChannelModeGet(UDMA_CHANNEL_SSI0RX | UDMA_PRI_SELECT); if(ulMode == UDMA_MODE_STOP) { // Swap active and background pages ActivePage = 1; BgPage = 0; MAP_uDMAChannelTransferSet(UDMA_CHANNEL_SSI0RX | UDMA_PRI_SELECT, UDMA_MODE_PINGPONG, (void *)(SSI0_BASE + SSI_O_DR), &DMABuffer[0][0], BUFFER_PAGE_SZ_WORDS); MAP_uDMAChannelEnable(UDMA_CHANNEL_SSI0RX); DMAtransferCount++; } //check alt channel ulMode = MAP_uDMAChannelModeGet(UDMA_CHANNEL_SSI0RX | UDMA_ALT_SELECT); if(ulMode == UDMA_MODE_STOP) { // Swap active and background pages ActivePage = 0; BgPage = 1; MAP_uDMAChannelTransferSet(UDMA_CHANNEL_SSI0RX | UDMA_ALT_SELECT, UDMA_MODE_PINGPONG, (void *)(SSI0_BASE + SSI_O_DR), &DMABuffer[1][0], BUFFER_PAGE_SZ_WORDS); MAP_uDMAChannelEnable(UDMA_CHANNEL_SSI0RX); DMAtransferCount++; } Semaphore_post(SEM_dma_data); } void initDMA_control_table(void) { ULONG lnTemp; debug_count++; MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA); uDMAEnable(); MAP_uDMAControlBaseSet(&ucControlTable[0]); MAP_uDMAChannelAttributeDisable(UDMA_CHANNEL_SSI0RX, UDMA_ATTR_USEBURST | UDMA_ATTR_REQMASK ); MAP_uDMAChannelAttributeDisable(UDMA_CHANNEL_SSI0RX, UDMA_ATTR_ALTSELECT | UDMA_ATTR_USEBURST | UDMA_ATTR_REQMASK ); MAP_uDMAChannelAttributeEnable(UDMA_CHANNEL_SSI0RX, UDMA_ATTR_HIGH_PRIORITY); //MAP_uDMAChannelAttributeEnable(UDMA_CHANNEL_SSI0RX, UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_ALTSELECT); // Primary Channel MAP_uDMAChannelControlSet(UDMA_CHANNEL_SSI0RX | UDMA_PRI_SELECT, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_8); MAP_uDMAChannelTransferSet(UDMA_CHANNEL_SSI0RX | UDMA_PRI_SELECT, UDMA_MODE_PINGPONG, (void *)(SSI0_BASE + SSI_O_DR), &DMABuffer[0][0], DAQ_BUFFER_PAGE_SZ_WORDS); // Alternate Channel MAP_uDMAChannelControlSet(UDMA_CHANNEL_SSI0RX | UDMA_ALT_SELECT, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_8); MAP_uDMAChannelTransferSet(UDMA_CHANNEL_SSI0RX | UDMA_ALT_SELECT, UDMA_MODE_PINGPONG, (void *)(SSI0_BASE + SSI_O_DR), &DMABuffer[1][0], DAQ_BUFFER_PAGE_SZ_WORDS); MAP_uDMAChannelEnable(UDMA_CHANNEL_SSI0RX); } void SSI0_dma_int(void) { ULONG ulMode; MAIL_BOX_t dmaInfo; if( ActivePage == 0) { //check alt channel ulMode = MAP_uDMAChannelModeGet(UDMA_CHANNEL_SSI0RX | UDMA_ALT_SELECT); if(ulMode == UDMA_MODE_STOP) { // Swap active and background pages ActivePage = 1; alternateBufferCounter++; MAP_uDMAChannelTransferSet(UDMA_CHANNEL_SSI0RX | UDMA_ALT_SELECT, UDMA_MODE_PINGPONG, (void *)(SSI0_BASE + SSI_O_DR), &DMABuffer[1][0], DAQ_BUFFER_PAGE_SZ_WORDS); MAP_uDMAChannelEnable(UDMA_CHANNEL_SSI0RX); dmaInfo.bufferNumber = 1; } } else if(ActivePage == 1) { //check primary channel ulMode = MAP_uDMAChannelModeGet(UDMA_CHANNEL_SSI0RX | UDMA_PRI_SELECT); if(ulMode == UDMA_MODE_STOP) { // Swap active and background pages ActivePage = 0; primaryBufferCounter++; MAP_uDMAChannelTransferSet(UDMA_CHANNEL_SSI0RX | UDMA_PRI_SELECT, UDMA_MODE_PINGPONG, (void *)(SSI0_BASE + SSI_O_DR), &DMABuffer[0][0], DAQ_BUFFER_PAGE_SZ_WORDS); MAP_uDMAChannelEnable(UDMA_CHANNEL_SSI0RX); } dmaInfo.bufferNumber = 0; } Mailbox_post(Mailbox_weld_daq, &dmaInfo, BIOS_NO_WAIT); }
Srinivasa
Is this using the TI-RTOS SPI driver or are you using driverlib directly? What device are you using? On Tiva devices, TI-RTOS has a spi loopback example that you can refer to. If you are using driverlib, TivaWare probably has some SPI examples.
My code uses uses driverlib directly.
Part number used: TIVA TM4C129ENCPDT
TI-RTOS Version: 1_21_00_09.
SSI examples provided in driverlib does not use DMA. I am having problem with SSI with DMA in PING-Pong mode.
Analysis methodology:
After a short run in debug mode, we are stopping the debugger and monitoring the DMABuffer. Comparing received data with the pattern of data that we are supposed to receive we are noticing some missing data in DMABuffer. To ensure that no other task is modifying this buffer we have commented the other parts of code where this buffer is read but still the same behavior and below details are also good.
Regards
Srinivasa
Hi Amit,
TI-RTOS Version: 1_21_00_09.
Tivaware: TivaWare_C_Series-2.0.1.11577a
I haven't tried with TivaWare only without RTOS.
Regards
Srinivasa