using the clear trigger bit in the dma xfercfg_n register

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

using the clear trigger bit in the dma xfercfg_n register

1,156 Views
eileen_radzwion
Contributor II

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

}

0 Kudos
Reply
4 Replies

1,068 Views
eileen_radzwion
Contributor II

Sorry - some more information

the io pin used for triggering transfers is tied to an external ADC's data ready pin.  This input should trigger the start of one transfer, which is 24bits/channel * number of channels.  we have 4 channels on there, and therefore, for each data ready (the dma hw trigger), we need to transfer (24bits per channel /8 bits per byte *4 channels) = 12bytes

after x-number of transfers (for example 10,000), i want to stop dma transfers, and issue a resync to the external ADC.  (this is the aforementioned "do something"). 

0 Kudos
Reply

1,068 Views
Omar_Anguiano
NXP TechSupport
NXP TechSupport

Hello Eileen Radzwion

I will appreciate if you help me providing me the part number you are working with

Best regards,

Omar

0 Kudos
Reply

1,068 Views
eileen_radzwion
Contributor II

Hello Omar,

My apologies, I am working with the LPC54608

0 Kudos
Reply

1,068 Views
Omar_Anguiano
NXP TechSupport
NXP TechSupport

Hello Eileen Radzwion

Unfortunately, there is no specific example for hardware triggering, one close approach is the lpc_adc_dma since the adc conversion is triggered externally.

 

The trigger input is selected in the DMA_ITRIG_INMUX registers. There are 20

possible internal trigger sources for each DMA channel. In addition, the DMA trigger

output can be routed to the trigger input of another channel through the trigger input

multiplexing. See Table 302 and Chapter 11 “LPC546xx Input multiplexing (INPUT MUX)” of the User Guide.

 

Hardware triggering requires setup of the HWTRIGEN, TRIGPOL, TRIGTYPE, and TRIGBURST fields in the CFG register for the related channel.

When a channel is initially set up, the SWTRIG bit in the XFERCFG

register can be set, causing the transfer to begin immediately.

Let me know if this is helpful

Best regards,

Omar

0 Kudos
Reply