The "why's" of timer allocation
The "why's" of timer allocation
Wondering why timers are allocated the way they are. In particular:
1) Is there any reason servos need a 32 bit timer, or need an up/down counter? At first glance, it would seem that 16 bit resolution would be sufficient to drive most hobby servos beyond their resolution capabilities, and down counting doesn't seem to get used for servos, unless I missed something reading the code.
2) Is there something magic about timer3 that makes it the reserved timer for the system? Again, does the system make use of down-counting, or could this be moved to another 16 bit timer that up-counts only?
The reason I am asking is that I am contemplating a custom build of Micro Python (with custom PCB) that would enable two quadrature decoders and retain the ability to drive at least two servos. Only timers 2,3,4 and 5 have quadrature decoders. I could use timers 2 and 4, ending up with asymmetric encoder sizes, which doesn't matter but bothers me more than it should. In any case, following the 2&4 plan and using timer 2 for QEI and leaving timer 5 for servos requires moving the USR pin (easily done, I'm already using a build configured that way).
I'd like to do something minimally invasive. Originally, I was aiming for something that would run (with limitations) a stock PyBoard stmhal build. I could still do that, but moving the servos to timer9 or moving the system off of timer 3 are attractive options, modulo any gotchas associated with that.
1) Is there any reason servos need a 32 bit timer, or need an up/down counter? At first glance, it would seem that 16 bit resolution would be sufficient to drive most hobby servos beyond their resolution capabilities, and down counting doesn't seem to get used for servos, unless I missed something reading the code.
2) Is there something magic about timer3 that makes it the reserved timer for the system? Again, does the system make use of down-counting, or could this be moved to another 16 bit timer that up-counts only?
The reason I am asking is that I am contemplating a custom build of Micro Python (with custom PCB) that would enable two quadrature decoders and retain the ability to drive at least two servos. Only timers 2,3,4 and 5 have quadrature decoders. I could use timers 2 and 4, ending up with asymmetric encoder sizes, which doesn't matter but bothers me more than it should. In any case, following the 2&4 plan and using timer 2 for QEI and leaving timer 5 for servos requires moving the USR pin (easily done, I'm already using a build configured that way).
I'd like to do something minimally invasive. Originally, I was aiming for something that would run (with limitations) a stock PyBoard stmhal build. I could still do that, but moving the servos to timer9 or moving the system off of timer 3 are attractive options, modulo any gotchas associated with that.
Re: The "why's" of timer allocation
on the pyboard, only timer 2 or 5 could be chosen for the Sevo, since those are the only 2 timers on pins X1-X4.
I think timer 3 for the other functions is arbitrary. IIRC the blue LED uses timer 3 as well.
I see no reason why the servo timer couldn't be configurable.
I see no reason why the timer 3 functions couldn't be configurable either. On the pyboard, none of timer 3 channels are exposed (except for the blue LED), which is probably one reason why it was chosen.
I think that they were allocated very early on in the micropython lifetime, and nobody has needed to change them up until now.
I'd like to see the Servo class generalized so that it can work on any PWM capable channel, but the Servo class is also pretty much a convenience thing. It was written before we had PWM support in the timers. It's pretty easy to write a Servo class in python now using the timers pwm functionality.
I think timer 3 for the other functions is arbitrary. IIRC the blue LED uses timer 3 as well.
I see no reason why the servo timer couldn't be configurable.
I see no reason why the timer 3 functions couldn't be configurable either. On the pyboard, none of timer 3 channels are exposed (except for the blue LED), which is probably one reason why it was chosen.
I think that they were allocated very early on in the micropython lifetime, and nobody has needed to change them up until now.
I'd like to see the Servo class generalized so that it can work on any PWM capable channel, but the Servo class is also pretty much a convenience thing. It was written before we had PWM support in the timers. It's pretty easy to write a Servo class in python now using the timers pwm functionality.
Re: The "why's" of timer allocation
@dhylands is right: these allocations were made long ago. The reasons he gives for the choices sound correct to me, but honestly I can't remember!
I would really like to see TIM3 freed up, either by moving to a 16 bit timer, or making configurable at build time, or in boot.py, or all of the above. We may even be able to do the flash cache flushing via the systick timer, and then tim3 (or whatever it becomes) is only needed if USB is enabled (which can be a dynamic thing).
There should be no gotchas to changing tim3 or the servo timer to something else.
I would really like to see TIM3 freed up, either by moving to a 16 bit timer, or making configurable at build time, or in boot.py, or all of the above. We may even be able to do the flash cache flushing via the systick timer, and then tim3 (or whatever it becomes) is only needed if USB is enabled (which can be a dynamic thing).
There should be no gotchas to changing tim3 or the servo timer to something else.
Re: The "why's" of timer allocation
Great! Sounds like there are a lot of options here that would not be huge coding efforts.
Re: The "why's" of timer allocation
Tim3 might be freed up also for USB (CDC) mode.
I was porting some of the USB code to an stml151 device (no MSC just CDC) and so I had time to check the need for that callback that ST proposes for CDC mode. I did not understand why there should be a timer reserved to periodically check the usb buffer - the usb master must poll the usb slave anyway so the endpoints inherently get polled, hence a timer really shouldn't be necessary.
Based on that I added a simple TX complete callback in the lower levels of the Usb stack. The handling was actually already there but it wasn't exposed as a callback for some reason.
And it seems to work nicely. The advantage is that tim3 gets freed up and in general the response is faster over usb, because the callback gets immediately called and not just by the timer irq.
If interested I can provide a patch. I also added a ringbuffer implementation for the rxtx handling.
I was porting some of the USB code to an stml151 device (no MSC just CDC) and so I had time to check the need for that callback that ST proposes for CDC mode. I did not understand why there should be a timer reserved to periodically check the usb buffer - the usb master must poll the usb slave anyway so the endpoints inherently get polled, hence a timer really shouldn't be necessary.
Based on that I added a simple TX complete callback in the lower levels of the Usb stack. The handling was actually already there but it wasn't exposed as a callback for some reason.
And it seems to work nicely. The advantage is that tim3 gets freed up and in general the response is faster over usb, because the callback gets immediately called and not just by the timer irq.
If interested I can provide a patch. I also added a ringbuffer implementation for the rxtx handling.
Re: RE: Re: The "why's" of timer allocation
I would definitely be interested.marfis wrote:Tim3 might be freed up also for USB (CDC) mode.
I was porting some of the USB code to an stml151 device (no MSC just CDC) and so I had time to check the need for that callback that ST proposes for CDC mode. I did not understand why there should be a timer reserved to periodically check the usb buffer - the usb master must poll the usb slave anyway so the endpoints inherently get polled, hence a timer really shouldn't be necessary.
Based on that I added a simple TX complete callback in the lower levels of the Usb stack. The handling was actually already there but it wasn't exposed as a callback for some reason.
And it seems to work nicely. The advantage is that tim3 gets freed up and in general the response is faster over usb, because the callback gets immediately called and not just by the timer irq.
If interested I can provide a patch. I also added a ringbuffer implementation for the rxtx handling.
Re: The "why's" of timer allocation
@marfis that sounds awesome! I think the tim3 stuff used by the ST examples is because they connect the other end of the USB serial to a UART (ie implement a pass through), and we don't do that.
Re: The "why's" of timer allocation
Sure.
@dpgeorge: yes you are right - I forgot about that. But even for a Usb<>uart conversion i believe it's not necessary. The rx uart irq can be used to fill the ringbuffer and the endpoint callback can check the status of the buffer and submit the data. So no timer required there. The other direction is even simpler (using a DMA channel for example). Anyway...
I need some time to cleanup the code and test it on the pyboard, but I guess that the idea is important..
At the moment there are minor modification necessary in the USB stack, this might not be ideal if the stack was updated later on. I'll have a look if it's possible to separate the code changes.
@dpgeorge: yes you are right - I forgot about that. But even for a Usb<>uart conversion i believe it's not necessary. The rx uart irq can be used to fill the ringbuffer and the endpoint callback can check the status of the buffer and submit the data. So no timer required there. The other direction is even simpler (using a DMA channel for example). Anyway...
I need some time to cleanup the code and test it on the pyboard, but I guess that the idea is important..
At the moment there are minor modification necessary in the USB stack, this might not be ideal if the stack was updated later on. I'll have a look if it's possible to separate the code changes.
Re: The "why's" of timer allocation
@marfis
We already make a bunch of changes to the hal code. See the HALCOMMITS file and in the hal directory.
We already make a bunch of changes to the hal code. See the HALCOMMITS file and in the hal directory.
Re: The "why's" of timer allocation
I've placed a pull request:
https://github.com/micropython/micropython/pull/1652
https://github.com/micropython/micropython/pull/1652