2025-06-11 1:57 AM - edited 2025-06-11 2:04 AM
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
2025-06-11 2:06 AM - edited 2025-06-11 2:17 AM
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:
But the documentation:
Is not at all clear that GPIO_Pin is a bitmask.
2025-06-11 2:13 AM
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
2025-06-11 2:22 AM
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.
2025-06-11 2:38 AM - edited 2025-06-11 2:40 AM
> 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