This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Hello,
I'm trying to transmit multiple large buffers using uDMA Ping Pong Mode, after transmitting for example buffer 1, 2, I swap buffer 1, with buffer 3.
My question is where the triple buffering needed to be swapped, in which area exactly in the interrupts ?
/* Private Typedefs ----------------------------------------------------------*/ #pragma DATA_ALIGN(psDMAControlTable, 1024) tDMAControlTable psDMAControlTable[64]; #define EPI_DATA_SIZE 1024 #define SYSTEM_CLOCK_120M 120000000 #define EPI_PORT 0xA0000000 uint8_t testttttttttttttt = 0; int PingCount; uint16_t send_data[EPI_DATA_SIZE] = { }; uint16_t send_data2[EPI_DATA_SIZE] = { }; uint16_t send_data3[EPI_DATA_SIZE] = { }; uint32_t ui32SysClock, g_ui32EPIErrors = 0; volatile uint32_t *g_pusEPIFPGA; // Pointer for EPI memory window. uint16_t *pa; uint16_t *pb; void initEPI(void) { SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA); // SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB); // SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC); // SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOG); // SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOH); // SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOK); // SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOL); // SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOM); // SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOP); // SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOQ); // SysCtlPeripheralEnable(SYSCTL_PERIPH_EPI0); while (!SysCtlPeripheralReady(SYSCTL_PERIPH_EPI0)) //wait for it to be ready { } MAP_GPIOPinConfigure(GPIO_PK0_EPI0S0); GPIOPinTypeEPI(GPIO_PORTK_BASE, GPIO_PIN_0); //D0 MAP_GPIOPinConfigure(GPIO_PK1_EPI0S1); GPIOPinTypeEPI(GPIO_PORTK_BASE, GPIO_PIN_1); //D1 MAP_GPIOPinConfigure(GPIO_PK2_EPI0S2); GPIOPinTypeEPI(GPIO_PORTK_BASE, GPIO_PIN_2); //D2 MAP_GPIOPinConfigure(GPIO_PK3_EPI0S3); GPIOPinTypeEPI(GPIO_PORTK_BASE, GPIO_PIN_3); //D3 MAP_GPIOPinConfigure(GPIO_PC7_EPI0S4); GPIOPinTypeEPI(GPIO_PORTC_BASE, GPIO_PIN_7); //D4 MAP_GPIOPinConfigure(GPIO_PC6_EPI0S5); GPIOPinTypeEPI(GPIO_PORTC_BASE, GPIO_PIN_6); //D5 MAP_GPIOPinConfigure(GPIO_PC5_EPI0S6); GPIOPinTypeEPI(GPIO_PORTC_BASE, GPIO_PIN_5); //D6 MAP_GPIOPinConfigure(GPIO_PC4_EPI0S7); GPIOPinTypeEPI(GPIO_PORTC_BASE, GPIO_PIN_4); //D7 MAP_GPIOPinConfigure(GPIO_PA6_EPI0S8); GPIOPinTypeEPI(GPIO_PORTA_BASE, GPIO_PIN_6); //D8 MAP_GPIOPinConfigure(GPIO_PA7_EPI0S9); GPIOPinTypeEPI(GPIO_PORTA_BASE, GPIO_PIN_7); //D9 MAP_GPIOPinConfigure(GPIO_PG1_EPI0S10); GPIOPinTypeEPI(GPIO_PORTG_BASE, GPIO_PIN_1); //D10 MAP_GPIOPinConfigure(GPIO_PG0_EPI0S11); GPIOPinTypeEPI(GPIO_PORTG_BASE, GPIO_PIN_0); //D11 MAP_GPIOPinConfigure(GPIO_PM3_EPI0S12); GPIOPinTypeEPI(GPIO_PORTM_BASE, GPIO_PIN_3); //D12 MAP_GPIOPinConfigure(GPIO_PM2_EPI0S13); GPIOPinTypeEPI(GPIO_PORTM_BASE, GPIO_PIN_2); //D13 MAP_GPIOPinConfigure(GPIO_PM1_EPI0S14); GPIOPinTypeEPI(GPIO_PORTM_BASE, GPIO_PIN_1); //D14 MAP_GPIOPinConfigure(GPIO_PM0_EPI0S15); GPIOPinTypeEPI(GPIO_PORTM_BASE, GPIO_PIN_0); //D15 MAP_GPIOPinConfigure(GPIO_PL0_EPI0S16); GPIOPinTypeEPI(GPIO_PORTL_BASE, GPIO_PIN_0); //A0 MAP_GPIOPinConfigure(GPIO_PL1_EPI0S17); GPIOPinTypeEPI(GPIO_PORTL_BASE, GPIO_PIN_1); //A1 MAP_GPIOPinConfigure(GPIO_PL2_EPI0S18); GPIOPinTypeEPI(GPIO_PORTL_BASE, GPIO_PIN_2); //A2 MAP_GPIOPinConfigure(GPIO_PL3_EPI0S19); GPIOPinTypeEPI(GPIO_PORTL_BASE, GPIO_PIN_3); //A3 MAP_GPIOPinConfigure(GPIO_PQ0_EPI0S20); GPIOPinTypeEPI(GPIO_PORTQ_BASE, GPIO_PIN_0); //A4 MAP_GPIOPinConfigure(GPIO_PQ1_EPI0S21); GPIOPinTypeEPI(GPIO_PORTQ_BASE, GPIO_PIN_1); //A5 MAP_GPIOPinConfigure(GPIO_PQ2_EPI0S22); GPIOPinTypeEPI(GPIO_PORTQ_BASE, GPIO_PIN_2); //A6 MAP_GPIOPinConfigure(GPIO_PQ3_EPI0S23); GPIOPinTypeEPI(GPIO_PORTQ_BASE, GPIO_PIN_3); //A7 MAP_GPIOPinConfigure(GPIO_PK7_EPI0S24); GPIOPinTypeEPI(GPIO_PORTK_BASE, GPIO_PIN_7); //A8 MAP_GPIOPinConfigure(GPIO_PK6_EPI0S25); GPIOPinTypeEPI(GPIO_PORTK_BASE, GPIO_PIN_6); //A9 MAP_GPIOPinConfigure(GPIO_PL4_EPI0S26); GPIOPinTypeEPI(GPIO_PORTL_BASE, GPIO_PIN_4); //A10 MAP_GPIOPinConfigure(GPIO_PB2_EPI0S27); GPIOPinTypeEPI(GPIO_PORTB_BASE, GPIO_PIN_2); //A11 MAP_GPIOPinConfigure(GPIO_PB3_EPI0S28); GPIOPinTypeEPI(GPIO_PORTB_BASE, GPIO_PIN_3); //WR MAP_GPIOPinConfigure(GPIO_PP2_EPI0S29); GPIOPinTypeEPI(GPIO_PORTP_BASE, GPIO_PIN_2); //RD MAP_GPIOPinConfigure(GPIO_PP3_EPI0S30); GPIOPinTypeEPI(GPIO_PORTP_BASE, GPIO_PIN_3); //FRAME MAP_GPIOPinConfigure(GPIO_PK5_EPI0S31); GPIOPinTypeEPI(GPIO_PORTK_BASE, GPIO_PIN_5); //CLK EPIModeSet(EPI0_BASE, EPI_MODE_GENERAL); //general mode EPIDividerSet(EPI0_BASE, 5); //1=60MHz, 10=10MHz, 119=1MHz EPIConfigGPModeSet(EPI0_BASE, EPI_GPMODE_CLKPIN | //interface clock is output on a pin // EPI_GPMODE_CLKGATE | //clock is stopped when there is no transaction // EPI_GPMODE_FRAME50 | //frame 50:50 - not using frame signal // EPI_GPMODE_WRITE2CYCLE | //two cycle write - single cycle write EPI_GPMODE_ASIZE_NONE | //address bus size of 4 bits EPI_GPMODE_DSIZE_16, //data bus size of 16 bits 0, //frame 0 0); //parameter not used EPIAddressMapSet(EPI0_BASE, EPI_ADDR_PER_SIZE_256B | //only 16 needed EPI_ADDR_PER_BASE_C); //EPI0 is mapped from 0xC0000000 to 0xC00000FF. EPIFIFOConfig(EPI0_BASE, (EPI_FIFO_CONFIG_TX_1_2)); /* EPIIntDisable( EPI0_BASE, EPI_INT_RXREQ | EPI_INT_TXREQ | EPI_INT_ERR); EPIIntErrorClear(EPI0_BASE, EPI_INT_ERR_WTFULL | EPI_INT_ERR_RSTALL | EPI_INT_ERR_TIMEOUT); //setup the interrupt mask for the EPI. //Note: interrupt masking has no effect on uDMA, which // operates off the raw source of the read/write // interrupts //Note: we dont want to enable the EPI Rx and Tx interrupt, // the EPI fifos will be serviced by the uDMA EPIIntEnable( EPI0_BASE, // EPI_INT_RXREQ | // EPI_INT_TXREQ | // EPI_INT_DMA_TX_DONE | // EPI_INT_DMA_RX_DONE | EPI_INT_ERR);*/ EPIIntDisable( EPI0_BASE, EPI_INT_RXREQ | EPI_INT_TXREQ | EPI_INT_ERR); EPIIntErrorClear(EPI0_BASE, EPI_INT_ERR_WTFULL | EPI_INT_ERR_RSTALL | EPI_INT_ERR_TIMEOUT); //EPIIntEnable( EPI0_BASE // EPI_INT_RXREQ | // EPI_INT_TXREQ | //EPI_INT_DMA_TX_DONE // EPI_INT_DMA_RX_DONE | // ); EPIIntEnable( EPI0_BASE, // EPI_INT_RXREQ | //EPI_INT_TXREQ EPI_INT_DMA_TX_DONE //EPI_INT_DMA_RX_DONE // EPI_INT_ERR ); // Enable the EPI interrupt on the processor (NVIC). // Note: even if no EPI interrupt were enabled, the uDMA // controller will generate an interrupt on the EPI // interrupt signal when a uDMA transfer is complete. IntEnable(INT_EPI0); EPIIntEnable(EPI0_BASE, EPI_INT_DMA_TX_DONE); while (HWREG(EPI0_BASE + EPI_O_STAT) & EPI_STAT_INITSEQ) { } } //initEPI() void DMA_Init() { SysCtlPeripheralDisable(SYSCTL_PERIPH_UDMA); SysCtlPeripheralReset(SYSCTL_PERIPH_UDMA); SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA); uDMAEnable(); while (!(SysCtlPeripheralReady(SYSCTL_PERIPH_UDMA))) ; uDMAControlBaseSet(psDMAControlTable); //uDMAChannelAttributeDisable(UDMA_CH20_EPI0RX, UDMA_ATTR_ALL); uDMAChannelAttributeDisable(UDMA_CH21_EPI0TX, UDMA_ATTR_ALL); uDMAChannelAttributeEnable(UDMA_CH21_EPI0TX, UDMA_ATTR_USEBURST); //single request is not supported //uDMAChannelAssign(UDMA_CH20_EPI0RX); uDMAChannelAssign(UDMA_CH21_EPI0TX); uDMAChannelControlSet(UDMA_CH21_EPI0TX | UDMA_PRI_SELECT, UDMA_SIZE_16 | UDMA_SRC_INC_16 | UDMA_DST_INC_NONE | UDMA_ARB_1024); // UDMA_ARB_2 uDMAChannelControlSet(UDMA_CH21_EPI0TX | UDMA_ALT_SELECT, UDMA_SIZE_16 | UDMA_SRC_INC_16 | UDMA_DST_INC_NONE | UDMA_ARB_1024); // UDMA_ARB_2 uDMAChannelSelectSecondary(UDMA_DEF_TMR1B_SEC_EPI0TX); } void EPI_HPI_uDMA_write(uint16_t * s2,uint16_t * s1,uint32_t count) { g_pusEPIFPGA = (uint32_t*) 0xC0000000; // EPIIntEnable(EPI0_BASE, EPI_INT_DMA_TX_DONE); uDMAChannelTransferSet(UDMA_CH21_EPI0TX | UDMA_PRI_SELECT, UDMA_MODE_PINGPONG, (void*) s1, (void*) g_pusEPIFPGA, count); //UDMA_MODE_AUTO, UDMA_MODE_BASIC uDMAChannelTransferSet(UDMA_CH21_EPI0TX | UDMA_ALT_SELECT, UDMA_MODE_PINGPONG, (void*) s2, (void*) g_pusEPIFPGA, count); uDMAChannelEnable(UDMA_CH21_EPI0TX); EPIDMATxCount(EPI0_BASE, count*2); } void SwapBuffers(uint16_t ** a, uint16_t **b) { uint16_t *tmp = *a; *a = *b; *b = tmp; } int main(void) { ui32SysClock = SysCtlClockFreqSet( (SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480), SYSTEM_CLOCK_120M); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPION); while (!SysCtlPeripheralReady(SYSCTL_PERIPH_GPION)) { } GPIOPinTypeGPIOOutput(GPIO_PORTN_BASE, GPIO_PIN_0); GPIOPinTypeGPIOOutput(GPIO_PORTN_BASE, GPIO_PIN_1); DMA_Init(); initEPI(); pa = send_data; pb = send_data3; //uint16_t i =0; EPI_HPI_uDMA_write(pa,send_data2,1024); SwapBuffers(&pa, &pb); /* uint16_t data1[16] = { 0x0000 , 0x0000 , 0x0000 , 0x0000 , 0xFFFF , 0xAAAA , 0x5555 , 0x0000 , 0x0000 , 0x5555 , 0xAAAA , 0xFFFF , 0xFFFF , 0xFFFF , 0xFFFF , 0xFFFF}; //initEPI(); //uint16_t sr; //to read an fpga register... sr = EPIfpga[2]; //to write an fpga register... */ while (1) { /*while(uDMAChannelModeGet(UDMA_CH21_EPI0TX)!=UDMA_MODE_STOP); uDMAChannelTransferSet(UDMA_CH21_EPI0TX |UDMA_PRI_SELECT, UDMA_MODE_BASIC,(void*)send_data2, (void*) g_pusEPIFPGA, 1024); //UDMA_MODE_AUTO, UDMA_MODE_BASIC uDMAChannelEnable(UDMA_CH21_EPI0TX); EPIDMATxCount(EPI0_BASE, 1024); while(uDMAChannelModeGet(UDMA_CH21_EPI0TX)!=UDMA_MODE_STOP); uDMAChannelTransferSet(UDMA_CH21_EPI0TX | UDMA_ALT_SELECT, UDMA_MODE_BASIC,(void*)send_data, (void*) g_pusEPIFPGA, 1024); //UDMA_MODE_AUTO, UDMA_MODE_BASIC uDMAChannelEnable(UDMA_CH21_EPI0TX); EPIDMATxCount(EPI0_BASE, 1024);*/ if (uDMAChannelModeGet(UDMA_CH21_EPI0TX) == UDMA_MODE_STOP) { GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_1, 2); GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0, 0); EPI_HPI_uDMA_write(pa,send_data2,1024); } else if (uDMAChannelModeGet(UDMA_CH21_EPI0TX) == UDMA_MODE_PINGPONG) { GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_1, 0); GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0, 1); } } } void EPIIntHandler(void) { //IntDisable(INT_EPI0); uint32_t state = EPIIntStatus(EPI0_BASE, true); if(state & EPI_INT_ERR) EPIIntErrorClear(EPI0_BASE, EPIIntErrorStatus(EPI0_BASE)); uint32_t ui32Mode; ui32Mode = uDMAChannelModeGet(UDMA_CH21_EPI0TX | UDMA_PRI_SELECT); if(ui32Mode == UDMA_MODE_STOP) { PingCount++; } ui32Mode = uDMAChannelModeGet(UDMA_CH21_EPI0TX | UDMA_ALT_SELECT); if(ui32Mode == UDMA_MODE_STOP) { PingCount++; } if(PingCount >=2) { PingCount = 0; SwapBuffers(&pa, &pb); } switch (state) { case EPI_INT_DMA_TX_DONE: // EPIIntErrorClear(EPI0_BASE, EPI_INT_ERR_DMAWRIC); //* if(!testttttttttttttt) // { // testttttttttttttt = 1; EPI_HPI_uDMA_write(pa,send_data2,1024); // } // else // { // testttttttttttttt = 0; // EPI_HPI_uDMA_write(send_data3,send_data,1024); // } break; case EPI_INT_ERR: // EPIIntErrorClear(EPI0_BASE, EPIIntErrorStatus(EPI0_BASE)); break; default: break; } // switch () // { // case 4: // EPIIntDisable(EPI0_BASE, EPI_INT_TXREQ); // // break; // } uDMAIntClear(UDMA_CH21_EPI0TX); uDMAIntClear(UDMA_SEC_CHANNEL_EPI0TX); }
Hello Ahmed,
Within the interrupt is one possibility but it doesn't have to be inside of the interrupt. You can also set up the interrupt to track flags about the buffer state along with an application loop that simply checks for which buffer has been filled or emptied and then swaps them. It depends how quick you need the swaps executed. The interrupt would be the fastest method.
We have an example of how to use Ping Pong mode for two buffers using the ADC peripheral in TivaWare 2.2.0.
You can find it at [Install Path]\TivaWare_C_Series-2.2.0.295\examples\boards\ek-tm4c1294xl\adc_udma_pingpong - This will show you how to check for the buffer being filled in an interrupt. If you decide you want to swap within the interrupt, you just need to take the APIs used to enable the next uDMA block transfer from the application loop and use them in the ISR instead.
I don't see a reason the same logic can't be extended to three or more buffers so that should give you what you need to get the uDMA working as you intend.
Best Regards,
Ralph Jacobi
Have you got some time to review the code above please ? especially the EPI Interrupt handler, I think the flags there are incorrect.
Hello Ahmed,
We don't do comprehensive code reviews. We can look at sections that are noted to have issues as well as configurations, but not entire programs.
Regarding your interrupt code as you marked that as an area for concern, you shouldn't need to clear uDMA interrupts with uDMAIntClear. You'd want to clear the EPI interrupt instead. That should be done at the start of the ISR too.
As far as flags go I am not sure which ones you mean. I would recommend you review the example I provided and implement improvements and then if you are having specific issues you can show your updated code and explain what isn't working.
Best Regards,
Ralph Jacobi
Checking the uDMA if it's stop/finished inside the interrupt of EPI is correct or not ? that's my question...
here is the part that is suspicious to me
and what does this flag do? EPI_INT_DMA_TX_DONE
ui32Mode = uDMAChannelModeGet(UDMA_CH21_EPI0TX | UDMA_PRI_SELECT);
if(ui32Mode == UDMA_MODE_STOP)
{
PingCount++;
}
ui32Mode = uDMAChannelModeGet(UDMA_CH21_EPI0TX | UDMA_ALT_SELECT);
if(ui32Mode == UDMA_MODE_STOP)
{
PingCount++;
}
Hello Ahmed,
You can check if its stopped but the code you have is slightly wrong.
You are using UDMA_CH21_EPI0TX which is the addressing used for uDMAChannelAssign. However most of your APIs need to provide the channel number you are accessing. In TivaWare this would be UDMA_CHANNEL_TMR1B which is the define for channel 21.
You can see why this is used by looking at Table 9-1 uDMA Channel Assignments in the datasheet: https://www.ti.com/lit/ds/symlink/tm4c1294ncpdt.pdf#page=680
The EPI 0 TX channel is shared with GPTimer 1B and since only one peripheral can use a specific channel at a time, the define we provided in TivaWare is for UDMA_CHANNEL_TMR1B.
So the correct API call would be:
ui32Mode = uDMAChannelModeGet(UDMA_CHANNEL_TMR1B | UDMA_PRI_SELECT);
Looking through your code, the same issue applies to a lot of your uDMA configuration.
Please take the time to refer to our completed uDMA Ping Pong example to see how to properly configure your uDMA peripheral and how to setup the checks in the ISR. Once you have done so if you are still having issues then you can post your updated configurations and I can see if there are any missing steps.
Best Regards,
Ralph Jacobi
Oh and regarding EPI_INT_DMA_TX_DONE, that is the interrupt flag in the EPI interrupt flag register which corresponds to the uDMA TX being completed.
Best Regards,
Ralph Jacobi
Thanks for your patience.
I have reviewed the code, if you can review it:
void EPIIntHandler(void) { uint32_t intStatus; uint32_t channelModeTX; // // 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_CHANNEL_TMR1B | UDMA_PRI_SELECT); if(channelModeTX == UDMA_MODE_STOP) { } channelModeTX = uDMAChannelModeGet(UDMA_CHANNEL_TMR1B | UDMA_ALT_SELECT); if (channelModeTX == UDMA_MODE_STOP) { } }
and for DMA Init
void DMA_Init()
{
SysCtlPeripheralDisable(SYSCTL_PERIPH_UDMA);
SysCtlPeripheralReset(SYSCTL_PERIPH_UDMA);
SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA);
uDMAEnable();
while (!(SysCtlPeripheralReady(SYSCTL_PERIPH_UDMA)))
;
uDMAControlBaseSet(psDMAControlTable);
//uDMAChannelAttributeDisable(UDMA_CH20_EPI0RX, UDMA_ATTR_ALL);
uDMAChannelAttributeDisable(UDMA_CH21_EPI0TX, UDMA_ATTR_ALL);
uDMAChannelAttributeEnable(UDMA_CH21_EPI0TX, UDMA_ATTR_USEBURST); //single request is not supported
//uDMAChannelAssign(UDMA_CH20_EPI0RX);
uDMAChannelAssign(UDMA_CH21_EPI0TX);
uDMAChannelControlSet(UDMA_CH21_EPI0TX | UDMA_PRI_SELECT,
UDMA_SIZE_16 | UDMA_SRC_INC_16 | UDMA_DST_INC_NONE | UDMA_ARB_1024); // UDMA_ARB_2
uDMAChannelControlSet(UDMA_CH21_EPI0TX | UDMA_ALT_SELECT,
UDMA_SIZE_16 | UDMA_SRC_INC_16 | UDMA_DST_INC_NONE | UDMA_ARB_1024); // UDMA_ARB_2
uDMAChannelSelectSecondary(UDMA_DEF_TMR1B_SEC_EPI0TX);
}
Hello, I have followed the example, Would you tell me where is the point in code that the buffer should be swapped, assuming 3 buffers A,B,C.
Hello Ahmed,
Reviewing your code, you still have some issues with your implementation. Please reference my past comments.
You are using UDMA_CH21_EPI0TX which is the addressing used for uDMAChannelAssign. However most of your APIs need to provide the channel number you are accessing. In TivaWare this would be UDMA_CHANNEL_TMR1B which is the define for channel 21.
You can see why this is used by looking at Table 9-1 uDMA Channel Assignments in the datasheet: https://www.ti.com/lit/ds/symlink/tm4c1294ncpdt.pdf#page=680
The EPI 0 TX channel is shared with GPTimer 1B and since only one peripheral can use a specific channel at a time, the define we provided in TivaWare is for UDMA_CHANNEL_TMR1B.
So the correct API call would be:
ui32Mode = uDMAChannelModeGet(UDMA_CHANNEL_TMR1B | UDMA_PRI_SELECT);
Looking through your code, the same issue applies to a lot of your uDMA configuration.
UDMA_CH21_EPI0TX should only be used for uDMAChannelAssign.
You need to use UDMA_CHANNEL_TMR1B for the other APIs such as like this:
uDMAChannelAttributeDisable(UDMA_CHANNEL_TMR1B, UDMA_ATTR_ALL);
Would you tell me where is the point in code that the buffer should be swapped, assuming 3 buffers A,B,C.
Deciding where to handle the buffer swaps is an application specific decision, I can't really guide you on that?
Best Regards,
Ralph Jacobi