BUG in STM32F1xx_ll_gpio driver (STM32Cube_FW_F1_V1.8.3) in regards to Push/Pull resistor settings on PUSHPULL OUTPUT
Dear readers,
It has taken me quit a lot of time and rewrites to get this working (using STMCUBE IDE V1.5 and LL libraries V1.8.3, for a STM32F103VB).
When initializing the GPIO pins for PUSHPULL outputs i want to make sure that the pins initialize with the correct output level.
So before i call LL_GPIO_INIT( GPIOD, &GPIO_InitStruct ) i call LL_GPIO_SetOutputPin( GPIOD, _ERROR_Pin );
However after the INIT the pins are LOW even after i set them (to HIGH).
The way i see it:
- in the LL_GPIO_Init() function something goes wrong
This functions (always) calls:
LL_GPIO_SetPinPull(GPIOx, currentpin, GPIO_InitStruct->Pull); to configure pull up or down resistors, that does not make much sense if we have a push pull output configuration, but should not be a problem, however, this function does not write to the (input) push pull settings (in the CRL / CNFx registers) it writes to the ODR register (setting or resetting the output state):
__STATIC_INLINE void LL_GPIO_SetPinPull(GPIO_TypeDef *GPIOx, uint32_t Pin, uint32_t Pull)
{
MODIFY_REG(GPIOx->ODR, (Pin >> GPIO_PIN_MASK_POS), Pull << (POSITION_VAL(Pin >> GPIO_PIN_MASK_POS)));
}Running the following code and stepping through it while viewing the GPIOD ODR SFRs clearly shows the ouput pin being set (by LL_GPIO_SetOutputPin()) and next being reset (by LL_GPIO_SetPinPull())
#define _HEARTBEAT_Pin LL_GPIO_PIN_0
#define _ERROR_Pin LL_GPIO_PIN_1LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
// GPIO Ports Clock Enable
LL_APB2_GRP1_EnableClock( LL_APB2_GRP1_PERIPH_GPIOC );
LL_APB2_GRP1_EnableClock( LL_APB2_GRP1_PERIPH_GPIOD );
LL_APB2_GRP1_EnableClock( LL_APB2_GRP1_PERIPH_GPIOE );
LL_GPIO_SetOutputPin( GPIOD, _ERROR_Pin ); // does NOT WORK prior to LL_GPIO_INIT
LL_GPIO_SetOutputPin( GPIOD, _HEARTBEAT_Pin ); // does NOT WORK prior to LL_GPIO_INIT
GPIO_InitStruct.Pin = _HEARTBEAT_Pin | _ERROR_Pin;
GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
LL_GPIO_Init( GPIOD, &GPIO_InitStruct );When i (temporarily) disable the call for LL_GPIO_SetPinPull() in LL_GPIO_Init() it works as intended.
My suggestion / solution (for now) is as follows:
- In LL_GPIO_Init() change the call to SetPinPull() like this:
if( GPIO_InitStruct->OutputType != LL_GPIO_OUTPUT_PUSHPULL ) // Skip pull up or down resistor setting if OutputType == LL_GPIO_OUTPUT_PUSHPULL
LL_GPIO_SetPinPull( GPIOx, currentpin, GPIO_InitStruct->Pull ); // Pull-up Pull-down resistor configuration
LL_GPIO_SetPinMode( GPIOx, currentpin, GPIO_InitStruct->Mode ); // Pin Mode configurationThe real solution would be to change the LL_GPIO_SetPinPull() routine but i assume it works for inputs (i have not tested that) so i left that alone for now.
Am i the only one having this problem and am i doing something wrong or is this a bug?
