0
votes

Update :

Problem with a STM32L4 board that sometimes won't run after DFU update, jump to Edit 2 for short story & example code.

I'm working on a project using a custom board based on a STM32L4. I've been having issues when formatting strings before sending them over USB.
The issue happens when updating the mcu using DFU over USB, everything works fine in debug mode (using STLink).
When passing more than 3 arguments to sprintf, the mcu leaves DFU mode but the app never starts (no init steps, no run, nothing).

I've tracked down the line that causes the issue:

    sprintf(tx_buffer, "Hello World: %ld/%ld/%ld\r\n", 1,2,3); // OK
    sprintf(tx_buffer, "Hello World: %ld/%ld/%ld, %ld\r\n", 1,2,3, 4); // NOK
    sprintf(tx_buffer, "Hello World: %d/%d/%d\r\n", 1,2,3); // NOK

tx_buffer is a simple char tx_buffer[255].

It seems that adding too many arguments and/or choosing certain types causes problem.

The issue is that for the NOK cases, the app won't even start, no init whatsoever whereas in other cases it works fine.
For any case, in debug mode, everything runs fine.

Is there a limit to the arguments or types that can be used with sprintf for STM32?
Has anyone experienced this issue or has ideas on how to solve this.

Note : There is only a LED that allows me to tell if I'm in init/running or not.
Error handlers or HardFault handlers make the LED blink to a specific pattern that I have never observe when the app does not seem to boot.

Thanks


Edit: After some digging, I tried to get rid of the printf and send a plain buffer.
I still have the same issues when adding one byte to my buffer makes it work, or makes it fail.

I noted that changing compiler optimisation also have effects on the behavior. Everything always works in Og but not always in Os. Also adding -mno-unaligned-access has effects too.
Maybe this is a memory alignment problem, stack size too ?

2nd edit: This seems things are going random, removing some led blink at the end of the main loop breaks the code, makes it work when it is there.


Edit 2: I started all over with a new blank project for this board.
Same things happen even with a minimal code :

#define LED_TOOGGLE() 

(HAL_GPIO_TogglePin(PWR_I2C_GPIO_Port,GPIO_PIN_4))
#define LED_BLINK(ntime) for(int i=0; i<ntime*2; i++) {LED_TOOGGLE(); HAL_Delay(100);}

uint8_t buff4[4] = {0, 1, '\r','\n'};
uint8_t buff5[5] = {0, 1, 2, '\r','\n'};
uint8_t buff6[6] = {0, 1, 2, 3, '\r','\n'};
uint8_t buff7[7] = {0, 1, 2, 3, 4, '\r','\n'};
uint8_t buff8[8] = {0, 1, 2, 3, 4, 5, '\r','\n'};

int main(void)
{
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_AES_Init();
  MX_I2C1_Init();
  MX_SPI1_Init();
  MX_I2C3_Init();
  MX_ADC1_Init();
  MX_CRC_Init();
  MX_USB_DEVICE_Init();

  HAL_Delay(100);

  while (1) {

    LED_BLINK(1);
    HAL_Delay(10);
    CDC_Transmit_FS(buff6, 6);
  }
}

When I change buff6 (and size accordingly) for 5, the app won't start and the board go back to DFU mode. This is the same behavior as previously.
If anyone can reproduce and has insights on how to dig into this, that'll be a good start. Thanks

1
The printf routines consume a lot of stack. Perhaps you are close to the stack limit and the extra argument puts you over the limit. Try increasing the stack size and see if the problem goes away. (Don't be stingy, increase the size by more then you think is necessary just as an experiment.) - kkrambo
@kkrambo I'll try to do that and update. Thanks. - d6bels
Could You please provide more details making this issue reproducable? - Kamiccolo
printf in particular and sometimes other C library calls are massive if you are trying to debug does DFU work or not use a simple led blinker. if this is instead a case of debugging a program and isnt a DFU thing then need more info, like part number, a readelf map of the binary produced, maybe disassembly of functions in question not working. (posted here, not a link) - old_timer
Without precise information about toolchain being used noone can properly reproduce Your issue. Moreover without stacktrace or any debug information all we can do is just shooting blind guesses. - Kamiccolo

1 Answers

-1
votes

I see similar random glitches when code is not compiled properly for the system with DFU, especially when DFU is also a bootloader (starts before main program) or when there is separate tiniy bootloader (MBR), which decides what to jump to after reset: DFU or main app.

I suggest checking your compiled *.hex and making sure your program is expected to start at the address where your DFU loads it to.

The simplest and quickest way to do that is using ST-Link Utility. Simply drag-drop your hex file into main window and you will immediately get what you need. ST-Link Sample view

For STM32 chips, basic apps should be loaded into the beginning of the flash memory, which starts at 0x08000000.

If you are using a bootloader, which already occupies that sector, and your program starts at a different address, linker must be aware of that, since, among other things, your program has to properly initialize interrupts vector with array of function pointers, which are calculated at the link time.

So, if your DFU writes your program starting form address 0x08003000, then your linker has to assemble your program accordingly, and you should see that offset in the ST-Link Utility.