i have a io pin that iset to trigger dma transfer from spi5. i would like to enable that when a set of descriptors is full/complete, some "things" happen, and then reset/re-enable that the tirgger again, initiates dma transfers. the first time through the linked descriptors, data is filled into the destination locations correctly. on the final descriptor i have set the interrupt A for the channel, and the clear trigger bit. in the dma interrupt service routine, i would like to issue a sync request to the attached peripheral, and then resume dma transfers. But, as soon as i get into the ISR, the spi channel associated falls idle.
flexcomm 5 is the associated spi channel, although dma is only configured for receiving (dma channel 10).
i started with the spi_polling_b2b _transfer_master, and have referred to different dma examples from the sdk, but there are no dma examples that use hw triggering.
thank you
Here is my code:
#define EXAMPLE_SPI_MASTER SPI5
#define EXAMPLE_SPI_MASTER_IRQ FLEXCOMM5_IRQn
#define EXAMPLE_SPI_MASTER_CLK_SRC kCLOCK_Flexcomm5
#define EXAMPLE_SPI_MASTER_CLK_FREQ CLOCK_GetFlexCommClkFreq(5)
#define EXAMPLE_SPI_SSEL 0
#define EXAMPLE_SPI_SPOL kSPI_SpolActiveAllLow
#define DMA_RX_CHANNEL 10
#define PERIPHERAL_DEVICE 1
/*******************************************************************************
* Prototypes
******************************************************************************/
void PIN_INT0_DriverIRQHandler( void );
void DMA0_DriverIRQHandler( void );
/*******************************************************************************
* Variables
******************************************************************************/
uint32_t storage[100];
static uint8_t srcBuff[1];
#define BUFFER_SIZE ( 0x3FF )
static uint8_t destBuff0[BUFFER_SIZE];
static uint8_t destBuff1[BUFFER_SIZE];
static uint8_t destBuff2[BUFFER_SIZE];
static uint8_t destBuff3[BUFFER_SIZE];
static uint8_t destBuff4[BUFFER_SIZE];
static uint8_t destBuff5[BUFFER_SIZE];
uint32_t buff0_fill_count;
uint32_t buff1_fill_count;
#pragma data_alignment = 16
static dma_descriptor_t next_descr_table[6];
dma_handle_t dma_rx_handle;
/*******************************************************************************
* Code
******************************************************************************/
int main( void )
{
spi_master_config_t userConfig = {0};
uint32_t srcFreq = 0;
uint32_t i = 0;
uint32_t err = 0;
spi_transfer_t xfer = {0};
dma_channel_trigger_t dma_ch_trigger;
/* attach 12 MHz clock to SPI9 */
CLOCK_AttachClk(kFRO12M_to_FLEXCOMM5);
/* reset FLEXCOMM for SPI */
RESET_PeripheralReset(kFC5_RST_SHIFT_RSTn);
BOARD_InitPins();
BOARD_BootClockRUN();
buff0_fill_count=0;
/* SPI Master Default Config:
* userConfig.enableLoopback = false;
* userConfig.enableMaster = true;
* userConfig.polarity = kSPI_ClockPolarityActiveHigh;
* userConfig.phase = kSPI_ClockPhaseFirstEdge;
* userConfig.direction = kSPI_MsbFirst;
* userConfig.baudRate_Bps = 500000U;
*/
SPI_MasterGetDefaultConfig(&userConfig);
srcFreq = CLOCK_GetAudioPllOutFreq();
userConfig.sselNum = (spi_ssel_t)EXAMPLE_SPI_SSEL;
userConfig.sselPol = (spi_spol_t)EXAMPLE_SPI_SPOL;
userConfig.baudRate_Bps = srcFreq/16; // 13.5/16 = 843.75kHz
SPI_MasterInit(EXAMPLE_SPI_MASTER, &userConfig, srcFreq);
/* Init Buffer*/
for (i = 0; i < BUFFER_SIZE; i++)
{
srcBuff[i] = i;
}
DMA_Init( DMA0 );
dma_ch_trigger.type = kDMA_RisingEdgeTrigger;
// dma_ch_trigger.burst = kDMA_BurstSize16;
dma_ch_trigger.burst = kDMA_BurstSize1;
dma_ch_trigger.wrap = kDMA_NoWrap;
DMA_SetChannelConfig( DMA0, DMA_RX_CHANNEL, &dma_ch_trigger, PERIPHERAL_DEVICE );
//#define DMA_CHANNEL_XFER(reload, clrTrig, intA, intB, width, srcInc, dstInc, bytes)
DMA_SetupDescriptor( &next_descr_table[0], DMA_CHANNEL_XFER( 1, 0, 0, 0, 1, 0, 1, BUFFER_SIZE ),
(void *)&(SPI5->FIFORD), &destBuff0, &next_descr_table[1] );
DMA_SetupDescriptor( &next_descr_table[1], DMA_CHANNEL_XFER( 1, 0, 0, 0, 1, 0, 1, BUFFER_SIZE ),
(void *)&(SPI5->FIFORD), &destBuff1, &next_descr_table[2] );
DMA_SetupDescriptor( &next_descr_table[2], DMA_CHANNEL_XFER( 1, 0, 0, 0, 1, 0, 1, BUFFER_SIZE ),
(void *)&(SPI5->FIFORD), &destBuff2, &next_descr_table[3] );
DMA_SetupDescriptor( &next_descr_table[3], DMA_CHANNEL_XFER( 1, 0, 0, 0, 1, 0, 1, BUFFER_SIZE ),
(void *)&(SPI5->FIFORD), &destBuff3, &next_descr_table[4] );
DMA_SetupDescriptor( &next_descr_table[4], DMA_CHANNEL_XFER( 1, 0, 0, 0, 1, 0, 1, BUFFER_SIZE ),
(void *)&(SPI5->FIFORD), &destBuff4, &next_descr_table[5] );
DMA_SetupDescriptor( &next_descr_table[5], DMA_CHANNEL_XFER( 1, 1, 1, 0, 1, 0, 1, BUFFER_SIZE ),
(void *)&(SPI5->FIFORD), &destBuff5, &next_descr_table[0] );
dma_rx_handle.base = DMA0;
dma_rx_handle.channel = DMA_RX_CHANNEL;
DMA_SubmitChannelTransferParameter( &dma_rx_handle, DMA_CHANNEL_XFER( 1, 0, 0, 0, 1, 0, 1, BUFFER_SIZE ),
(void *)&(SPI5->FIFORD), &destBuff0, &next_descr_table[1] );
/* set up drdy pin for triggering dma xfer */
CLOCK_EnableClock( kMUX_RST_SHIFT_RSTn );
CLOCK_EnableClock( kCLOCK_Pint );
INPUTMUX->PINTSEL[0] = 1; // PIN INT 0 for port 0, pin 1 as pin int
RESET_PeripheralReset(kPINT_RST_SHIFT_RSTn);
PINT_PinInterruptConfig( PINT, kPINT_PinInt0, kPINT_PinIntEnableRiseEdge, NULL );
NVIC_ClearPendingIRQ( PIN_INT0_IRQn );
PINT->IST = 1;
// channel 10 receive to use pin interrupt 0
INPUTMUX->DMA_ITRIG_INMUX[DMA_RX_CHANNEL] = 4;
// sync adc channels - assert output (active low)
GPIO->CLR[4] = (1 << 25);
/*Start Transfer*/
xfer.txData = srcBuff;
xfer.dataSize = sizeof(srcBuff);
xfer.configFlags = kSPI_FrameAssert;
SPI_EnableRxDMA( SPI5, 1 ); // 1 FOR ENABLE DMA REQUEST
// " output (active low) - sync adc channels
GPIO->SET[4] = (1 << 25); // return sync to not active state
DMA_EnableChannelInterrupts( DMA0, DMA_RX_CHANNEL );
// DMA_StartTransfer( &dma_rx_handle );
DMA_EnableChannel( DMA0, DMA_RX_CHANNEL );
NVIC_EnableIRQ( DMA0_IRQn );
while (1)
{
uint32_t spi_cfg_flags;
spi_cfg_flags = 0x07010000;
SPI_WriteData( SPI5, (uint16_t)i, spi_cfg_flags );
}
}
void PIN_INT0_DriverIRQHandler( void )
{
buff1_fill_count++;
// DMA_StartTransfer( &dma_rx_handle );
// NVIC_DisableIRQ( PIN_INT0_IRQn );
NVIC_ClearPendingIRQ( PIN_INT0_IRQn );
}
void DMA0_DriverIRQHandler( void )
{
// // sync adc channels - assert output (active low)
// GPIO->CLR[4] = (1 << 25);
// DMA_DisableChannel( DMA0, DMA_RX_CHANNEL );
buff0_fill_count++;
/* Clear INTA flag */
DMA_COMMON_REG_SET( DMA0, DMA_RX_CHANNEL, INTA, (1UL << DMA_RX_CHANNEL));
NVIC_ClearPendingIRQ( DMA0_IRQn );
// " output (active low) - sync adc channels
// GPIO->SET[4] = (1 << 25); // return sync to not active state
}