Hello everybody,
I'm trying to setup a DMA from the SDFM to a high-speed SPI interface in order to transfer all captured data samples over a connected FTDI cable with MPSSE to a PC. In my opinion the DMA is probably not well configured but I'm not familiar in debugging this mechanism. The SDFM is already working in the system, and the SPI and DMA are newly implemented. On the uC I have connected the SPI signals to a scope in order to visualize if some data is coming out of the processor. The configuration sequence is as follows:
1. Configure corresponding GPIOs of SDFM and SPI, e.g. SPI SIMO signal.
GPIO_setDirectionMode (SPI_SIMO_PIN, GPIO_DIR_MODE_OUT);
GPIO_setMasterCore(SPI_SIMO_PIN, GPIO_CORE_CPU1);
GPIO_setPadConfig (SPI_SIMO_PIN, GPIO_PIN_TYPE_PULLUP);
GPIO_setQualificationMode(SPI_SIMO_PIN, GPIO_QUAL_ASYNC);
GPIO_setPinConfig (GPIO_58_SPISIMOA);
2. Initialize SDFM module.
// Reset SDFM1 module
SysCtl_resetPeripheral (SYSCTL_PERIPH_RES_SD1);
// Configure and enable interrupts
Interrupt_clearACKGroup (INTERRUPT_ACK_GROUP5);
Interrupt_enable (INT_SD1);
// Input Control Unit
SDFM_setupModulatorClock (SDFM1_BASE, SDFM_FILTER_1,
SDFM_MODULATOR_CLK_EQUAL_DATA_RATE);
SDFM_setupModulatorClock (SDFM1_BASE, SDFM_FILTER_2,
SDFM_MODULATOR_CLK_EQUAL_DATA_RATE);
// Data Filter Unit
SDFM_configDataFilter (SDFM1_BASE,
(SDFM_FILTER_1 | SDFM_FILTER_SINC_3 | SDFM_SET_OSR(200)),
(SDFM_DATA_FORMAT_16_BIT | SDFM_FILTER_ENABLE | SDFM_SHIFT_VALUE(0x0008)));
SDFM_configDataFilter (SDFM1_BASE,
(SDFM_FILTER_2 | SDFM_FILTER_SINC_3 | SDFM_SET_OSR(200)),
(SDFM_DATA_FORMAT_16_BIT | SDFM_FILTER_ENABLE | SDFM_SHIFT_VALUE(0x0008)));
// Enable Master filter bit
SDFM_enableMasterFilter (SDFM1_BASE);
// Disable external resets
SDFM_disableExternalReset (SDFM1_BASE, SDFM_FILTER_1);
SDFM_disableExternalReset (SDFM1_BASE, SDFM_FILTER_2);
// Enable interrupts
SDFM_enableInterrupt (SDFM1_BASE, SDFM_FILTER_1,
SDFM_DATA_FILTER_ACKNOWLEDGE_INTERRUPT);
SDFM_enableInterrupt (SDFM1_BASE, SDFM_FILTER_2,
SDFM_DATA_FILTER_ACKNOWLEDGE_INTERRUPT);
SDFM_disableInterrupt (SDFM1_BASE, SDFM_FILTER_1,
(SDFM_HIGH_LEVEL_THRESHOLD_INTERRUPT |
SDFM_LOW_LEVEL_THRESHOLD_INTERRUPT |
SDFM_MODULATOR_FAILURE_INTERRUPT));
SDFM_disableInterrupt (SDFM1_BASE, SDFM_FILTER_2,
(SDFM_HIGH_LEVEL_THRESHOLD_INTERRUPT |
SDFM_LOW_LEVEL_THRESHOLD_INTERRUPT |
SDFM_MODULATOR_FAILURE_INTERRUPT));
// Enable master interrupt so that any of the filter interrupts can trigger
// by SDFM interrupt to CPU
SDFM_enableMasterInterrupt (SDFM1_BASE);
3. Initialize interrupts for DMA module.
// Configure and enable interrupts
Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP7);
Interrupt_register(INT_DMA_CH6, &dmaCh6ISR);
Interrupt_enable(INT_DMA_CH6);
// Initialize DMA controller
DMA_initController();
DMA_setEmulationMode(DMA_EMULATION_FREE_RUN);
4. Initialize SPI module
// Reset SPI module
SysCtl_resetPeripheral(SYSCTL_PERIPH_RES_SPIA);
// Configure and enable interrupts
Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP6);
Interrupt_register(INT_SPIA_TX, &spiTxISR);
Interrupt_enable(INT_SPIA_TX);
// Must disable SPI module before configuring it
SPI_disableModule(SPIA_BASE);
// Hardware configuration
SPI_setConfig(SPIA_BASE, (uint32_t) DEVICE_LSPCLK_FREQ,
SPI_PROT_POL0PHA0, SPI_MODE_MASTER,
(uint32_t) SPI_BAUD_RATE, (uint16_t) SPI_WORD_WIDTH);
SPI_enableHighSpeedMode(SPIA_BASE);
SPI_setEmulationMode(SPIA_BASE, SPI_EMULATION_FREE_RUN);
SPI_disableTriWire(SPIA_BASE);
SPI_disableLoopback(SPIA_BASE);
// FIFO and interrupt configuration
SPI_enableFIFO(SPIA_BASE);
SPI_resetTxFIFO(SPIA_BASE);
SPI_resetRxFIFO(SPIA_BASE);
SPI_setFIFOInterruptLevel(SPIA_BASE, SPI_TX_FIFO_INTLEV, SPI_FIFO_RXDEFAULT);
SPI_clearInterruptStatus(SPIA_BASE, SPI_INT_TXFF);
SPI_enableInterrupt(SPIA_BASE, SPI_INT_TXFF);
SPI_disableInterrupt(SPIA_BASE, SPI_INT_RXFF);
// Enable SPI module
SPI_enableModule(SPIA_BASE);
After these steps the uC enters the infinite loop where a command parser is running. Over a terminal program from the PC I can set the number of samples and the SDFM channel to be captured. After that a separate command is used to trigger the function hsdlStart(void) to parameterize the DMA channel, start the transfer and wait until finished. And here it stucks since the job never gets done! The code of the mentioned is as follows:
#define SPI_BAUD_RATE (DEVICE_LSPCLK_FREQ / 4) #define SPI_WORD_WIDTH 16 #define SPI_TX_FIFO_INTLEV SPI_FIFO_TX4
void hsdlStart (void)
{
uint16_t dmaBurstSize;
uint32_t dmaTransferSize;
const void *srcAddr;
const void *destAddr;
// Ensure that DMA is connected to bridge of Peripheral Frame 1 and 2
EALLOW;
HWREG(CPUSYS_BASE + SYS_SECMSEL) = 0x5;
EDIS;
// Calculate DMA burst and transfer size
dmaBurstSize = 16 - SPI_TX_FIFO_INTLEV;
dmaTransferSize = hsdlParams.nSamples / SPI_TX_FIFO_INTLEV;
// Set DMA burst and transfer size
DMA_configBurst(DMA_CH6_BASE,dmaBurstSize,1,1);
DMA_configTransfer(DMA_CH6_BASE,dmaTransferSize,1,1);
// Set pointer to destination address
destAddr = (const void *)(SPIA_BASE + SPI_O_TXBUF);
// Configure DMA channel 6
if (hsdlParams.dataSel == 0)
{
// Set pointer to source address
srcAddr = (const void *)(SDFM1_BASE + SDFM_O_SDDATA1 + 0x1U); // +1 to set pointer to lower 16 bits
// Configure DMA mode
DMA_configMode(DMA_CH6_BASE,DMA_TRIGGER_SDFM1FLT1,
DMA_CFG_ONESHOT_ENABLE | DMA_CFG_CONTINUOUS_ENABLE | DMA_CFG_SIZE_16BIT);
}
else if (hsdlParams.dataSel == 1)
{
// Set pointer to source address
srcAddr = (const void *)(SDFM1_BASE + SDFM_O_SDDATA2 + 0x1U); // +1 to set pointer to lower 16 bits
// Configure DMA mode
DMA_configMode(DMA_CH6_BASE,DMA_TRIGGER_SDFM1FLT2,
DMA_CFG_ONESHOT_ENABLE | DMA_CFG_CONTINUOUS_ENABLE | DMA_CFG_SIZE_16BIT);
}
DMA_configAddresses(DMA_CH6_BASE,destAddr,srcAddr);
DMA_setInterruptMode(DMA_CH6_BASE,DMA_INT_AT_END);
DMA_enableTrigger(DMA_CH6_BASE);
DMA_enableInterrupt(DMA_CH6_BASE);
// Start DMA channel 6
DMA_startChannel(DMA_CH6_BASE);
DMA_forceTrigger(DMA_CH6_BASE);
// Show debug output and LED that HSDL transfer has started
printf ("*** HSDL transfer started ***\n");
GPIO_writePin (GPIO_PIN_STATUS_LED_3, 0);
// Enable flag to indicate that HSDL transfer is started
// --> disabled in "__interrupt void dmaCh6ISR(void)"
hsdlParams.running = 1;
// Wait until HSDL transfer is finished
while (hsdlParams.running == 1) { }
// Show debug output and LED that HSDL transfer has completed
printf ("*** HSDL transfer completed ***\n");
GPIO_writePin (GPIO_PIN_STATUS_LED_3, 1);
// Ensure that CLA is connected to bridge of Peripheral Frame 1 and 2
EALLOW;
HWREG(CPUSYS_BASE + SYS_SECMSEL) = 0x0;
EDIS;
}
__interrupt void dmaCh6ISR(void)
{
// Stop DMA channel 6
DMA_stopChannel(DMA_CH6_BASE);
// Disable flag to indicate that HSDL transfer is completed
hsdlParams.running = 0;
// Acknowledge this interrupt to receive more interrupts from group 7
Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP7);
}
__interrupt void spiTxISR(void)
{
// Clear interrupt flag
SPI_clearInterruptStatus(SPIA_BASE, SPI_INT_TXFF);
// Acknowledge this interrupt to receive more interrupts from group 6
Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP6);
}
When debugging the code it never gets out of the while loop in hsdlStart(), so I guess it has something to do with not properly configured interrupts because the ISRs are never entered. It would be great if anyone has an idea what's going wrong in my setup.
Best regards
Steffen