-
Notifications
You must be signed in to change notification settings - Fork 1k
HardwareTimer incomplete? #763
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
@ABOSTM |
I @HendryKaak, I agree that this is a bug, timer should really be stopped when pause() is called, Thus my proposal would be to have 2 API: As far as setMode() is concerned, it is not possible to write directly the register:
the timer periperal clock (the clock of register) is enabled only on resume() (thanks to HAL_TIM_Base_Init()). Thus it is not possible to write register on setMode(). |
I was wondering: Is your idea for the HardwareTimer class to maintain the API (mostly) as is, or if it's OK to apply some bigger adjustments on the API? It seems the code has only been fairly recently added, so I would think some needed but incompatible changes would be acceptable?
Your comment on
Is it not possible to set the clock earlier on in the code? Alternatively, an idea would be to set the channel config immediately when the timer is disabled, but if the timer is enabled leave the configuration for later (like now)? |
@LinoBarreca |
@fpistm I honestly read this but then I didn't because I have mixed feelings. HardwareTimer is definitely incomplete so I agree with @HendryKaak ...BUT (and I wrote it uppercase because it's very big) that's how it should be: simple. Exposing through the HardwareTimer all the characteristics of the underlying TIM devices would make the class a nightmare (and that's why I disagree with @HendryKaak). @HendryKaak I understand you have a problem and maybe there should be a way to. But the workaround is easy: Instead of using the channel to give the output, use the arduino way: in channel ISR you So....I didn't comment because what I said doesn't really add something useful to the issue..because I don't really have an opinion besides "let's keep it simple" (and his suggestion of |
Hi @LinoBarreca , thanks you for sharing your view. |
Hello @LinoBarreca
I agree that exposing most of the HAL functionality through HardwareTimer is a lot of work to maintain. However, even when using the HAL directly for advanced features, I would rather still use the HardwareTimer class for the easiness of certain functions (such as Arduino pin to ST pin assignment), configure the channels for example without to much hassle of searching through the HAL files (which is nicely done right now) and still have the option available to setup custom timer settings. IIUC you also think so, but you suggest to do all register manipulations through the HardwareTimer class, so the HT class can keep its internal state consistent. While that is probably a good idea in theory, in practice it is probably not feasible because 1) that would prevent using the existing HAL functions to modify the registers (at least AFAICS) and 2) it is generally tricky to parse all the register bits and deduce the current configuration from that.
Using the timer with interrupts with digitalWrites in it gives a lot of overhead (and process time overhead) and jitter that the timer can properly do itself. This is not the way it should be done in my opinion. This is why MCU's have the output compare on pins for in the first place, which can do zero-overhead zero-jitter output generation. For the same reason, using Tone is not an option for us.
That's OK I guess. It's just that I prefer to keep function names as clear as possible and related to what the function actually does.
Thanks, that would be great.
Yes indeed, but it would be a much more comprehensible that way. |
Main rework: * HAL_TIM_Base_Init() is now called only once at object creation * HAL_TIM_xxx_ConfigChannel is now done in setMode() * HAL_TIM_xxx_Start is done in resumeChannel() * use LL when possible * Configuration are directly made through hardware register access (xhen possible), then remove useless attribut * Add new API to pause only one channel: pauseChannel(uint32_t channel) fixes stm32duino#763 * integration of PR stm32duino#767 Flexible interrupts handling
Main rework: * HAL_TIM_Base_Init() is now called only once at object creation * HAL_TIM_xxx_ConfigChannel is now done in setMode() * HAL_TIM_xxx_Start is done in resumeChannel() * use LL when possible * Configuration are directly made through hardware register access (xhen possible), then remove useless attribut * Add new API to pause only one channel: pauseChannel(uint32_t channel) resumeChannel(uint32_t channel) fixes stm32duino#763 * integration of PR stm32duino#767 Flexible interrupts handling
Main rework: * HAL_TIM_Base_Init() is now called only once at object creation * HAL_TIM_xxx_ConfigChannel is now done in setMode() * HAL_TIM_xxx_Start is done in resumeChannel() * use LL when possible * Configuration are directly made through hardware register access (xhen possible), then remove useless attribut * Add new API to pause only one channel: pauseChannel(uint32_t channel) resumeChannel(uint32_t channel) fixes stm32duino#763 * integration of PR stm32duino#767 Flexible interrupts handling
Main rework: * HAL_TIM_Base_Init() is now called only once at object creation * HAL_TIM_xxx_ConfigChannel is now done in setMode() * HAL_TIM_xxx_Start is done in resumeChannel() * use LL when possible * Configuration are directly made through hardware register access (xhen possible), then remove useless attribut * Add new API to pause only one channel: pauseChannel(uint32_t channel) resumeChannel(uint32_t channel) fixes stm32duino#763 * integration of PR stm32duino#767 Flexible interrupts handling
Main rework: * HAL_TIM_Base_Init() is now called only once at object creation * HAL_TIM_xxx_ConfigChannel is now done in setMode() * HAL_TIM_xxx_Start is done in resumeChannel() * use LL when possible * Configuration are directly made through hardware register access (xhen possible), then remove useless attribut * Add new API to pause only one channel: pauseChannel(uint32_t channel) resumeChannel(uint32_t channel) fixes stm32duino#763 * integration of PR stm32duino#767 Flexible interrupts handling
I also would like to access to the register throught the TIMx object. For example I try to clock the timer from an external source and I don't see any predefined mode for it. How could one count pulses? I could do it with Roger's library like that
|
Hi @mrguen, |
Ok, let me know about using LL in the Arduino environment. Is there some kind of resources available? |
Hi @mrguen,
|
👍 |
Hey,
I've been struggling with the implementation of the current
HardwareTimer
class with a custom stm32f401 board and would like to share a few points that caused some problems here and there.What i've been trying to do is using the HardwareTimer class to setup a PWM output for a buzzer and used a specific timer channel to do so. But the first problem I encountered was that the timer or channel was not disabled when the
Pause()
function is called. Looking at the code I found out that in the HALstm32f4xx_hal_tim.h
, the timer would only be disabled when all timer channels are disabled:Arduino_Core_STM32/system/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_tim.h
Lines 1022 to 1031 in 1e2a598
So disabling the timer never happens because the
HAL_TIM_OC_Stop
macro is never called with the correct timer channel in thepause()
function.Arduino_Core_STM32/cores/arduino/HardwareTimer.cpp
Lines 101 to 109 in 1e2a598
Only the interrupts are being stopped over there as you can see, but never the channel itself and thus the timer is never stopped.
To resolve this:
pause()
andresume()
. Essentially, these functions really stop/disable and start/enable the timer, where pause would suggest it just stops the timer without reconfiguring anything (in particular, I would not expect pause to change the current pin output), Perhaps these functions should be renamed and/or better documented? Maybe real pause/resume methods should be added?Another thing that I found questionable is the
setMode()
function. AFAIK is that the channels modes are first stored in RAM, but only written to registers whenresume()
is called. This means that the only way to change a channel's configuration is by restarting the timer. It might be feasible to sometimes reconfigure a channel while the timer is running (an obvious usecase is to disable or re-enable a single channel without affecting the others, but also changing other setttings on the fly would make sense). Maybe setMode should just apply the changes directly? As long as the timer is disabled, there should be no harm in applying the channel settings, I believe?The text was updated successfully, but these errors were encountered: