2 years, 7 months ago.

Default bootloader on STM32L432KC

Dear all, I have project based on Nucleo STM32L432KC with 256k FLASH. My application is about 80k. I am using the last 3 pages of FLASH memory as EEPROM to save some configuration data. The main connection with my own application on PC is by USB (as a virtual COM port) - on the baseboard is a FTDI chip FT230XS which is connected to the Nucleo on pins PB6 (Tx) and PB7 (Rx). Now I need to add some possibility to update the firmware in Nucleo from my PC application – simply upload the new bin file. It means that there is necessary to implement some bootloader.

I am a bit new in programing and I see that bootloader is above my strength now. I have few questions: - I have found that in STM32L432KC is some bootloader available as a default https://www.st.com/content/ccc/resource/technical/document/application_note/51/5f/03/1e/bd/9b/45/be/CD00264342.pdf/files/CD00264342.pdf/jcr:content/translations/en.CD00264342.pdf

- Is it true or not? - If yes is realy also available on pins PB6 and PB7? (I think no, because there is default I2C)

I have one idea: For update I will use the available SW like FLASHER-STM32 (not my application) and default built-in bootloader. But if I see right in datasheet on my pins PB6, PB7 is default I2C bootloader not UART. Do you have any idea how to solve it?

Thank you very much for your help. I will be thankful for every idea.

Best regards Lukas

1 Answer

2 years, 7 months ago.

Hello Lukas,

  • STM32 microcontrollers come with built-in bootloader that is programmed during production - see Application Note AN2606.
  • Table 6 - Boot modes (chapter 2.6, Boot configuration) in the Reference manual, shows how to select system memory as boot area (i.e. how to start the bootloader on reset). Based on that information it seems that you'll need to disconnect the BOOT0 pin from GND by opening the solder bridge SB12 (see Figure 10, MCU, in the User Manual for STM32 Nucleo-32 boards) before each software update and then close it once you have finished.
  • I would recommend to update your NUCLEO board either using MBED's drag and drop (i.e. copy and paste) feature, as you did so far, or you can use the STM32 ST-LINK utility for flashing.

Dear Zoltan, Thank you very much for your answer. I have checked the all datasheets and I see lot of problems for me :( I will try to explain why:

- now I am developing the testing samples of my product, where is a Nucleo board, but it is in plastic cover - it means that the micro USB on Nucleo is not accesible, because is covered. - in mass production there will be assembled only chip STM on PCB, not nucleo board - it means that I have available only my USB, which is connected to the pins PB6 and PB7 (thrue FT230 chip) - on these pins I can not used the default bootloader, because there is default setting for I2C booting and there is no way how to change it. I also can not connect my USB to another pins, because i need these other pins for analog inputs and pwm regulation. - the upload must be possible from my SW application which is on PC. Customer don't want to install any additional applications - the update must be easiest as possible.

Based on these facts I see only one way - my own bootloader. I have started to program it with this idea:

1. from my application I will reset the STM chip 2. After restart the chip will wait for some command - if yes, then I send the size of the new BIN file and then I will send the file byte by byte. The file will be saved into flash memory from some adress and on the end I will jump to this adress. If the command on the beginning is not detected then I will jump directly to this adress where is my application.

I am working on it, but I see problems: - the BIN file of the bootloader is very big, because MBED is included (about 25k), but because my application has about 60k it is in principle still ok (Nucleo L432KC has 256kb). - I am not sure if I understand of flash memory structure right? My bootloader will be from adress 0x08000000 and the adress where I want to have my application will be from 0x08007800?

0x08000000 ~ 0x08007800 30kb for bootloader

0x08007800 ~ 0x08040000 226kb for application

- is there necessary to compile application as default or from my adress 0x08007800 (because will be saved on diferent adress)?

I hope that I will test it during end of this week, then I will provide the source code.

Best regards Lukas

posted by Lukas Bier 15 Nov 2018

Hello all, I have tested to write my own code regarding bootloader, but as I expected it doesn't work. First I wrote the bootloader and after compilation I puted it into Nucleo (from default adress 0x08000000) The bootloader waiting for special command (i got the answer) and then I am sending message of complete data size (for control) and after answer I am sending the BIN file byte per byte. On the end if the size of writing data is the same as size of my file I sent the next command to start my application from address 0x0800F000.

Bootloader is checking the flash memory on the begining

  flash.init();
        const uint32_t page_size = flash.get_page_size();                       //need to know page_size
        char *page_buffer = new char[page_size];                                      //set page_buffer
        uint32_t addr = 0x0800F000;                                                               //addres of my application
        uint32_t next_sector = addr + flash.get_sector_size(addr);
        bool sector_erased = false;
     flash.deinit();

Then I am writing in cycle the data from page_buffer. When I wrote the data I am sending the command to my PC to send next one. (I know it is very slow, but it is only for test. )

flash.init();
                            if (!sector_erased)                             //erase if necessary
                            {
                                flash.erase(addr, flash.get_sector_size(addr));
                                sector_erased = true;
                            }
                          
                            flash.program(page_buffer, addr, page_size);    //save buffer to the flash
                            addr += page_size;                              //increase the address
                      
                            if (addr >= next_sector)                        //jum to the necxt sector
                            {
                                next_sector = addr + flash.get_sector_size(addr);
                                sector_erased = false;
                            }
                            flash.deinit();
                            delete[] page_buffer; 

And on the end I am trying to start my application by command

mbed_start_application (0x0800F000);                             

but without any reaction :(

There could be few reasons of this result: a) my idea is completely wrong :( b) there is necessary to change some vector to my application c) i can not compile my application as default, because isn't saved on default flash memory address d) there is some mistake when I am reading the BIN file and sending to the Nucleo. For this I am using this construction in Lazarus:

posted by Lukas Bier 23 Nov 2018

procedure TForm1.Button5Click(Sender: TObject);         //read file into buffer
var f : file of byte;
var i:byte;
var LBuffer: TBytes;
begin
     if not FileExists(update_file) then Exit;

              assignfile(f,update_file);
              reset(f);
                          Memo1.Lines.Add('File open    OK ');
              SetLength(LBuffer, filesize(f));
              for i := 1 to filesize(f) do
                       read(f,LBuffer[i]);
             closefile(f);
                      Memo1.Lines.Add('Number of bytes: '+ IntToStr (Length(LBuffer)));
end; 
// from LBuffer I will send the data to the nucleo.

Thank you very much for your advice. BR Lukas

posted by Lukas Bier 23 Nov 2018