cancel
Showing results for 
Search instead for 
Did you mean: 

What are GPIO events? How do I connect an event to a peripheral, specifically the DMA?

mleo2
Associate II

I've been reading about GPIO and what can be triggered. I see an event can be triggered. Events can be connected to peripherals to have some control without the CPU intervening. I can't find good documentation showing how to connect or effect peripherals. I'm hoping there is a way to trigger a DMA channel to transfer data with a GPIO without a timer in between.

Are GPIO events the way to trigger a DMA transfer with an external signal? Interrupts are too slow. Timers can do it but are they necessary?

1 ACCEPTED SOLUTION

Accepted Solutions
BarryWhit
Senior

I'm assuming UPDATE occurs every edge that's being watched.

 

No, the update event is when the timer's counter has counted a total of Period_Value (ARR) ticks and

restarts the count. Think of the update event more like triggering event at fixed-frequency. 

 

TIM_DMA_ID_CC1 is what you want (CC1 means Capture/Compare event on channel 1).

 

HAL_DMA_Start_IT(&hdma_tim1_ch1, (uint32_t)clockedData_1, (uint32_t)&(GPIOB->BSRR), 13);

 

yes, you want to manually invoke HAL_DMA_Start_IT and specify the GPIO register you wish to DMA against.

 

- If you feel a post has answered your question, please click "Accept as Solution".
- Once you've solved your issue, please consider posting a summary with any additional details you've learned. Your new knowledge may help others in the future.

View solution in original post

12 REPLIES 12
AScha.3
Chief

You have to read in rm of your chip, whats possible on this chip, here example from H563 manual, GPDMA :

pin on exti mode -> trigger on rising or falling edge :

AScha3_0-1718522992313.png

Then you know, whats possible on this chip.

Or try to select in CubeMx (for your chip!) , it should show , whats possible triggers for a DMA channel.

 

 

If you feel a post has answered your question, please click "Accept as Solution".
BarryWhit
Senior

> I'm hoping there is a way to trigger a DMA channel to transfer data with a GPIO without a timer in between.

 

Repharsing: you want to trigger a dma when there is a voltage transition on a physical pin. In STM32-world this is not called GPIO, but EXTI (Extended interrupt), and it is possible. As @AScha.3 states, the way to do it depends on your device family, and the reference manual is your guide.

 

Interrupts are too slow.

 

Interrupt handlers *in software* may be too slow. But Interrupts/events themselves are all you have.

- If you feel a post has answered your question, please click "Accept as Solution".
- Once you've solved your issue, please consider posting a summary with any additional details you've learned. Your new knowledge may help others in the future.

You can use also TIMx_CHx set to Input Capture to trigger DMA. In older STM32 families without DMAMUX (which may or may not have EXTI triggers) this is the only way to trigger DMA from  pin, but in families with DMAMUX it works, too.

JW

mleo2
Associate II

Thanks for the input. I'm just starting the HAL and LL stuff coming from an Arduino background.

Here's what I've been looking at for the STM32l432KC, It's difficult for me to parse out what I'm looking at. I don't explicitly see any GDPMA or GPIO events. I do see plenty of TIMx_CHx.

mleo2_0-1718549279413.png

mleo2_1-1718549405796.png

From what waclawek.jan said, any TIMx_CHx feeding the DMA controller set in input capture mode should be able to trigger a data transfer on a selected edge. Correct?

 

mleo2
Associate II

Here's the settings for TIM1 in CubeMX I think I need for input capture:

mleo2_2-1718550586275.png

No clock for input capture, Trigger event selection? Do I need one, or do I use TIM1_CH1 for the DMA? What is TIM1_CH4/TRIG/COM, compare match. I don't think that's what I need? Can I use TIM1_UP?

I suspect I want TIM1_CH1.

 

mleo2_3-1718550721328.png

 

 

mleo2
Associate II

If you're wondering if I'm reading the manuals, I have been trying to. It's a lot of very condensed information.

mleo2_4-1718551342924.png

Here's a part of the block diagram for TIM1. I depend on CubeMX to provide the hardware setup, but trying to figure out how to use this information is hard. There are signals all over the place. Figuring out which ones are relevant to my task and which aren't isn't clear. I want a DMA event every falling edge. Do I use the counter/compare register? Should the compare value be zero or one? Should I pay attention to TRG0?

I apologize for whining about how hard this, but ... it is a very steep learning curve.

I am currently an associate II. I remember when I was an associate engineer. I was told associate = "ask". I'll be doing a lot of asking.

BarryWhit
Senior

Ignore TRG0, this is for triggering one timer from another, not relevant to your task.

Timer Input capture is a way to trigger an event from an external pin. a DMA from TIM1_CH1 is what you want but be aware that CubeMX will not do what you expect. It will program the DMA trigger source appropriately, but the provided  HAL_TIM_IC_Start_DMA API  hardcodes the peripheral addr for the DMA to be timer->CCR1. Not what you want. You can however copy HAL_TIM_IC_Start_DMA into your own function and easily modify it to DMA wherever you want.

 

I'm literally having this same conversation right now in another thread. This is a pervasive usability issue with CubeMX, and I'm going to open a bug report thread about it.

 

Configure the input capture section to trigger on whatever you need, rising/falling/both. That's what determines when an event is generated, and whenever that event is generated a DMA trigger will occur.

 

As a sidenote, if your external interrupt source is noisy (like a bouncing mechanical switch used during testing), be aware that the input capture mode provides a "filtering" functionality, i.e. hardware debouncing - which can be very handy.

- If you feel a post has answered your question, please click "Accept as Solution".
- Once you've solved your issue, please consider posting a summary with any additional details you've learned. Your new knowledge may help others in the future.
BarryWhit
Senior

I created a bug report thread for the recurring pain point of triggering DMA from timer event with CubeMX/HAL

Usability: CubeMX/HAL is a footgun if you want to trigger SPI/UART/foo DMA from timer events 

- If you feel a post has answered your question, please click "Accept as Solution".
- Once you've solved your issue, please consider posting a summary with any additional details you've learned. Your new knowledge may help others in the future.
mleo2
Associate II

I ran CubeMX with TIM1 set as input capture and generated code. I think this is the line BarryWhit is referring to:

__HAL_LINKDMA(tim_icHandle,hdma[TIM_DMA_ID_CC1],hdma_tim1_ch1);

I think I want to link it like this:

__HAL_LINKDMA(tim_icHandle,hdma[TIM_DMA_ID_UPDATE],hdma_tim1_ch1);

and then what I think I want is to do is:

HAL_DMA_Start_IT(&hdma_tim1_ch1, (uint32_t)clockedData_1, (uint32_t)&(GPIOB->BSRR), 13);

I'm assuming UPDATE occurs every edge that's being watched.

What are these?

#define TIM_DMA_ID_UPDATE      
#define TIM_DMA_ID_CC1         
#define TIM_DMA_ID_CC2         
#define TIM_DMA_ID_CC3         
#define TIM_DMA_ID_CC4         
#define TIM_DMA_ID_COMMUTATION 
#define TIM_DMA_ID_TRIGGER