Skip to main content
amomum
Associate III
August 21, 2017
Question

Bugs in stm32f10x LL library

  • August 21, 2017
  • 5 replies
  • 1705 views
Posted on August 21, 2017 at 14:16

I tried to use LL library for stm32f10x without CubeMX (  * @version V1.1.1  * @date: 12-May-2017) and almost immediately found some problems:

1) You can't actually download LL library without CubeMX, even if you don't want to use Cube. That's not a but, that's just irritating.

2) It seems that you can't enable clocking of any periphery because there is no equivalent of RCC_AHBPeriphClockCmd in ll_rcc module.

3) If I enabled GPIO blocking with something like

RCC->APB2ENR |= RCC_APB2ENR_IOPCEN;

and then try to do:

    RCC->APB2ENR |= RCC_APB2ENR_IOPCEN;

    

    LL_GPIO_InitTypeDef initStruct;

    LL_GPIO_StructInit( &initStruct );

    

    initStruct.Mode = LL_GPIO_MODE_OUTPUT_10MHz;

    initStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;

    initStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;

    initStruct.Pin = LL_GPIO_PIN_9; // that equals 0x04020002

    

    LL_GPIO_Init( GPIOC, &initStruct )

This code will actually init PC.2 to output push-pull.

Why? LL_GPIO_Init does this:

    pinpos = POSITION_VAL(GPIO_InitStruct->Pin);

where

    #define POSITION_VAL(VAL)     (__CLZ(__RBIT(VAL)))

obviously, pinpos will be equal to 1.

Then current pin will be calculated like this:

    currentpin = (GPIO_InitStruct->Pin) & (0x00000101U << pinpos);

so currentpint will be equal to 2.

And then

    LL_GPIO_SetPinMode(GPIOx, currentpin, GPIO_InitStruct->Mode);

will be called, despite the fact that LL_GPIO_SetPinMode should accept parameters like LL_GPIO_PIN_x.

4) And here we have another 'bug' - all inline functions in header files do not check their arguments with assert_param!

I'm actually startled, how something as simple as this can be broken and not tested?! Or maybe i'm horribly wrong and just using LL library in the wrong way?

    This topic has been closed for replies.

    5 replies

    After Forever
    Senior III
    August 21, 2017
    Posted on August 21, 2017 at 14:53

    1. Isn't it bundled with

    http://www.st.com/content/st_com/en/products/embedded-software/mcus-embedded-software/stm32-embedded-software/stm32cube-embedded-software/stm32cubef1.html

    ?

    2. That's not true, look at the numerous examples at STM32Cube_FW_F1_V1.6.0/Projects/STM32F103RB-Nucleo/Examples_LL

    4. Maybe this is deliberate. LL is a lightweight and advanced library, you should know what you are doing. assert_params would use a lot of space if used in every inline function, there was a case when I couldn't use the default debug build of a project with HAL because assert_params use too much flash.

    amomum
    amomumAuthor
    Associate III
    August 21, 2017
    Posted on August 21, 2017 at 16:00

    1) I can't see a big difference between CubeF1 and CubeMX. I still can't just download the sources of the library, I have to generate a project and install unnecessary software.

    2) My bad, haven't looked in the bus.h.

    3) That's my main concern here.

    4) assert_params are already optional. We need them at the debug stage, we disable them after all stupid bugs are fixed. I would prefer having them everywhere.

    After Forever
    Senior III
    August 21, 2017
    Posted on August 21, 2017 at 16:16

    1) Well there is a big difference. CubeMX is the software, whereas, last time I checked, CubeFx and CubeLx are only the archived library files (with their examples, documentation, etc) without the 'unnecessary software'.

    3) I can't look at it right now to try to confirm/deny the bug, maybe somebody else can help.

    4) I tend to agree.

    Max Zulus
    Visitor II
    December 1, 2017
    Posted on December 01, 2017 at 02:54

    3. LL F1 series lib has an error in the configuration function LL_GPIO_Init. You can fix it or do not use. Unfortunately, I just study the library for academic purposes and can not guarantee the working capacity after correction. But you can try written 

    '>> 8' 

    in two places:

    /* Initialize pinpos on first pin set */

    pinpos = POSITION_VAL((GPIO_InitStruct->Pin>>8));

    /* Configure the port pins */

    while ((((GPIO_InitStruct->Pin>>8) & 0x0000FFFFU) >> pinpos) != 0x00000000U)