ROM Bootloader

From SEGGER Wiki
Revision as of 09:21, 12 May 2022 by Leon (talk | contribs) (Challenges)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

This article explains what is meant by a "ROM Bootloader" (ROM BTL) of embedded devices and goes into detail on what needs to be considered when working with them, especially in regard to SEGGER's J-Link.

What is a ROM Bootloader

A ROM bootloader is some code programmed to read-only memory of an embedded device. That code is usually the very first thing that is executed after the chip is being powered - hence bootloader.
In general a ROM bootloader executes some device-specific initialization (e.g. setting up peripherals, ...) which makes sure that the chip functions as expected before any user code is executed.
As the code is in read-only memory, it is programmed into the chip once during production by the manufacturer before being shipped to the customer. After that, it cannot be changed.

This procedure is present in most modern embedded devices as it provides silicon vendors with more flexibility when designing chips.
Instead of having to re-design and produce new silicon whenever the behavior of a device needs to be adjusted (i.e. a new chip revision is introduced), chip vendors can simply ship new devices with an updated ROM bootloader while the silicon stays the same.
Because of that, ROM bootloaders are different from one type of device to another and may even be different from one revision of a device to another revision of the same type of device.

Challenges

Application design

When developing an application that should run on a device with a ROM BTL, it is important to know what the ROM BTL does in order to determine how and where to execute user code.
As mentioned above, what a ROM BTL does in detail is different from one device to another. It is recommended to look through documentation of the device in use and look for any explanation of the chip's boot sequence.

It is common for ROM BTL to verify the validity of a program image before starting to execute it.
Some bootloaders, for example, expect a so called bootheader, i.e. structured data at a predefined location in flash memory which provides the ROM BTL with some information like application entry point, size of application, application data checksum and so on.

Any data that needs to be programmed to the target device for the ROM BTL to be satisfied needs to be considered when (ideally before) designing the application image, as it may occupy memory at specific locations or similar. It is also important that this data is downloaded to the device in use, in addition to the actual "user application" (if not already present).

Note:

When building the application image, make sure that the toolchain keeps any data that is only needed for the ROM BTL and not referenced by the user application.

Some compilers and linkers may recognize the data as not being referenced anywhere in the code and as such discard it when generating the application image.

Debugging

When debugging an application that is running on a device with a ROM BTL, it is important that the ROM BTL was executed before any user application code.
At the start of a debug session, it is common for IDEs to set the target's program counter (PC register) to the entry point of the user application (i.e. main()) after downloading and resetting the target.
This can cause issues on devices with a ROM BTL, because the ROM BTL may not have been executed correctly meaning that the chip was not fully initialized which can cause unexpected behavior when the user code is run.
What the IDE should do in cases like this is the following:

  1. Download the application image to the target
  2. Set a breakpoint at the first user application instruction (e.g. main())
  3. Reset the target device
  4. Let target device run to user application "by itself", ensuring that the ROM BTL is executed correctly
  5. Wait for the target to run into the breakpoint at the start of the application instruction

Some IDEs (like SEGGER's Embedded Studio) offer project options for enabling behavior like explained above:

  • The "Run To" project option tells Embedded Studio where to set the "initial breakpoint"

  • The "Entry Point Symbol" project option tells Embedded Studio where to start execution of the application image. In this case it is left empty on purpose