cancel
Showing results for 
Search instead for 
Did you mean: 

Can LL_GPIO_Init() initialize multiple pins at once?

waclawek.jan
Super User

In an inherited code I see LL_GPIO_Init() being called with pin definitions (LL_GPIO_PIN_xx) OR-ed together, presumably to define multiple pins of the same port to the same settings, in one call of the function.

The documentation (doxygen header) to LL_GPIO_Init() does not say this is allowed; neither says so the description of the init struct. Is there any authoritative documentation which allows this?

Thanks,

JW

 

4 REPLIES 4
Andrew Neil
Super User

I've always found this to be unclear in both HAL and LL documentation.

It's never clear whether a "pin" parameter represents a pin number (so can only be a single pin), or a bitmask (so could represent multiple pins) - and both are used in various places.

 

PS:

See: https://community.st.com/t5/stm32-mcus-embedded-software/array-for-gpio-pins/m-p/654354/highlight/true#M46755

But the documentation:

AndrewNeil_0-1749633364422.png

Is not at all clear that GPIO_Pin is a bitmask.

A complex system that works is invariably found to have evolved from a simple system that worked.
A complex system designed from scratch never works and cannot be patched up to make it work.

In this case, neither of them, LL_GPIO_PIN_xx definitions contain multiple (three?) fields, neither of them is pin number and only one of them is the pin mask.

Nonetheless, LL_GPIO_Init() as it is now *is* written with the multiple-pins-at-once in mind; however, I am hesitant to rely on that once there's not a single iota hinting toward this option in the documentation I know of.

JW

I think those definitions do boil down to a bitmask for each pin:

/** @defgroup GPIO_LL_EC_PIN PIN
  * @{
  */
#define LL_GPIO_PIN_0                    ((GPIO_BSRR_BS0  << GPIO_PIN_MASK_POS) | 0x00000001U)  /*!< Select pin 0  */
#define LL_GPIO_PIN_1                    ((GPIO_BSRR_BS1  << GPIO_PIN_MASK_POS) | 0x00000002U)  /*!< Select pin 1  */
#define LL_GPIO_PIN_2                    ((GPIO_BSRR_BS2  << GPIO_PIN_MASK_POS) | 0x00000004U)  /*!< Select pin 2  */
#define LL_GPIO_PIN_3                    ((GPIO_BSRR_BS3  << GPIO_PIN_MASK_POS) | 0x00000008U)  /*!< Select pin 3  */

 

Especially given the final "ALL" definition:

#define LL_GPIO_PIN_ALL                  (LL_GPIO_PIN_0  | LL_GPIO_PIN_1  | LL_GPIO_PIN_2  | \
                                          LL_GPIO_PIN_3  | LL_GPIO_PIN_4  | LL_GPIO_PIN_5  | \
                                          LL_GPIO_PIN_6  | LL_GPIO_PIN_7  | LL_GPIO_PIN_8  | \
                                          LL_GPIO_PIN_9  | LL_GPIO_PIN_10 | LL_GPIO_PIN_11 | \
                                          LL_GPIO_PIN_12 | LL_GPIO_PIN_13 | LL_GPIO_PIN_14 | \
                                          LL_GPIO_PIN_15)                                      /*!< Select all pins */

 

But, indeed, this still doesn't guarantee that any particular function/macro taking them as a parameter will actually work with a multi-pin pattern.

 

So, indeed, this documentation needs to be clarified.

Throughout.

A complex system that works is invariably found to have evolved from a simple system that worked.
A complex system designed from scratch never works and cannot be patched up to make it work.
waclawek.jan
Super User

> I think those definitions do boil down to a bitmask for each pin

Only bits 8..24 are the actual pin mask, filled by (GPIO_BSRR_BSx << GPIO_PIN_MASK_POS)

Bits 0..7 (which in itself wouldn't be sufficient for a mask for all 16 pins) is something like "(half of) shift within one of the CRL/CRH registers" (this is 'F1, very different from other STM32; but in other STM32 that 8-bit mask is "shift wihin one of the ARL/ARH registers).

Then there's a flag somewhere at 26th bit which probably is "index" distinguishing between CRL/CRH. I am not going to dig deeper.

> Especially given the final "ALL" definition

The only purpose of the "ALL" is to be used in the "checker" macro, where it verifies that at least one of those 3 fields is nonzero and all other bits not occupied by those fileds are zero.

 

The HAL_GPIO_WritePin() you've quoted above *is* different from the initialization and it may indeed require only one pin at a time (not going to dig into that either).

JW