3
\$\begingroup\$

I'm trying to figure out the sequence of booting between bootloader and user firmware in the Cortex-M3. The Cortex-M3 design supports basic examples such as "Hello".

Here is the snippet for hello.c of user firmware code:

int main(void) 
{
  UartStdOutInit();
  printf("Hellow Test");
  printf("Test Passed");
  UartEndSimulation();
  return 0;
}

And here is bootloader.c:

_asm void FlashLoader(void)
{
  MOVS R0, #0
  LDR R1, [R0]
  MOV SP, R1
  LDR R1,[R0, #4[
  BX R1
}

int main(void) 
{
  UartStdOutInit();
  UartPuts("Boot Loader");
  UartPuts("load flash");
  FlashLoader();
  return 0;
}

As I know, the main sequence of bootloader is that it gets the initial MSP and PC value, and then branches to the R1 address which is the Reset_Handler of the bootloader.

But I'm confused about how the "bootloader" firmware finishes and how the "Hello" firmware magically starts?

\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

The sequence of booting between the bootloader and the user firmware on a Cortex-M3 microcontroller typically follows these steps:

  1. The microcontroller is powered on or reset.
  2. The bootloader code is loaded into memory and executed.
  3. The bootloader checks for a valid user firmware image in non-volatile memory (e.g. flash memory).
  4. If a valid user firmware image is found, the bootloader copies it from non-volatile memory into RAM and executes it.
  5. If a valid user firmware image is not found, the bootloader waits for a new firmware image to be uploaded via a communication interface (e.g. UART, USB, Ethernet).

Here is an example of bootloader code in C that performs these steps:

#include <stdint.h>
#include "memory.h"  // Memory mapping and manipulation functions
#include "flash.h"   // Flash memory functions
#include "uart.h"    // UART communication functions

#define FIRMWARE_ADDRESS  0x08000000  // Address of firmware in flash memory
#define FIRMWARE_SIZE     0x4000      // Size of firmware in bytes

int main(void)
{
  uint8_t buffer[FIRMWARE_SIZE];  // Buffer for storing firmware image
  int i;

  // Check if valid firmware image is present in flash memory
  if (flash_verify(FIRMWARE_ADDRESS, FIRMWARE_SIZE, buffer))
  {
    // Copy firmware image from flash memory to RAM
    for (i = 0; i < FIRMWARE_SIZE; i++)
    {
      *((uint8_t*)(FIRMWARE_ADDRESS + i)) = buffer[i];
    }

    // Jump to firmware
    ((void(*)(void))FIRMWARE_ADDRESS)();
  }
  else
  {
    // Wait for firmware image to be uploaded via UART
    uart_init();
    uart_puts("Waiting for firmware image...\n");
    while (1)
    {
      if (uart_gets(buffer, FIRMWARE_SIZE))
      {
        // Erase flash memory
        flash_erase(FIRMWARE_ADDRESS, FIRMWARE_SIZE);

        // Write firmware image to flash memory
        flash_write(FIRMWARE_ADDRESS, FIRMWARE_SIZE, buffer);

        // Jump to firmware
        ((void(*)(void))FIRMWARE_ADDRESS)();
      }
    }
  }

  return 0;
}

This is just one example of how a bootloader might work. There are many different ways to implement a bootloader, and the specific details will depend on the specific microcontroller and the requirements of the application.

As for a "Hello" firmware example, here is some simple firmware code in C that will print "Hello, World!" to a UART interface:

#include <stdio.h>
#include "uart.h"  // UART communication functions

int main(void)
{
  uart_init();  // Initialize UART
  printf("Hello, World!\n");  // Print message to UART
  return 0;
}
\$\endgroup\$
2
  • \$\begingroup\$ Can I update my hello.lst and bootload.lst for more question? \$\endgroup\$
    – Carter
    Dec 27, 2022 at 13:24
  • \$\begingroup\$ @Carter of course. \$\endgroup\$ Dec 27, 2022 at 13:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.