While playing with analogWrite I noticed that some of the PWM pins I expected to be available are not, and I’m just wondering what the reason is. From the datasheet I expected to be able to get PWM output on PA0, PA1, PA2, PA3, PA6, PA7, PA8, PA9, PA10, PB0, PB1 and maybe even PB6, PB7, PB8, PB9.
This seems to agree with the PIN_MAP in board.cpp, however the actual available pins are limited to the ones listed in boardPWMPins, ie PA0, PA1, PA2, PA3, PA6, PA7, PA8, PA9, PA10, PB0, PB6, PB7
So what happened to PB1, PB8 and PB9?
Are they tied up with some other use somewhere else so cant be freed for PWM?
// Note. See the enum of pin names in board.h
extern const stm32_pin_info PIN_MAP[BOARD_NR_GPIO_PINS] = {
{GPIOA, TIMER2, ADC1, 0, 1, 0}, /* PA0 */
{GPIOA, TIMER2, ADC1, 1, 2, 1}, /* PA1 */
{GPIOA, TIMER2, ADC1, 2, 3, 2}, /* PA2 */
{GPIOA, TIMER2, ADC1, 3, 4, 3}, /* PA3 */
{GPIOA, NULL, ADC1, 4, 0, 4}, /* PA4 */
{GPIOA, NULL, ADC1, 5, 0, 5}, /* PA5 */
{GPIOA, TIMER3, ADC1, 6, 1, 6}, /* PA6 */
{GPIOA, TIMER3, ADC1, 7, 2, 7}, /* PA7 */
{GPIOA, TIMER1, NULL, 8, 1, ADCx}, /* PA8 */
{GPIOA, TIMER1, NULL, 9, 2, ADCx}, /* PA9 */
{GPIOA, TIMER1, NULL, 10, 3, ADCx}, /* PA10 */
{GPIOA, TIMER1, NULL, 11, 4, ADCx}, /* PA11 */
{GPIOA, NULL, NULL, 12, 0, ADCx}, /* PA12 */
{GPIOA, NULL, NULL, 13, 0, ADCx}, /* PA13 */
{GPIOA, NULL, NULL, 14, 0, ADCx}, /* PA14 */
{GPIOA, NULL, NULL, 15, 0, ADCx}, /* PA15 */
{GPIOB, TIMER3, ADC1, 0, 3, 8}, /* PB0 */
{GPIOB, TIMER3, ADC1, 1, 4, 9}, /* PB1 */
{GPIOB, NULL, NULL, 2, 0, ADCx}, /* PB2 */
{GPIOB, NULL, NULL, 3, 0, ADCx}, /* PB3 */
{GPIOB, NULL, NULL, 4, 0, ADCx}, /* PB4 */
{GPIOB, NULL, NULL, 5, 0, ADCx}, /* PB5 */
{GPIOB, TIMER4, NULL, 6, 1, ADCx}, /* PB6 */
{GPIOB, TIMER4, NULL, 7, 2, ADCx}, /* PB7 */
{GPIOB, TIMER4, NULL, 8, 3, ADCx}, /* PB8 */
{GPIOB, NULL, NULL, 9, 0, ADCx}, /* PB9 */
{GPIOB, NULL, NULL, 10, 0, ADCx}, /* PB10 */
{GPIOB, NULL, NULL, 11, 0, ADCx}, /* PB11 */
{GPIOB, NULL, NULL, 12, 0, ADCx}, /* PB12 */
{GPIOB, NULL, NULL, 13, 0, ADCx}, /* PB13 */
{GPIOB, NULL, NULL, 14, 0, ADCx}, /* PB14 */
{GPIOB, NULL, NULL, 15, 0, ADCx}, /* PB15 */
{GPIOC, NULL, NULL, 13, 0, ADCx}, /* PC13 */
{GPIOC, NULL, NULL, 14, 0, ADCx}, /* PC14 */
{GPIOC, NULL, NULL, 15, 0, ADCx}, /* PC15 */
};
extern const uint8 boardPWMPins[BOARD_NR_PWM_PINS] __FLASH__ = {
PB0, PA7, PA6, PA3, PA2, PA1, PA0, PB7, PB6, PA10, PA9, PA8
};
extern const uint8 boardADCPins[BOARD_NR_ADC_PINS] __FLASH__ = {
PB0, PA7, PA6 , PA5 , PA4 , PA3 , PA2 , PA1 , PA0
};
According to the Maple mini wiki that is still on Leaflabs site http://leaflabs.com/docs/hardware/maple-mini.html
PB1 does have PWM.
However looking at the orginal (now defunct) leaflabs/libmaple repo
https://github.com/leaflabs/libmaple/bl … /board.cpp
It has the same boardPWMPins defined as we have (because our files are based on LibMaple)
So either the docs are wrong or the board file is wrong
Unfortunately Leaflabs called end of life on libmaple several months ago, so they won’t reply to issues posted to their repo.
But looking at usage of the boardPWMPins array, it seems to be redundant.
https://github.com/leaflabs/libmaple/se … ardPWMPins
As far as I can tell, PWM should work OK on PB1, as it has TIMER3 assigned to it, like PA6 etc does
Can you see if it actually works on PB1 ? A
And if so, perhaps we should remove the boardPWMPins definition as it doesnt seem to be used by the core anywhere or alternatively (I suppose a safer solution is to add the missing pins to boardPWMPins[] )
I havent yet dug any deeper into the code to see why.
My main requirement is not actually for PWM, but for ADC. The next line down in board.cpp gives:
extern const uint8 boardADCPins[BOARD_NR_ADC_PINS] __FLASH__ = {
PB0, PA7, PA6 , PA5 , PA4 , PA3 , PA2 , PA1 , PA0
};
That’s interesting.
I’m not sure if you have downloaded the manual for the STM32 yet (is a rather large PDF doc) called RM0008
http://www.st.com/web/en/resource/techn … 171190.pdf
As its the ultimate reference for this stuff.
I will PM Victor_pv as he has been looking closely at the timers recently, so he may be able to shed some light on the PWM stuff (as I’m sure it uses the timers)
PB8 seems to be the pin D32 in the maple mini, which is tied to the onboard button. I suspect leaflabs disabled PWM there in purpose.
PB1 is D33, which is listed as having PWM in their maple mini information.
Then pin 24 is PA11, which should have PWM, but they don’t list it for some reason. That is timer 1 Ch4.
And they did not list Timer 4 Ch4.
So 4 pins that should have PWM are not listed.
PB9 is used in the maple mini to enumerate the USB bus. It is free in the generic boards, so we probably just need to edit change some files.
D33 may be intentional because is a button, and perhaps D24 because is one of the USB lines, I don’t get why the other one still missing.
It’s pretty later over here, but I’ll try to have a look tomorrow.
In any case libmaple includes a bunch of lower level functions that allow you to see the PWM in any pin that has a timer on it, those most likely work as expected, but as I said I will need to check the code.
I would not set D24 to PWM unless you disable the USB peripheral first, as it is always enabled by default. But can be manually disabled if you need to though.
Regarding PB1 for ADC, same thing. As it is connected to a led in the maple mini, they left it out of the ADC list. That is the base of the C8/CB code, so that’s why it is disabled. We will most likely need to edit some files.
EDIT: I think that covers them all.
So the led pin can and does PWM, D32.
D33 is the button, which may not be very useful doing PWM, but should be able to do it. In an official mini if you set it as output and then press the button, you may cause a short and kill the pin or the MCU, so should not be allowed.
Then PA11 is DP-, should not do PWM or would mess up USB, and PB9 is the USB enumerator, should not do PWM or would mess up USB too.
For a generic board the only one we should not allow to do PWM in normal conditions is PA11, as we don’t have led, button in the same place, and no USB enumeration circuit.
Its odd that there are some pins which are in the wiki as having PWM and which have Timers attached to them (in PIN MAP) but don’t function as PWM – according to the OP
anyway, its not a big deal, but its one to keep an eye on.
I’m not sure even why the boardpwmpins definition is in the code, its not used, in the core, but perhaps its for the sketches. I know the Due has something similar
I guess we will have to edit it to add that. If I have time when I get home I’ll try to correct it and send a pull request.
EDIT:
One correction to why pin32 can not use PWM on the maple mini
Besides being connected to the butting, it is connect to the pin BOOT0, and to a pull down 10K resistor.
I am not sure of the effects of having PWM on the boot 0 pin and doing a reboot, so leaflabs may have been cautious there, or even tested and found the boot unreliable.
This obviously does not apply to a Generic board, so PWM should be allowed there for the generic ones.
I think it should be possible to use the pin connected to Boot0 without it causing any issues, however setting the pin connected to the button to any form of output, risks damaging the processor if the button was pushed.
Generic boards will vary in what is connected to those 2 pins, but on Generics I’d be more concerned about Boot0 as the jump links on some boards short Boot0 to GND
I understand Maple boards and official Arduino boards etc being software limited to match the hardware, but when using the library with ‘generic’ boards and custom user built boards I would have thought one should be able to apply any appropriate pin function to any capable pin.
Even on an Arduino board if you set a pin to output and then short it to ground its your own silly fault ![]()
If you look at the pinmap on the generic boards, you’ll find that all pins are defined.
So you can use them all.
However If there is some code kicking in and preventing PWM on Boot0 and the Maple mini boot pin, we should fix the code if possible
If I happen to find it in my travels I’ll let you know!
If you look at the pinmap on the generic boards, you’ll find that all pins are defined.
So you can use them all.
However If there is some code kicking in and preventing PWM on Boot0 and the Maple mini boot pin, we should fix the code if possible
Re: PB9
Sorry, this is me being a bit lazy.
The same applies to the V and Z series boards.
I didn’t have time to look up which timer was associated with which pin, so I set them all to null, expecting to get back to it shortly afterwards, but as ever, some more urgent fixes needed to be done, and I ended up forgetting it needed to be done.
In the docs (RM00008) it looks like PB9 is associate with Timer 4,
I’d need to also check if any of the other pins e,g, PC13 have Timers associated with them, and update not just the C series but also the R V and Z series (the Z will take some time as its got a lot of GPIO !)
Re: PB9
Sorry, this is me being a bit lazy.
The same applies to the V and Z series boards.
I didn’t have time to look up which timer was associated with which pin, so I set them all to null, expecting to get back to it shortly afterwards, but as ever, some more urgent fixes needed to be done, and I ended up forgetting it needed to be done.
In the docs (RM00008) it looks like PB9 is associate with Timer 4,
I’d need to also check if any of the other pins e,g, PC13 have Timers associated with them, and update not just the C series but also the R V and Z series (the Z will take some time as its got a lot of GPIO !)
I don’t remember that PR, but there is a lot going on and things are hard to keep track of.
Re: PB9
I will try to test if setting the timer on that pin to TIMER4 and see if it allows PWM on that pin
I seem to have lead you on a bit of a wild goose chase. After more careful testing this morning I can confirm that ALL PWM pins listed in the PIN_MAP work as expected. Including PB0, PB1 and PB6,7 and 8.
So the only error seems to be that PB9 should be linked to TIMER4 in the PIN_MAP. Presently PB9 does not work as a PWM pin, which is to be expected since its not in the PIN_MAP.
I can also confirm that all ADC pins listed in the PIN_MAP work as expected too including PB1 which is the one I was originally worried about. So this does indeed suggest that the boardPWMPins[] and boardADCPins[] do not have any effect.
If you have time, can you modify your pinmap to add TIMER4 to PB9 and see if that enables PWM on that pin ?
Re: boardPWMPins etc
I’ll see if any of the examples use this or whether the Due etc has it, and if not I don’t really see the point in having these definitions
We’d be better off having some utility functions which just check whether a timer or an ADC is defined in the PIN map for a specific pin.
Its one less thing to support and update
{GPIOB, TIMER4, NULL, 9, 4, ADCx}, /* PB9 */
PR’s are the easiest. I can action them in GitHub without even needing to download the code if I don’t want to


