PWM API change


I'm cleaning a local port for lm4f120 and making new PR. I see that a recent commit changed/cleaned the PWM API. One of the changes includes limiting the resolution to 16bits (it was an int before, so 32bits in my case). Is there a motivation for limiting the value to 16bits ? In my case, the underlying timer can't be scaled but simply extended by a 8 bits . When I need some low frequency (eg. something suitable for driving a servo), I need to set the timer to something > 16bits.

I see at least 2 possible fixes : - increase resolution to 32bits in the PWM API so that I can expose the real resolution. Having an 'int' here was not really bad in my opinion, as it was not forcing a size. Forcing 16bits param on a 32bits hw or 32bits param on a 16bits may cost more than simply using 'int'... - do some scaling on the resolution to be able to use the full range of the pwm while limiting the resolution to 16bits

What should I do ?

Thanks, Marc


It might also be an idea to create something like: #ifndef HAS_PWM_RES_T typedef uint16_t pwm_res_t #endif

Which can be overridden by the CPU implementation. This way 8bit timers can use 8bit values and 32bit timers 32bit.

Cheers, Nick


Yes, that would be great. Should I implement it in a PR, or has someone something against this ?



I have to say that I don’t quite understand the problem with the 16-bit max here. Is the timer on the lm4f120 limited to it’s prescalers? For applications like controller servo motors 16-bit is normally still more than sufficient… So I think the key here lies in the PWM implementation, and not in changing the API…

‘int’ was actually not a very smart idea -> when moving an application that uses PWM from a 32-bit platform to a 16-bit platform it will break, without giving any hints to why. When using fixed values for low-level APIs, you always now exactly what you can work with, independent of the hardware you are using.

Cheers, Hauke


Maybe you're right... PWM on lm4f120 is done by configuring a timer for which there's no real prescaler and a match value that gives the duty cycle. The timer is 16bits, but can be extended to 20bits if needed. The timer is clocked by the system, so there's no way to fix a resolution and then pick a frequency (even within a given range): the resolution is the value loaded in the timer, and that corresponds to a frequency. Getting a 50Hz PWM with a 16Mhz clock requires the loading of 0x4E200 in the timer. As the API states that the PWM must preserve the resolution given in the _init(), I need to be able to pass this value.

Of course, I could tweak the implementation and do some scaling on the values asked by the user (ie. compute the timer value needed for the required freq and scale all input from other function to match the real resolution), but that would not be ok with "In this case the PWM driver will always keep the resolution and decrease the frequency if needed.". In my case, this would mean the resolution is the real freq, which is not expected by the user.

Cheers, Marc

Hej Marc,

this seems like a pretty broken design to me, who knows what TI was thinking... Anyway, by looking at the datasheet, I think that the solution to this problem in this case is to map the values given via the RIOT PWM interface to internal values that make the PWM behave as expected. See section 20.4 how they configure a 25KHz PWM on top of a 20MHz CPU clock. The only thing that probably won't be as exact is the resolution (number of steps), as this must be rounded for this implementation. But just put a comment in the implementation about this.

Or as an alternative: implement the PWM interface by using a GPT timer, those can be adjusted to the desired clock speed...

Cheers, Hauke


Thank you for taking the time to try to help me solve my problem :slight_smile:

The thing is that on the ek-lm4f120xl board, it's a lm4f120... The DS you are referring to seems to be lm4f232 (or similar). I'm using the lm4f120h5qr-124014.pdf as a reference. The main reason I can see this is that there is no PWM generator on my board. I guess it was broken so they simply "removed" it from the datasheet. There is only the timers that can be used in PWM mode: that's what I was describing previously. I could not find how to change their clock speed (and by reading the docs and all the examples I could find, it seems that's not only me). You can easily configure a PWN by setting a freq and duty cycle, but not by settings a freq and resolution.



I think my datasheet was from the TM4C123GH6PZ, I thought this is just the re-branded lm4f120xl...

While the base timer clock speed is not configurable, the timer does have a pre-scale register, right? Can't we use that to change the timers freq? If not, I would say just adapt the freq to the wanted value and basically ignore the resolution parameter. This should suffice when implementing the PWM interface...

Best, Hauke

Yes, there is a "prescaler" register, which is in fact a simple extension of the timer by 4 bits. It's a pitty these bits are the high bits and that the register is counting down...

So, if it's ok, I'll workaround the API doc and do some scaling on the resolution...

Thanks for your help ! Marc