2024-06-15 10:13 PM
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?
Solved! Go to Solution.
2024-06-17 06:05 AM - edited 2024-06-17 06:09 AM
> 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.
2024-06-16 12:32 AM - edited 2024-06-16 12:35 AM
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 :
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.
2024-06-16 01:18 AM - edited 2024-06-17 08:01 AM
> 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.
2024-06-16 03:12 AM
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
2024-06-16 07:57 AM
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.
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?
2024-06-16 08:18 AM
Here's the settings for TIM1 in CubeMX I think I need for input capture:
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.
2024-06-16 08:43 AM
If you're wondering if I'm reading the manuals, I have been trying to. It's a lot of very condensed information.
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.
2024-06-16 10:26 AM - edited 2024-06-16 10:49 AM
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.
2024-06-16 03:23 PM
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
2024-06-17 02:41 AM
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