Pin definitions in Arduino_Core_STM32

AndySymons
Tue Nov 20, 2018 12:56 pm
I recently made a board definition by adapting code from a similar board, as the instructions suggest, but it is not clear how the definitions are used. The core modules pins_arduino.h and pins_arduino.c seem to do all the mapping.

For example, the digital pins D0 to Dmax are enumerated as zero upwards; does that mean the pin names in variant.h and variant.c have to start PA0, PA1 etc. up to PA15, then on to PB0 etc.? The examples I looked at use a random order, usually based on the physical layout of headers on the board. How does GPIO initialisation know the port and the pin corresponding to a number like PB6?

I also see that the Analog pins A0 to Amax are enumerated sequentially from a given starting point NUM_ANALOG_FIRST. This may work with an ATMega328 but for STM it is not correct unless the pins themselves are numbered in a special way. For the STM32F103, for example, PA0-7 correspond to IN0-7, then PB0-1 are IN8-9 and PC0-5 are IN10-15.

Of course this problem is avoided if one does not use D0-Dmax or A0 to Amax at all, but instead the STM32 names, like PA0 (PA_0), PB1 (PB_1), PC2 (PC_2) etc. It only makes sense to me to use the old Arduino D0-Dmax and A0-Amax names if these are printed as such on the board. Are there any boards that do this? If so, would it not be more reliable to put the definitions of D0-Dmax and A0-Amax in the board definitions — variant.h and variant.c ?

Regards, Andy


fpiSTM
Tue Nov 20, 2018 1:52 pm
[AndySymons – Tue Nov 20, 2018 12:56 pm] – The core modules pins_arduino.h and pins_arduino.c seem to do all the mapping.

No it only do basic mapping of Arduino naming Ax/Dx.

[AndySymons – Tue Nov 20, 2018 12:56 pm] –
For example, the digital pins D0 to Dmax are enumerated as zero upwards; does that mean the pin names in variant.h and variant.c have to start PA0, PA1 etc. up to PA15, then on to PB0 etc.? The examples I looked at use a random order, usually based on the physical layout of headers on the board. How does GPIO initialisation know the port and the pin corresponding to a number like PB6?

In Arduino D0 is always equal to 0. As DigitalRead(D0) is equivalent to DigitalRead(0). So Dx = x.
The PYn define in variant.h is a pin number. This allows to be compatible with most of Arduino API using pin number as argument.
So a PYn can be defined to be equal to a Dx.
It is also used as an index to the PinName array defined in variant.cpp.
A PinName is a type containing Port and pin info of the GPIO.
Ex:
PB_6 = (PortB << 4) + 0x06,


AndySymons
Thu Nov 22, 2018 10:10 pm
Thanks for those clarifications.

When you say Analog pins have to be contiguous to allow loop: , I suppose you mean that they have to be contiguous somewhere within the const PinName digitalPin[] table, which would be possible, not in the order of the physical pins, which is not possible?

So if the board is labelled D0-Dn, with some of the pins (also or alternatively) A0-An, then that should be the ordering of the const PinName digitalPin[] table; however if the board is not so labelled, then any order can be used in const PinName digitalPin[]?

The DIYMROE board, for example, is marked with the STM32 names, not Arduino names like Dx and Ax, so the discussion is moot. In this case it would be best if Dx and Ax were not defined at all — but that is not a variant option at the moment. Perhaps it would make more sense if they were defined specifically in the variants?

The way I set it up for DIYMROE they may be defined wrongly, but since they have no meaning with this board, the user would never use them anyway. I assume that pinMode, digitalRead/Write, and analogRead/Write will always work correctly with the STM names (PA1, PB2 etc), provided the #defines in variant.h match the ordering within const PinName digitalPin[]?

I think I am starting to get it!


fpiSTM
Fri Nov 23, 2018 8:13 am
Dx and Ax are not important. I don’t understand why you focus on them.
It is for Arduino compatibility that’s all and it’s up to the user to use it or not, this not growth the code size.
All API are compatible with STM pin name PYn.
In variant up to you to define the order of the pin the only restriction is to have the Analog pins contiguous and the first one have to be higher than the number of analog you define.

BennehBoy
Thu Jan 10, 2019 4:52 pm
Sorry to piggyback on this thread, especially given it’s 2 months old… but…

I can’t seem to get analogRead to work on the 2 GenF4 variants that I have access to (DIYMROE & BLACK407VET6)

Are they pre-configured if included in the analog pinmap or is there some pin setup required?


