Skip to main content
Graduate II
July 16, 2025
Question

Nucleo-L433RC-P: Debug fails on first attempt but works on second

  • July 16, 2025
  • 8 replies
  • 1216 views

I am developing software on the Nucleo-L433RC-P board but have a strange situation when debugging.

The first time I debug, the software does not run and I get the following error...

 

Break at address "0x1fff2ce8" with no debug information available, or outside of program code.

Break at address "0x1fff2cd6" with no debug information available, or outside of program code.

 

As shown in the screenshot below...

Monosnap Voice - Source not found. - STM32CubeIDE 2025-07-16 19-34-31.png

However, the second time I debug it works correctly.

Why does it not work correctly on the first debug, but then works correctly on the second debug ?

I have tried two different boards (one of which is brand new and never been used) but the behaviour is the same, so it must be a software issue.

    This topic has been closed for replies.

    8 replies

    Graduate II
    July 16, 2025

    That's from the ROM, so either the BOOT0 is HIGH, or the FLASH is blank and doesn't contain viable vector table, so goes to ROM code instead.

    freeflyerAuthor
    Graduate II
    July 16, 2025

    BOOT0 is pulled low via a 10k resistor on this board and the pin on the header is floating

     

    freeflyer_0-1752700295314.png

     

    why would the flash be blank when I debug ?

     

    Graduate II
    July 16, 2025

    Well, depends on the sequencing, but if you erase, and reset, this determination may be sticky and require a power-cycle to clear on some STM32 parts. Relates to how it latches option bytes, and protects against code recovery attacks.

    You'd want to look at the connection options chosen in the programmer.

    The debugger might be resetting to gain control of the part, or to get a clear start.

    The key take-away is that it's running code from ROM rather than FLASH, and has no source code to associate to that.

    You could perhaps try a different debugger, or check firmware version in ST-LINK

    freeflyerAuthor
    Graduate II
    July 16, 2025

    When I plugged the new board in the firmware for the stlink did an update to the latest version

    I just click the debug button.In STM32CubeIDE, I don’t manually erase

    Could it be a bug in the stlink firmware?

    This problem occurs on two different boards and one is brand new

    Graduate II
    July 16, 2025

    Not sure if it matters if the boards are new, or not

    https://www.st.com/resource/en/reference_manual/rm0394-stm32l41xxx42xxx43xxx44xxx45xxx46xxx-advanced-armbased-32bit-mcus-stmicroelectronics.pdf#page=78

    There are boot setting in the Option Bytes, and it checks for 0xFFFFFFFF patterns in the vector table.

    Does your code work reliably out of a power cycle? That's the primary thing to worry about.

    When the debugger is erasing, resetting and break-pointing it could well trigger annoying behaviours in the part and it's protection methods. Not sure I'd spend too much time fighting these shadows. You could make a boot loader that gates access to an application firmware you develop deeper into the FLASH, and then the block/sector at 0x08000000 wouldn't need to get erased in your crash-n-burn debug cycle.

     

    freeflyerAuthor
    Graduate II
    July 17, 2025

    I have attached my project (Software.zip) and hoping someone could have a look to see whats causing this please?

    It only happens with my project, so there is something wrong with it.

    If I step through the code from the first line in main, which starts with "HAL_Init();" and step line by line to the while(1) loop, it works correctly every time.

    However, if I resume (F8) from the start of the code then this issue occurs, where after each debug flash it alternately fails and goes to ROM or works correctly.

    I dont have confidence in developing my software futher as Im concerned this problem could be causing other problems.

    I am currently trying to implement shutdown, but for now I have commented out the call to shutdown.

    Thanks in advance

    freeflyerAuthor
    Graduate II
    July 19, 2025

    I have found where the problem is occuring, but dont know why.

    Once I have flashed the device and step through the code, it fails (alterntately) on the function 'w25qxx_init' which initialises the external flash device (W25Q128)...

     

    w25qxx_init(&w25qxx, &hspi2, GPIOB, GPIO_PIN_6);

     

    This is the function... 

     

    #ifdef W25QXX_QSPI
    W25QXX_result_t w25qxx_init(W25QXX_HandleTypeDef *w25qxx, QSPI_HandleTypeDef *qhspi) {
    #else
    W25QXX_result_t w25qxx_init(W25QXX_HandleTypeDef *w25qxx, SPI_HandleTypeDef *hspi, GPIO_TypeDef *cs_port, uint16_t cs_pin) {
    #endif
    
     W25QXX_result_t result = W25QXX_Ok;
    
     W25_DBG("w25qxx_init");
    
     char *version_buffer = malloc(strlen(W25QXX_VERSION) + 1);
     if (version_buffer) {
     sprintf(version_buffer, "%s", W25QXX_VERSION);
     free(version_buffer);
     }
    
    #ifdef W25QXX_QSPI
     w25qxx->qspiHandle = qhspi;
    #else
     w25qxx->spiHandle = hspi;
     w25qxx->cs_port = cs_port;
     w25qxx->cs_pin = cs_pin;
    
     cs_off(w25qxx);
    #endif
    
     uint32_t id = w25qxx_read_id(w25qxx);
     if (id) {
     w25qxx->manufacturer_id = (uint8_t) (id >> 16);
     w25qxx->device_id = (uint16_t) (id & 0xFFFF);
    
     switch (w25qxx->manufacturer_id) {
     case W25QXX_MANUFACTURER_GIGADEVICE:
    
     w25qxx->block_size = 0x10000;
     w25qxx->sector_size = 0x1000;
     w25qxx->sectors_in_block = 0x10;
     w25qxx->page_size = 0x100;
     w25qxx->pages_in_sector = 0x10;
    
     switch (w25qxx->device_id) {
     case 0x6017:
     w25qxx->block_count = 0x80;
     break;
     default:
     W25_DBG("Unknown Giga Device device");
     result = W25QXX_Err;
     }
    
     break;
     case W25QXX_MANUFACTURER_WINBOND:
    
     w25qxx->block_size = 0x10000;
     w25qxx->sector_size = 0x1000;
     w25qxx->sectors_in_block = 0x10;
     w25qxx->page_size = 0x100;
     w25qxx->pages_in_sector = 0x10;
    
     switch (w25qxx->device_id) {
     case 0x4018:
     w25qxx->block_count = 0x100;
     break;
     case 0x4017:
     w25qxx->block_count = 0x80;
     break;
     case 0x4016:
     w25qxx->block_count = 0x40;
     break;
     default:
     W25_DBG("Unknown Winbond device");
     result = W25QXX_Err;
     }
    
     break;
     default:
     W25_DBG("Unknown manufacturer");
     result = W25QXX_Err;
     }
     } else {
     result = W25QXX_Err;
     }
    
     if (result == W25QXX_Err) {
     // Zero the handle so it is clear initialization failed!
     memset(w25qxx, 0, sizeof(W25QXX_HandleTypeDef));
     }
    
     return result;
    
    }

     

    When I step through the 'w25qxx_init' function, it fails on this line....

     

     char *version_buffer = malloc(strlen(W25QXX_VERSION) + 1);

     

    This never used to happen in the early stages of development, I have added further code and peripherals since then so don't know why w25qxx_init would suddenly cause this issue ?

    Graduate II
    July 19, 2025

    So you think this is an issue with the string library or the dynamic memory allocation?

    Fails How? Hard Faults or loops somewhere else?

    Is this code necessary? You're not outputting the message, and creating a strmalloc() type function with malloc/strcpy might be more efficient

    freeflyerAuthor
    Graduate II
    July 19, 2025

    It fails on line 168 of the 'w25qxx_init' function and then the debugger crashes.  When I pause the debugger it appears to go outside the flash area with the error "Break at address "0x1fff2d24" with no debug information available, or outside of program code."

     

    freeflyer_0-1752934684286.png

     

    freeflyer_1-1752934742329.png

     

     

    I did not write the w25qxx driver, I got the driver from here...

    https://github.com/mengguang/w25qxx

    I do not understand what this line is doing anyway....

     char *version_buffer = malloc(strlen(W25QXX_VERSION) + 1);

     

    Its strange how it also happens alternately

    First debug flash and it fails, second debug flash and it works and so on....

    freeflyerAuthor
    Graduate II
    July 19, 2025

    Thanks all, how do I enable Full Chip Erase and ensure my debug configuration includes program loading before starting execution ?

    I cant see any options for those in the debugger settings ?

     

    freeflyer_0-1752935365969.png

    freeflyer_1-1752935387443.png

    freeflyer_2-1752935441767.png

     

    freeflyerAuthor
    Graduate II
    August 28, 2025

    Thanks michaeljyti, the point at which the program fails when stepping though the code was a red herring.

    As my code developed. the program failed at a different points in the program.

    The stack size is the default setting, I have not changed this...

    _Min_Heap_Size = 0x200; /* required amount of heap */
    _Min_Stack_Size = 0x400; /* required amount of stack */

    freeflyer_0-1756384017685.png

    I have never used stack painting so will need to look further into this.

    If the stack size was incorrect, then wouldn't it fail every time ?

    The flashing fails the first time but works the next time, it alternatively fails and works.

    So why would an incorrect stack size cause this ?

     

     

    freeflyerAuthor
    Graduate II
    September 7, 2025

    This is driving me crazy, espeically as I am trying to get a custom bootloader to work too.

    I checked the stack and its well within the limits....

    freeflyer_0-1757262349718.png

    Below is the code snipet to check the stack...

    static uint32_t stack_used;
    static uint32_t stack_free;
    static uint32_t stack_used_max;
    static uint32_t stack_free_max;
    
    int main(void)
    {
     HAL_Init();
     SystemClock_Config();
     Stack_Paint();
    ...
    ...
    ...
    }
    
    
    void Stack_Paint(void) {
     uint32_t *p = &_stack_end;
     while (p < &_estack) {
     *p++ = 0xA5A5A5A5; // fill with pattern
     }
    }
    
    uint32_t Stack_GetUsage(void) {
     extern uint32_t _stack_end;
     extern uint32_t _estack;
     uint32_t *p = &_stack_end;
     while (p < &_estack && *p == 0xA5A5A5A5) {
     p++;
     }
     stack_used = (&_estack - p) * sizeof(uint32_t); // bytes used
     if (stack_used > stack_used_max)
     {
     	stack_used_max = stack_used;
     }
    }
    
    uint32_t Stack_GetFree(void) {
     extern uint32_t _stack_end;
     extern uint32_t _estack;
     uint32_t *p = &_stack_end;
     while (p < &_estack && *p == 0xA5A5A5A5) {
     p++;
     }
     stack_free = (p - &_stack_end) * sizeof(uint32_t); // free space in bytes
     if (stack_free > stack_free_max)
     {
     	stack_free_max = stack_used;
     }
    }

     

    Stack_GetUsage and Stack_GetFree is called in a 100ms task and the program is left to run for several minutes.

    I've written a custom bootloader and a simple application that flashes an LED, I can successfully flash the application using the bootloader.

     

    However, when I try to flash the application for this project, although it flashes successfully it does not run the application.  I don't know whether the application has the same issue, where it does not work the first time its flashed but does work the second time its flash.  However, I cant test this because the application is used to call the bootloader, so when it does not work the flash then its not possible to go back to the bootloader.