Trigger DMA write with TMR CMPLD1

キャンセル
次の結果を表示 
表示  限定  | 次の代わりに検索 
もしかして: 

Trigger DMA write with TMR CMPLD1

564件の閲覧回数
aberger
Contributor V

I am trying to trigger a write to GPIO1->DR via DMA using the TMR peripheral of the i.MX RT1050. Is this possible?

My reading of the reference manual is that the TMR should be able to generate DMA requests when CMPLD1 (or CMPLD2) "needs an update" (see Sec 53.10). I'm not totally sure what "needs an update" means, but according to Sec 53.11.13 it seems that it should mean anytime the the contents of CMPLD1 are transferred to COMP1

Setting this bit enables DMA write requests for CMPLD1 whenever data is transferred out of the CMPLD1 register into the COMP1 register.

I have TMR3_CSTRL0[CL1] = 0x2 ("load upon successful compare with the value in COMP2").

The DMA request is enabled with:

QTMR_EnableDma(DAC_TIMER, DAC_DMA_CHAN, kQTMR_ComparatorPreload1DmaEnable);

 

Furthermore, the DMA MUX is configured with:

DMAMUX_SetSource(DMA0_DMAMUX_BASEADDR, DMA0_CH0_DMA_CHANNEL, kDmaRequestMuxQTIMER3CaptTimer0Cmpld1Timer0Cmpld2Timer1);


I've configured TMR3_CH0 to generate a 1 MHz signal with 25% duty factor, synchronous to TMR3_CH1 (50% duty factor). 

Unfortunately, it appears that the GPIO writes are not synchronized to the TMR channels, as you can see in the following oscilloscope capture. I've configured the DMA source to buffer the values [0, 1, 2, 3] and the destination to be GPIO1->DR. These decimal values can be represented on the two pins (captured by CH3 and CH4 of the oscilloscope). 

aberger_0-1752530901503.png

So the DMA transfers are happening, but they are not being triggered by TMR3_CH0 as desired. 

Any ideas as to what might be wrong?

ラベル(1)
タグ(2)
0 件の賞賛
返信
5 返答(返信)

525件の閲覧回数
Sam_Gao
NXP Employee
NXP Employee

Hi,

Actually I didn't get the point. Please clairfy what you would like to do.

  •  'GPIO writes are not synchronized to the TMR channels'

Yes, TMR channels need to pass through and depend on its conditions.

Sam_Gao_1-1752736935805.png

 

  • Here is one example about how to config QTMR channels to captrue DMA.

https://github.com/nxp-mcuxpresso/mcuxsdk-examples/blob/release/25.03.00/_boards/evkbimxrt1050/drive... 

 

 

 

0 件の賞賛
返信

509件の閲覧回数
aberger
Contributor V

I'm not trying to trigger an input capture. I'm trying to trigger a GPIO write when the TMR COMP match occurs. Unfortunately, there is no DMA trigger for COMP match. The closest event to a COMP match is the associated CMPLD register read. The TMR module does provide DMA triggers "whenever data is transferred out of the CMPLDn register." 

When the DMA Transfer configuration is defined, I get to define the source and destination address. So I am free to set the destination address for the DMA write to:

((uint32_t)(&GPIO1->DR))

Specifically, I would like to read from a waveform buffer and write that data to a set of GPIO pins, with the transfer timing set precisely by the TMR COMP events. 

Here is how I set up the DMA transfer

/* Relevant Defines and Declarations */
#define DMA0_DMA_BASEADDR DMA0
#define DMA0_DMAMUX_BASEADDR DMAMUX
#define DMA0_CH0_DMA_REQUEST kDmaRequestMuxQTIMER3CaptTimer0Cmpld1Timer0Cmpld2Timer1
uint32_t waveform_buffer[WAV_BUF_LEN] __attribute__((aligned(4)));

/* Channel CH0 initialization */
/* Set the source kDmaRequestMuxQTIMER3CaptTimer0Cmpld1Timer0Cmpld2Timer1 request in the DMAMUX */
DMAMUX_SetSource(DMA0_DMAMUX_BASEADDR, DMA0_CH0_DMA_CHANNEL, DMA0_CH0_DMA_REQUEST);
/* Enable the channel 0 in the DMAMUX */
DMAMUX_EnableChannel(DMA0_DMAMUX_BASEADDR, DMA0_CH0_DMA_CHANNEL);
/* Create the eDMA DMA0_CH0_Handle handle */
EDMA_CreateHandle(&DMA0_CH0_Handle, DMA0_DMA_BASEADDR, DMA0_CH0_DMA_CHANNEL);
/* DMA0 transfer CH0_TRANSFER0 configuration */
EDMA_PrepareTransferConfig(&DMA0_CH0_TRANSFER0_config, (void *) &waveform_buffer, 1 << kEDMA_TransferSize4Bytes, 4, (void *) ((uint32_t)(&GPIO1->DR)), 1 << kEDMA_TransferSize4Bytes, 0, 4U, 16U); 
/* DMA0 transfer CH0_TRANSFER0 submit */
status = EDMA_SubmitTransfer(&DMA0_CH0_Handle, &DMA0_CH0_TRANSFER0_config);

But maybe that doesn't work? I'm starting to think that the TMRx_DMAn[CMPLDyDE] bit only exists to trigger a write to the CMPLD register. That's a bit more inflexible than what I had hoped for.

 

0 件の賞賛
返信

440件の閲覧回数
aberger
Contributor V

In case its useful for others, I was able to get this to work. The key is to use the eDMA Channel Linking feature. 

Since the TMR can only trigger writes to itself (namely CMPLDn writes on a CMPLDn->COMPn transfer "event"), the first DMA channel is configured to do that. A second channel is linked, so that on completion of the CMPLD1 write, a GPIO->DR write is triggered. 

Attached is the project with README.

A summary screenshot is shown here:, showing parallel updates to GPIO1, pins 16 and 17, triggered by the COMP events on TMR3_CH0. The latency between the COMP2 event and an update of the GPIO lines is about 250 ns.

GPIO_DMA_1MHz.png

Unfortunately, with linked channels, it seems that the fastest I can trigger the GPIO writes is about 3 MHz. For example, if DAC_CLK_FREQ_HZ is set to 10 MHz, the GPIO writes no longer remain synchronized to the the TMR periods. It seems the fastest the GPIO lines can be updated is about 250 ns, or 38 cycles of the 150 MHz IPG_CLKC that runs the DMA and GPIO peripherals. Is 38 cycles consistent with execution of two linked DMA channels, one of which writes the 16-bit CMPLD register, and the second of which writes to the 32-bit GPIO DR register? That seems like a lot of extra cycles.

UDPATE: There isn't a section in the iMX reference manual on eDMA Performance. But by comparison to the K66 reference manual, it seems that ~17 cycles per eDMA request is expected (Table 24-5). This is consistent with the 38 cycles to process the two linked channel requests in my demo.

To make an additional comparison to the K66: it seems the TMR and eFlexPWM peripherals of the iMX are not as flexible as the FlexTimer peripherals of the Kinetis-series devices. The FTM peripherals could trigger a general DMA write. The TMR and eFlexPWM peripherals of the iMX can only trigger writes to their own registers (CMPLD, and VALx, respectively).

タグ(3)
0 件の賞賛
返信

420件の閲覧回数
aberger
Contributor V

Somehow the project didn't get attached to the previous post. Trying again here.

0 件の賞賛
返信

287件の閲覧回数
Sam_Gao
NXP Employee
NXP Employee

Thanks for your contribution!

0 件の賞賛
返信