fpiSTM
Thu Jan 10, 2019 5:16 pm
There is no specific stuff to do. If they are well defined they should work simply using:
int sensorValue = analogRead(A0);

fpiSTM
Fri Jan 11, 2019 7:57 am
Ok I’ve made the test and I think I guess why you asked if it is working.

#define Serial SerialUSB // Arduino Due, Maple

// the setup routine runs once when you press reset:
void setup() {
// initialize serial communication at 9600 bits per second:
Serial.begin(9600);
}

// the loop routine runs over and over again forever:
void loop() {
// print out the value you read:
Serial.print("A0 (PA0)= "); Serial.print(analogRead(A0)); Serial.print("\t"); Serial.print(analogRead(0)); Serial.print("\t"); Serial.println(analogRead(PA0));
delay(1); // delay in between reads for stability
Serial.print("A1 (PA1)= "); Serial.print(analogRead(A1)); Serial.print("\t"); Serial.print(analogRead(1)); Serial.print("\t"); Serial.println(analogRead(PA1));
delay(1); // delay in between reads for stability
Serial.print("A2 (PA2)= "); Serial.print(analogRead(A2)); Serial.print("\t"); Serial.print(analogRead(2)); Serial.print("\t"); Serial.println(analogRead(PA2));
delay(1); // delay in between reads for stability
Serial.print("A3 (PA3)= "); Serial.print(analogRead(A3)); Serial.print("\t"); Serial.print(analogRead(3)); Serial.print("\t"); Serial.println(analogRead(PA3));
delay(1); // delay in between reads for stability
Serial.print("A4 (PA4)= "); Serial.print(analogRead(A4)); Serial.print("\t"); Serial.print(analogRead(4)); Serial.print("\t"); Serial.println(analogRead(PA4));
delay(1); // delay in between reads for stability
Serial.print("A5 (PA5)= "); Serial.print(analogRead(A5)); Serial.print("\t"); Serial.print(analogRead(5)); Serial.print("\t"); Serial.println(analogRead(PA5));
delay(1); // delay in between reads for stability
Serial.print("A6 (PB0)= "); Serial.print(analogRead(A6)); Serial.print("\t"); Serial.print(analogRead(6)); Serial.print("\t"); Serial.println(analogRead(PB0));
delay(1); // delay in between reads for stability
Serial.print("A7 (PB1)= "); Serial.print(analogRead(A7)); Serial.print("\t"); Serial.print(analogRead(7)); Serial.print("\t"); Serial.println(analogRead(PB1));
delay(1); // delay in between reads for stability
Serial.print("A8 (PC0)= "); Serial.print(analogRead(A8)); Serial.print("\t"); Serial.print(analogRead(8)); Serial.print("\t"); Serial.println(analogRead(PC0));
delay(1); // delay in between reads for stability
Serial.print("A9 (PC1)= "); Serial.print(analogRead(A9)); Serial.print("\t"); Serial.print(analogRead(9)); Serial.print("\t"); Serial.println(analogRead(PC1));
delay(1); // delay in between reads for stability
Serial.print("A10 (PC2)= "); Serial.print(analogRead(A10)); Serial.print("\t"); Serial.print(analogRead(10)); Serial.print("\t"); Serial.println(analogRead(PC2));
delay(1); // delay in between reads for stability
Serial.print("A11 (PC3)= "); Serial.print(analogRead(A11)); Serial.print("\t"); Serial.print(analogRead(11)); Serial.print("\t"); Serial.println(analogRead(PC3));
delay(1); // delay in between reads for stability
Serial.print("A12 (PC4)= "); Serial.print(analogRead(A12)); Serial.print("\t"); Serial.print(analogRead(12)); Serial.print("\t"); Serial.println(analogRead(PC4));
delay(1); // delay in between reads for stability
Serial.print("A13 (PC5)= "); Serial.print(analogRead(A13)); Serial.print("\t"); Serial.print(analogRead(13)); Serial.print("\t"); Serial.println(analogRead(PC5));
delay(1000); // delay in between reads for stability
Serial.println("#################");
}


BennehBoy
Fri Jan 11, 2019 10:42 am
OK thanks, that makes total sense.

I’ll have a play about with the variant configs to see if I can get the right ordering then submit changes if successful.


fpiSTM
Fri Jan 11, 2019 12:26 pm
I’m currently writing a sketch to test variant coherency. I will share it this afternoon.

