Pin functions in board.cpp

C_D
Mon Jul 06, 2015 10:56 pm
Im just tinkering with a few ‘blue pill’ F103C8T6 boards at the moment, and getting my head around how the STM32DUINO thing works. Flashed the stm32duino bootloader and uploaded some simple arduino sketches, very impressed so far 8-)

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
};


RogerClark
Mon Jul 06, 2015 11:32 pm
Thats a good point.

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[] )


C_D
Mon Jul 06, 2015 11:51 pm
At present it does not work. Using analogWrite only works on the pins listed in 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
};


RogerClark
Tue Jul 07, 2015 12:07 am
OK

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)


victor_pv
Tue Jul 07, 2015 4:29 am
Having a quick look:
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.


RogerClark
Tue Jul 07, 2015 4:34 am
Thanks Victor

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


victor_pv
Tue Jul 07, 2015 4:42 pm
I checked the board.cpp for the generic C boards, and is indeed missing some pins stuff.
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.


RogerClark
Tue Jul 07, 2015 9:20 pm
Victor

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


C_D
Tue Jul 07, 2015 11:51 pm
Surely its up to the user to know that they are specifying a pin to do something inappropriate for the way the hardware is connected?

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 ;)


RogerClark
Wed Jul 08, 2015 12:15 am
@C_D

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


C_D
Wed Jul 08, 2015 12:56 am
Cool bananas :)

If I happen to find it in my travels I’ll let you know!


victor_pv
Wed Jul 08, 2015 5:11 am
RogerClark wrote:@C_D

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


RogerClark
Wed Jul 08, 2015 5:51 am
Victor,

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 !)


victor_pv
Wed Jul 08, 2015 3:49 pm
RogerClark wrote:Victor,

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 !)


RogerClark
Wed Jul 08, 2015 9:16 pm
Hi Victor,

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


C_D
Wed Jul 08, 2015 11:29 pm
My apologies!!!

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.


RogerClark
Wed Jul 08, 2015 11:56 pm
@C_D

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


C_D
Thu Jul 09, 2015 12:41 am
Modifying the line as follows successfully enables PWM on PB9.

{GPIOB, TIMER4, NULL, 9, 4, ADCx}, /* PB9 */


RogerClark
Thu Jul 09, 2015 12:52 am
Yes

PR’s are the easiest. I can action them in GitHub without even needing to download the code if I don’t want to


Leave a Reply

Your email address will not be published. Required fields are marked *