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