BennehBoy
Fri Jan 11, 2019 2:13 pm
[fpiSTM – Fri Jan 11, 2019 12:26 pm] –
I’m currently writing a sketch to test variant coherency. I will share it this afternoon.

Great, thanks.


fpiSTM
Fri Jan 11, 2019 5:00 pm
[BennehBoy – Fri Jan 11, 2019 2:13 pm] –

[fpiSTM – Fri Jan 11, 2019 12:26 pm] –
I’m currently writing a sketch to test variant coherency. I will share it this afternoon.

Great, thanks.

First shot. I will add some other check.

https://gist.github.com/fpistm/93f26012 … 6383e4f314


BennehBoy
Fri Jan 11, 2019 6:01 pm
Nice.

Although I’m thinking that getting the correct PXy refs might be too much of a kludge.

This tool will help for now I think.


BennehBoy
Sun Jan 13, 2019 11:54 am
@fpiSTM

Is the ADC configured to be only 10 bit for Arduino AVR compatibility?

Any way to have the full 12 bits?


BennehBoy
Sun Jan 13, 2019 12:11 pm
Just had a look at wiring_analog.c

Presumably we could make the _readResolution adjustable somehow?

Presently it is fixed at 10:

static int _readResolution = 10;


BennehBoy
Sun Jan 13, 2019 12:24 pm
From what I can tell ESP has code in their HAL to handle the resolution (up to 12 bit h/w or 16 bit s/w).

fpiSTM
Sun Jan 13, 2019 2:18 pm
Hum, in fact there is a misalignment as in fact this is 12b resolution:

https://github.com/stm32duino/Arduino_C … log.c#L550
And defined also here:
https://github.com/stm32duino/Arduino_C … ino.h#L279

In fact, this should be this, I guess:
static int _readResolution = ADC_RESOLUTION;


BennehBoy
Sun Jan 13, 2019 2:45 pm
Tested & working, I’ll submit a PR once I’m able :lol:

fpiSTM
Sun Jan 13, 2019 3:03 pm
Hum, in fact this is not an issue.
https://www.arduino.cc/reference/en/lan … esolution/
By default, resolution is well 10 bits.
Conversion is done in 12bits but mapped to 10.
As mentioned in the Arduino API reference:
The Due, Zero and MKR Family boards have 12-bit ADC capabilities that can be accessed by changing the resolution to 12. This will return values from analogRead() between 0 and 4095.
So user have to explicitly request 12 bits.
// change the resolution to 12 bits
analogReadResolution(12);

BennehBoy
Sun Jan 13, 2019 3:26 pm
My bad, thanks for pointing that out.

fredbox
Fri Feb 15, 2019 11:26 pm
After reading thorough this thread, I’m still confused.

Examples:
digitalWrite(PC13,0) turns on the LED on a blue pill.
digitalWrite(PC_13,0) does not.

Serial.print(PC13) prints 17.
Serial.print(PC_13) prints 45.

digitalWriteFast(PC13,0) gives a compile error
digitalWriteFast(PC_13,0) compiles but does not turn on the LED


fpiSTM
Sat Feb 16, 2019 2:54 pm
PXn is the pin number as in all Arduino API.
PY_n is a type pinname, it represent the GPIO port and bit.

That’s why they have not the same value.

digitalWrite(PC13,0); // turns on the LED on a blue pill. --> ok as this API use the pin number
digitalWrite(PC_13,0); // does not. --> not ok as this is the piname while it waits the pin number.

digitalWriteFast(PC13,0); // gives a compile error --> compiler wait a pinname type not a pin number so this is ok
digitalWriteFast(PC_13,0); // compiles but does not turn on the LED --> this should while the pin has been configured before using pinmode(PC13, OUTPUT);


fredbox
Sat Feb 16, 2019 4:36 pm
I was using pinMode(PC_13,OUTPUT) for testing digitalWriteFast().

It does work as you describe for pinMode(PC13,OUTPUT) followed by digitalWriteFast(PC_13,x).

It would make more sense if pinMode() understood both formats.


fredbox
Sat Feb 16, 2019 5:34 pm
I found a macro in pins_arduino.h to do the conversion: #define digitalPinToPinName(p) ...

fpiSTM
Sat Feb 16, 2019 6:36 pm
[fredbox – Sat Feb 16, 2019 4:36 pm] –

It would make more sense if pinMode() understood both formats.

Unfortunately, this could not be done as pinMode is a C API and official Arduino API.
MAybe convert digital API to C++ could be a solution.


Leave a Reply

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