cancel
Showing results for 
Search instead for 
Did you mean: 

STM32CubeMX LL Code Generating Bug when the Flash Interrupt is Enabled

I use STM32L0 series microcontroller with LL and CMSIS libraries, no HAL is selected in the advanced settings tab, only LL.

And still, when I enable the "Flash and EEPROM global interrupt" in the Configuration -> NVIC, STM32CubeMX starts using the HAL library and generating code for it. As I understand, LL (at least for STM32L0) misses a module for working with Flash, but still, I think this is a bug.

8 REPLIES 8
Khouloud GARSI
Lead II

Hi @After Forever​ ,

Thanks for your feedback!

It is reported internally for further check.

Khouloud.

Cyril FENARD
ST Employee

Hi @After Forever​ ,

 May you check your application's map file and verify there is something like the following:

.text.HAL_FLASH_IRQHandler
 
        0x08000688   0x110 Drivers/STM32L0xx_HAL_Driver/stm32l0xx_hal_flash.o
 
        0x08000688        HAL_FLASH_IRQHandler

  There is no LL code for FLASH, but please you may have look at stm32l0xx_hal_flash_ex.c, stm32l0xx_hal_flash_ramfunc.c, stm32l0xx_hal_flash.c files to write your application.

 You can also have a look in examples of CubeFW folders, i.e. STM32Cube_FW_L0_V1.11.0RC3\Projects\[NUCLEO-EVAL]\Examples\FLASH\...

 Hoping it helps.

 Regards.

 Cyril

Hi @Cyril FENARD​ 

More information: I have checked "Copy only the necessary library files" radio-button and "Generate peripheral initialization as a pair of '*c/*.h' files" checkbox.

After enabling the "Flash and EEPROM global interrupt" in the NVIC configuration window and re-generating the code I noticed that STM32CubeMX generated this function in stm32l0xx_it.c:

void FLASH_IRQHandler(void)
{
  /* USER CODE BEGIN FLASH_IRQn 0 */
 
  /* USER CODE END FLASH_IRQn 0 */
  HAL_FLASH_IRQHandler();
  /* USER CODE BEGIN FLASH_IRQn 1 */
 
  /* USER CODE END FLASH_IRQn 1 */
}

