Hi all!
I try to read data from the epi interface via DMA. Writing data to the interface works fine, but reading dosen't.
I don't get any EPI interrupts and I can't see anything with my oscilloscope on the RDn pin. Here is my configuration:
Thanks for your help.
Regards Michael
//Interrupt Handler//////////////////////////////////////////////////////////////7
void EpiIntHandler(void) { uint32_t intStatus = uDMAIntStatus(); uint32_t channelModeTX = uDMAChannelModeGet(UDMA_SEC_CHANNEL_EPI0TX); uint32_t channelModeRX = uDMAChannelModeGet(UDMA_SEC_CHANNEL_EPI0RX); if ((intStatus & UDMA_DEF_TMR1B_SEC_EPI0TX) && (channelModeTX == UDMA_MODE_STOP)) { } if ((intStatus & UDMA_DEF_TMR1A_SEC_EPI0RX) && (channelModeRX == UDMA_MODE_STOP)) { } }
int main(){ SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ); initEpi(); initDma(); memset(buffer, 0xAA, 256); IntMasterEnable(); while(1) { read(buffer, 256);
//write(buffer, 256); //works fine } return 0;}
void initEpi(){ SysCtlPeripheralEnable(SYSCTL_PERIPH_EPI0); SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_EPI0); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOH); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOJ); GPIOPinConfigure(GPIO_PH3_EPI0S0); //D0 GPIOPinConfigure(GPIO_PH2_EPI0S1); //D1 GPIOPinConfigure(GPIO_PC4_EPI0S2); //D2 GPIOPinConfigure(GPIO_PC5_EPI0S3); //D3 GPIOPinConfigure(GPIO_PC6_EPI0S4); //D4 GPIOPinConfigure(GPIO_PC7_EPI0S5); //D5 GPIOPinConfigure(GPIO_PH0_EPI0S6); //D6 GPIOPinConfigure(GPIO_PH1_EPI0S7); //D7 GPIOPinConfigure(GPIO_PH6_EPI0S26); //FIFO-Empty GPIOPinConfigure(GPIO_PH7_EPI0S27); //FIFO-Full GPIOPinConfigure(GPIO_PJ4_EPI0S28); //RDn GPIOPinConfigure(GPIO_PJ5_EPI0S29); //WRn GPIOPinTypeEPI(GPIO_PORTC_BASE, GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7); GPIOPinTypeEPI(GPIO_PORTH_BASE, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_6 | GPIO_PIN_7); GPIOPinTypeEPI(GPIO_PORTJ_BASE, GPIO_PIN_4 | GPIO_PIN_5); EPIModeSet(EPI0_BASE, EPI_MODE_HB8); EPIConfigHB8Set(EPI0_BASE, EPI_HB8_MODE_FIFO, 0); EPIAddressMapSet(EPI0_BASE, EPI_ADDR_PER_BASE_C | EPI_ADDR_PER_SIZE_256B); EPIFIFOConfig(EPI0_BASE, EPI_FIFO_CONFIG_TX_EMPTY | EPI_FIFO_CONFIG_RX_1_4); EPIDividerSet(EPI0_BASE, 1); IntEnable(INT_EPI0);}
void initDma(){ SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA); SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_UDMA); IntEnable(INT_UDMAERR); uDMAEnable(); IntEnable(INT_UDMA); uDMAControlBaseSet(dmaControlTable); uDMAChannelSelectSecondary(/*UDMA_DEF_TMR1B_SEC_EPI0TX |*/ UDMA_DEF_TMR1A_SEC_EPI0RX); uDMAChannelAttributeDisable(UDMA_SEC_CHANNEL_EPI0TX, UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK); uDMAChannelAttributeDisable(UDMA_SEC_CHANNEL_EPI0RX, UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK); uDMAChannelAttributeEnable(UDMA_SEC_CHANNEL_EPI0TX, UDMA_ATTR_USEBURST); uDMAChannelAttributeEnable(UDMA_SEC_CHANNEL_EPI0RX, UDMA_ATTR_USEBURST); uDMAChannelControlSet(UDMA_SEC_CHANNEL_EPI0TX | UDMA_PRI_SELECT, UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE | UDMA_ARB_4); uDMAChannelControlSet(UDMA_SEC_CHANNEL_EPI0RX | UDMA_PRI_SELECT, UDMA_SIZE_8 | UDMA_SRC_INC_NONE | UDMA_DST_INC_8 | UDMA_ARB_4);}
void write(uint8_t* buffer, uint32_t size){ if (size > 0) { uDMAChannelTransferSet(UDMA_SEC_CHANNEL_EPI0TX, UDMA_MODE_BASIC, (void*) buffer, (void*) 0xC0000000, size); uDMAChannelEnable(UDMA_SEC_CHANNEL_EPI0TX); }}void read(uint8_t* buffer, uint32_t size){ if (size > 0) { uDMAChannelTransferSet(UDMA_SEC_CHANNEL_EPI0RX, UDMA_MODE_BASIC, (void*) 0xC0000000, (void*) buffer, size); uDMAChannelEnable(UDMA_SEC_CHANNEL_EPI0RX); }}
Hello Michael Hamal,
I don't see anything obviously wrong in your code. Some additional information might help me offer suggestions.
- What is connected to the EPI?
- You indicate the RDn pin state is not changing. Is it high or low on the scope?
Hi Mitch,
thank you for your fast reply. Here is the requested information.
RDn pin is HIGH, WRn pin is LOW, I pulled both FIFO pins (FEMPTY and FFULL) down to GND. Normally I there is a FPGA connected to the micro via EPI, but for my tests, I use the DK-LM3S9B96 eval board without any device at EPI, except FEMPTY and FFULL as mentioned before.
Regards
Michael
Here is the code withou DMA:
int main(){ SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);
initEpi(); initDma();
memset(buffer, 0xAA, 256);
IntMasterEnable();
EPINonBlockingReadConfigure(EPI0_BASE, 1, 4, 0xC0000000);
while(true) { //read(buffer, 256); EPINonBlockingReadStart(EPI0_BASE, 0, 4); uint32_t currentReadSize = EPINonBlockingReadGet8(EPI0_BASE, 4, buffer);
}
return 0;}
Hello Michael,
I took your non-DMA version and adjusted a few things (using a single EPI channel for instance) and took a look with a logic analyzer. It's definitely toggling RDn in this situation. I will also start testing your DMA version and let you know what I see.
The modified non-DMA code:
unsigned char g_pucBuffer[1024];
intmain(void){ unsigned long ulReadSize; unsigned long ulLoopCount; // // Set the clocking to run directly from the crystal. // ROM_SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ); // // Set the device pinout appropriately for this board. // PinoutSet(); // // Setup the UART0 console. // Enable the (non-GPIO) peripherals used by this example. PinoutSet() // already enabled GPIO Port A. // ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0); GPIOPinConfigure(GPIO_PA0_U0RX); GPIOPinConfigure(GPIO_PA1_U0TX); GPIOPinTypeUART(GPIO_PORTA_BASE, (GPIO_PIN_0 | GPIO_PIN_1)); UARTStdioInit(0); UARTprintf("\n\nCustomer EPI test\n"); // // Setup EPI pins/etc. // SysCtlPeripheralEnable(SYSCTL_PERIPH_EPI0); SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_EPI0); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOH); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOJ); GPIOPinConfigure(GPIO_PH3_EPI0S0); //D0 GPIOPinConfigure(GPIO_PH2_EPI0S1); //D1 GPIOPinConfigure(GPIO_PC4_EPI0S2); //D2 GPIOPinConfigure(GPIO_PC5_EPI0S3); //D3 GPIOPinConfigure(GPIO_PC6_EPI0S4); //D4 GPIOPinConfigure(GPIO_PC7_EPI0S5); //D5 GPIOPinConfigure(GPIO_PH0_EPI0S6); //D6 GPIOPinConfigure(GPIO_PH1_EPI0S7); //D7 GPIOPinConfigure(GPIO_PH6_EPI0S26); //FIFO-Empty GPIOPinConfigure(GPIO_PH7_EPI0S27); //FIFO-Full GPIOPinConfigure(GPIO_PJ4_EPI0S28); //RDn GPIOPinConfigure(GPIO_PJ5_EPI0S29); //WRn GPIOPinTypeEPI(GPIO_PORTC_BASE, (GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7)); GPIOPinTypeEPI(GPIO_PORTH_BASE, (GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_6 | GPIO_PIN_7)); GPIOPinTypeEPI(GPIO_PORTJ_BASE, (GPIO_PIN_4 | GPIO_PIN_5)); EPIModeSet(EPI0_BASE, EPI_MODE_HB8); EPIConfigHB8Set(EPI0_BASE, EPI_HB8_MODE_FIFO, 0); EPIAddressMapSet(EPI0_BASE, (EPI_ADDR_PER_BASE_C | EPI_ADDR_PER_SIZE_256B)); EPIFIFOConfig(EPI0_BASE, (EPI_FIFO_CONFIG_TX_EMPTY | EPI_FIFO_CONFIG_RX_1_4)); EPIDividerSet(EPI0_BASE, 1); // // Setup and start EPI non-blocking reads. // EPINonBlockingReadConfigure(EPI0_BASE, 0, EPI_NBCONFIG_SIZE_8, 0x00000000); EPINonBlockingReadStart(EPI0_BASE, 0, 1024); ulReadSize = 0; ulLoopCount = 0; while(ulReadSize < 1024) { if((EPINonBlockingReadAvail(EPI0_BASE)) > 0) { ulReadSize += EPINonBlockingReadGet8(EPI0_BASE, 1024, g_pucBuffer); ulLoopCount++; } } // // Output some info and notify done. // UARTprintf(" Read %d in %d ReadGet8 calls\n", ulReadSize, ulLoopCount); UARTprintf("....done\n"); // // Spin. // while(1) { } }
Hello Mitch,
did you find out something new to the subject EPI DMA read in HB8 FIFO mode?
Hi Michael,
Sorry for the delayed response. It appears that unlike the TX side, you need to trigger the EPI read to start the FIFO fill. The DMA can then pull it from the FIFO into a buffer. I do see the RDn toggle as expected in the analyzer. To confirm, I tied DS0 to 3.3V to signal a 1 for the reads. As I would expect, the buffer fills with values of 0x01.
I made some minor changes to your code to use for testing (read(), clearing DMA IRQ, vars for info tracking). You can find it below.
void EPIIntHandler(void){ uint32_t intStatus; uint32_t channelModeTX; uint32_t channelModeRX; // // Handle any EPI error IRQ signals. // intStatus = EPIIntErrorStatus(EPI0_BASE); if(intStatus) { g_ui32EPIErrors++; } EPIIntErrorClear(EPI0_BASE, intStatus); intStatus = EPIIntStatus(EPI0_BASE, false); if(intStatus) { g_ui32EPIStatus = intStatus; } // // Get any DMA related information. Clear the IRQ. // intStatus = uDMAIntStatus(); uDMAIntClear(intStatus); channelModeTX = uDMAChannelModeGet(UDMA_SEC_CHANNEL_EPI0TX); channelModeRX = uDMAChannelModeGet(UDMA_SEC_CHANNEL_EPI0RX); if((intStatus & UDMA_DEF_TMR1B_SEC_EPI0TX) && (channelModeTX == UDMA_MODE_STOP)) { } if((intStatus & UDMA_DEF_TMR1A_SEC_EPI0RX) && (channelModeRX == UDMA_MODE_STOP)) { g_ui32RxCount++; }}void DMAErrHandler(void){ uint32_t ui32Status; ui32Status = uDMAErrorStatusGet(); if(ui32Status) { uDMAErrorStatusClear(); g_ui32DMAErrCount++; }}void initEpi(void){ SysCtlPeripheralEnable(SYSCTL_PERIPH_EPI0); SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_EPI0); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOH); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOJ); GPIOPinConfigure(GPIO_PH3_EPI0S0); //D0 GPIOPinConfigure(GPIO_PH2_EPI0S1); //D1 GPIOPinConfigure(GPIO_PC4_EPI0S2); //D2 GPIOPinConfigure(GPIO_PC5_EPI0S3); //D3 GPIOPinConfigure(GPIO_PC6_EPI0S4); //D4 GPIOPinConfigure(GPIO_PC7_EPI0S5); //D5 GPIOPinConfigure(GPIO_PH0_EPI0S6); //D6 GPIOPinConfigure(GPIO_PH1_EPI0S7); //D7 GPIOPinConfigure(GPIO_PH6_EPI0S26); //FIFO-Empty GPIOPinConfigure(GPIO_PH7_EPI0S27); //FIFO-Full GPIOPinConfigure(GPIO_PJ4_EPI0S28); //RDn GPIOPinConfigure(GPIO_PJ5_EPI0S29); //WRn GPIOPinTypeEPI(GPIO_PORTC_BASE, GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7); GPIOPinTypeEPI(GPIO_PORTH_BASE, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_6 | GPIO_PIN_7); GPIOPinTypeEPI(GPIO_PORTJ_BASE, GPIO_PIN_4 | GPIO_PIN_5); EPIModeSet(EPI0_BASE, EPI_MODE_HB8); EPIConfigHB8Set(EPI0_BASE, EPI_HB8_MODE_FIFO, 0); EPIAddressMapSet(EPI0_BASE, EPI_ADDR_PER_BASE_C | EPI_ADDR_PER_SIZE_256B); EPIFIFOConfig(EPI0_BASE, (EPI_FIFO_CONFIG_TX_EMPTY | EPI_FIFO_CONFIG_RX_1_4 | EPI_FIFO_CONFIG_RSTALLERR)); EPIDividerSet(EPI0_BASE, 1); IntEnable(INT_EPI0);}void initDma(void){ SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA); SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_UDMA); uDMAEnable(); uDMAIntClear(uDMAIntStatus()); IntEnable(INT_UDMA); IntEnable(INT_UDMAERR); uDMAControlBaseSet(dmaControlTable); uDMAChannelSelectSecondary(UDMA_DEF_TMR1B_SEC_EPI0TX | UDMA_DEF_TMR1A_SEC_EPI0RX); uDMAChannelAttributeDisable(UDMA_SEC_CHANNEL_EPI0TX, (UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK)); uDMAChannelAttributeDisable(UDMA_SEC_CHANNEL_EPI0RX, (UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK)); uDMAChannelAttributeEnable(UDMA_SEC_CHANNEL_EPI0TX, UDMA_ATTR_USEBURST); uDMAChannelAttributeEnable(UDMA_SEC_CHANNEL_EPI0RX, UDMA_ATTR_USEBURST); uDMAChannelControlSet((UDMA_SEC_CHANNEL_EPI0TX | UDMA_PRI_SELECT), (UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE | UDMA_ARB_4)); uDMAChannelControlSet((UDMA_SEC_CHANNEL_EPI0RX | UDMA_PRI_SELECT), (UDMA_SIZE_8 | UDMA_SRC_INC_NONE | UDMA_DST_INC_8 | UDMA_ARB_4));}void write(uint8_t* buffer, uint32_t size){ if(size > 0) { uDMAChannelTransferSet(UDMA_SEC_CHANNEL_EPI0TX, UDMA_MODE_BASIC, (void*) buffer, (void*) 0xC0000000, size); uDMAChannelEnable(UDMA_SEC_CHANNEL_EPI0TX); }}void read(uint8_t* buffer, uint32_t size){ if(size > 0) { uDMAChannelTransferSet(UDMA_SEC_CHANNEL_EPI0RX, UDMA_MODE_BASIC, (void*)0xC0000000, (void*) buffer, size); EPINonBlockingReadConfigure(EPI0_BASE, 0, EPI_NBCONFIG_SIZE_8, 0x00000000); EPINonBlockingReadStart(EPI0_BASE, 0, size); uDMAChannelEnable(UDMA_SEC_CHANNEL_EPI0RX); }}int main(){ uint32_t ui32Loop, ui32TempRxCount; // // Setup clocks // ROM_SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ); // // Set the device pinout appropriately for this board. // PinoutSet(); // // Setup the UART0 console. // Enable the (non-GPIO) peripherals used by this example. PinoutSet() // already enabled GPIO Port A. // ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0); GPIOPinConfigure(GPIO_PA0_U0RX); GPIOPinConfigure(GPIO_PA1_U0TX); GPIOPinTypeUART(GPIO_PORTA_BASE, (GPIO_PIN_0 | GPIO_PIN_1)); UARTStdioInit(0); UARTprintf("\n\nCustomer uDMA EPI test\n"); // // Initialize RX DMA count and error count. // g_ui32RxCount = 0; g_ui32DMAErrCount = 0; // // Set the buffer to known values. // UARTprintf("Initializing read buffer\n"); for(ui32Loop = 0; ui32Loop < 256; ui32Loop++) { g_pui8Buffer[ui32Loop] = 0xaa; } // // Initialize EPI & uDMA // UARTprintf("Initializing DMA\n"); initDma(); UARTprintf("Initializing EPI\n"); initEpi(); UARTprintf("Enabling master interrupt\n"); IntMasterEnable(); UARTprintf("Starting transfer loop\n"); ui32Loop = 0; while(1) { ui32TempRxCount = g_ui32RxCount; read(g_pui8Buffer, 256); // // Wait for the DMA to complete // while(g_ui32RxCount <= ui32TempRxCount) { if(g_ui32DMAErrCount) { UARTprintf("DMA error count = %d\n", g_ui32DMAErrCount); } if(g_ui32EPIErrors) { UARTprintf("EPI error count = %d\n", g_ui32EPIErrors); } } ui32Loop++; //write(buffer, 256); //works fine // // Arbitrary count selected. Halt the loop and output some data. // if(ui32Loop > 2000) { UARTprintf("Halting loop.\n"); UARTprintf("DMA RX transfer count = %d\n", g_ui32RxCount); UARTprintf("buffer contents: \n0000:"); for(ui32Loop = 1; ui32Loop <= 256; ui32Loop++) { UARTprintf("0x%02x ", g_pui8Buffer[ui32Loop-1]); if(!(ui32Loop % 12)) { UARTprintf("\n%04d:", (ui32Loop - 1)); } } // // Spin. // while(1) { } } }}
Thank you for your help, I can now read from EPI with DMA. Thank you again for the very good support!
Regads