...and the stm32l0xx_hal_* files in the Drivers/STM32L0xx_HAL_Driver/Src directory. I don't have any HAL library selected, only LL. So this was an error, and I didin't even try to compile the code in this state (so can't look at the map file), because the existence of HAL makes my binary bigger than the Flash size of my microcontroller.

So I un-checked the "Flash and EEPROM global interrupt" in the NVIC configuration window, re-generating the code, this removed every mention of HAL from the code. Then I added a custom FLASH_IRQHandler function in one of the user code section in stm32l0xx_it.c, also another user function to enable the interrupt:

void FLASH_IRQHandler(void)
{
    if ((FLASH->SR & FLASH_SR_EOP)) {
        FLASH->SR = FLASH_SR_EOP;
        flash_eop_callback();
    } else if ((FLASH->SR & FLASH_SR_FWWERR)) {
        FLASH->SR = FLASH_SR_FWWERR;
        flash_error_callback(FLASH_SR_FWWERR);
    } else if ((FLASH->SR & FLASH_SR_NOTZEROERR)) {
        FLASH->SR = FLASH_SR_NOTZEROERR;
        flash_error_callback(FLASH_SR_NOTZEROERR);
    } else if ((FLASH->SR & FLASH_SR_SIZERR)) {
        FLASH->SR = FLASH_SR_SIZERR;
        flash_error_callback(FLASH_SR_SIZERR);
    } else if ((FLASH->SR & FLASH_SR_WRPERR)) {
        FLASH->SR = FLASH_SR_WRPERR;
        flash_error_callback(FLASH_SR_WRPERR);
    } else if ((FLASH->SR & FLASH_SR_RDERR)) {
        FLASH->SR = FLASH_SR_RDERR;
        flash_error_callback(FLASH_SR_RDERR);
    } else if ((FLASH->SR & FLASH_SR_OPTVERR)) {
        FLASH->SR = FLASH_SR_OPTVERR;
        flash_error_callback(FLASH_SR_OPTVERR);
    } else if ((FLASH->SR & FLASH_SR_PGAERR)) {
        FLASH->SR = FLASH_SR_PGAERR;
        flash_error_callback(FLASH_SR_PGAERR);
    } else {
        flash_error_callback(FLASH_UNKNOWN_ERROR);
    }
}
 
void flash_init(void)
{
    NVIC_SetPriority(FLASH_IRQn, 1);
    NVIC_EnableIRQ(FLASH_IRQn);
}

Cyril FENARD
ST Employee

 Hi @After Forever​ ,

May you try to compile the project from CubeMX, all HAL/LL objects will be generated, and then inspect result of your link. It should fit your flash memory, embedding only the code that is needed for the application. 

 Hoping it helps.

 Regards.

 Cyril

Hello @Cyril FENARD​ 

I did what you asked, and as was expected, the map file has several HAL functions and objects in it (like HAL_InitTick, HAL_Init, HAL_IncTick, HAL_NVIC_SetPriority, HAL_FLASH_IRQHandler, etc...):

 .text.HAL_InitTick
                0x000000000800c4b0       0x28 /home/sweden/projects/stm32l0-test/build/stm32l0xx_hal.c.o
                0x000000000800c4b0                HAL_InitTick
 .text.HAL_Init
                0x000000000800c4d8       0x20 /home/sweden/projects/stm32l0-test/build/stm32l0xx_hal.c.o
                0x000000000800c4d8                HAL_Init
 .text.HAL_IncTick
                0x000000000800c4f8       0x10 /home/sweden/projects/stm32l0-test/build/stm32l0xx_hal.c.o
                0x000000000800c4f8                HAL_IncTick
 .text.c
                0x000000000800c508       0x74 /home/sweden/projects/stm32l0-test/build/stm32l0xx_hal_cortex.c.o
                0x000000000800c508                HAL_NVIC_SetPriority
 .text.HAL_NVIC_EnableIRQ
                0x000000000800c57c       0x24 /home/sweden/projects/stm32l0-test/build/stm32l0xx_hal_cortex.c.o
                0x000000000800c57c                HAL_NVIC_EnableIRQ
 .text.HAL_SYSTICK_Config
                0x000000000800c5a0       0x34 /home/sweden/projects/stm32l0-test/build/stm32l0xx_hal_cortex.c.o
                0x000000000800c5a0                HAL_SYSTICK_Config
 .text.HAL_SYSTICK_Callback
                0x000000000800c5d4        0x2 /home/sweden/projects/stm32l0-test/build/stm32l0xx_hal_cortex.c.o
                0x000000000800c5d4                HAL_SYSTICK_Callback
 .text.HAL_SYSTICK_IRQHandler
                0x000000000800c5d6        0x8 /home/sweden/projects/stm32l0-test/build/stm32l0xx_hal_cortex.c.o
                0x000000000800c5d6                HAL_SYSTICK_IRQHandler
 *fill*         0x000000000800c5de        0x2 
 .text.FLASH_SetErrorCode
                0x000000000800c5e0       0xa8 /home/sweden/projects/stm32l0-test/build/stm32l0xx_hal_flash.c.o
 .text.HAL_FLASH_EndOfOperationCallback
                0x000000000800c688        0x2 /home/sweden/projects/stm32l0-test/build/stm32l0xx_hal_flash.c.o
                0x000000000800c688                HAL_FLASH_EndOfOperationCallback
 .text.HAL_FLASH_OperationErrorCallback
                0x000000000800c68a        0x2 /home/sweden/projects/stm32l0-test/build/stm32l0xx_hal_flash.c.o
                0x000000000800c68a                HAL_FLASH_OperationErrorCallback
 .text.HAL_FLASH_IRQHandler
                0x000000000800c68c       0xe0 /home/sweden/projects/stm32l0-test/build/stm32l0xx_hal_flash.c.o
                0x000000000800c68c                HAL_FLASH_IRQHandler
 .text.FLASH_PageErase
                0x000000000800c76c       0x2c /home/sweden/projects/stm32l0-test/build/stm32l0xx_hal_flash_ex.c.o
                0x000000000800c76c                FLASH_PageErase
 .text.LL_EXTI_Init
                0x000000000800c798       0xf4 /home/sweden/projects/stm32l0-test/build/stm32l0xx_ll_exti.c.o
                0x000000000800c798                LL_EXTI_Init
 .text.LL_GPIO_Init
                0x000000000800c88c      0x150 /home/sweden/projects/stm32l0-test/build/stm32l0xx_ll_gpio.c.o
                0x000000000800c88c                LL_GPIO_Init
 .text.LL_I2C_Init
                0x000000000800c9dc      0x118 /home/sweden/projects/stm32l0-test/build/stm32l0xx_ll_i2c.c.o
                0x000000000800c9dc                LL_I2C_Init
 .text.RCC_GetHCLKClockFreq
                0x000000000800caf4       0x18 /home/sweden/projects/stm32l0-test/build/stm32l0xx_ll_rcc.c.o
                0x000000000800caf4                RCC_GetHCLKClockFreq
 .text.RCC_GetPCLK1ClockFreq
                0x000000000800cb0c       0x18 /home/sweden/projects/stm32l0-test/build/stm32l0xx_ll_rcc.c.o
                0x000000000800cb0c                RCC_GetPCLK1ClockFreq
 .text.RCC_GetPCLK2ClockFreq
                0x000000000800cb24       0x18 /home/sweden/projects/stm32l0-test/build/stm32l0xx_ll_rcc.c.o
                0x000000000800cb24                RCC_GetPCLK2ClockFreq
 .text.RCC_PLL_GetFreqDomain_SYS
                0x000000000800cb3c       0x3c /home/sweden/projects/stm32l0-test/build/stm32l0xx_ll_rcc.c.o
                0x000000000800cb3c                RCC_PLL_GetFreqDomain_SYS
 .text.RCC_GetSystemClockFreq
                0x000000000800cb78       0x48 /home/sweden/projects/stm32l0-test/build/stm32l0xx_ll_rcc.c.o
                0x000000000800cb78                RCC_GetSystemClockFreq
 .text.LL_RCC_GetSystemClocksFreq
                0x000000000800cbc0       0x20 /home/sweden/projects/stm32l0-test/build/stm32l0xx_ll_rcc.c.o
                0x000000000800cbc0                LL_RCC_GetSystemClocksFreq
 .text.LL_RCC_GetUSARTClockFreq
                0x000000000800cbe0       0xb8 /home/sweden/projects/stm32l0-test/build/stm32l0xx_ll_rcc.c.o
                0x000000000800cbe0                LL_RCC_GetUSARTClockFreq
 .text.LL_RTC_EnterInitMode
                0x000000000800cc98       0x70 /home/sweden/projects/stm32l0-test/build/stm32l0xx_ll_rtc.c.o
                0x000000000800cc98                LL_RTC_EnterInitMode

But my issue is that I don't want to use HAL, I selected only LL so I expect only LL and CMSIS functions in my linked binary. Don't you think this is a bug? Thank you!

0690X000006C8f3QAC.png

Cyril FENARD
ST Employee

Hi @After Forever​ ,

 Your feedback is in line with the implementation of the CubeMX tool.

 Minimum code elementary initialization uses HAL implementation. This is not a problem and you can still use LL implementation for IPs, depending on your choice.

 Regards.

 Cyril

@Cyril FENARD​ 

> Your feedback is in line with the implementation of the CubeMX tool.

Thank you for your time. Please let me (as my last resort about this issue) express my opinion that in cases when HAL is not being used that "implementation" is not logical, and here is why:

  1. Although ST mentions the "Possible concurrent usage of HAL and LL" with some limitations, LL is marketed as a lightweight alternative to HAL, not a supplement. I didn't select the HAL library anywhere (as shown in the screenshot posted previously), and yet it's being used
  2. Confusion, as LL is lightweight and for example it doesn't come with its own systick handler implementing a global millisecond counter, so it was implemented in the user code. Now, after enabling the flash interrupt, CubeMX inserted HAL with its own systick handler which conflicts with mine.
  3. Unnecessary, why do we need HAL's FLASH_IRQHandler with its callbacks (that would be useful only when the firmware in fact uses the HAL functions) for a simple interrupt handler where HAL is not required anywhere else in the firmware? Just generate an empty FLASH_IRQHandler interrupt handler function with user code sections, and 2 lines of code somewhere to set the priority and enable the interrupt. And that's everything required.

Thank you again.

Cyril FENARD
ST Employee

Hi @After Forever​ ,

I understand your last point, I will ask for improvements in future versions. 

Regards.

Cyril