CANopen Compliant Bootloader and Debugger Cores for Flash Microcontrollers
by Olaf Pfeiffer and Andrew Ayre
Goal of this paper is to define the minimal CANopen functions, features and variables that a boot loader needs to support to still be recognized as a CANopen node in a system. For the scope of this document we define the boot loader to be a piece of code that is shipped pre-installed with Flash microcontrollers. Using hardware or software mechanisms, the microcontroller can be set into boot mode - which means the application code is bypassed and the boot loader code is executed.
This documents requires some intermediate knowledge about CANopen. The specifications DS 301 V4.01 and DSP302 V2.0 were used as a guideline for this document.
The minimal expected functionality of the CANopen compliant boot loader is:
- Start up with a pre-defined CANopen node ID of 64 (0x40) and a default CAN baud rate of 125 kbits
- CANopen configuration tools can detect the device
- CANopen configuration tools can transfer a regular (Intel-) hex file to the device which programs the contents into the Flash memory
- After the Flash was successfully re-programmed the device automatically reset or re-initializes and executes the new code
Extended functionality may include:
- Default parameters are configurable:
- CANopen node ID
- CAN baud rate (or auto baud detection)
- Vendor and Product ID codes
- Supporting multiple Flash memory blocks depending on the chip architecture
- Debug support - implement a communication interface for Debuggers
Minimizing code resources by minimizing functionality
Most Flash microcontrollers only offer limited code space in the boot area forcing us to minimize the CANopen implementation used. A minimal CANopen implementation as suggested in this document would never be a "true" CANopen node just by itself. As it does not have any application program and as there is no application I/O it is feasible to violate DS 301 V4.01 if the result is to further minimize the code size.
A CANopen compliant boot loader would not listen to the NMT master message changing operating states, as it would not have any operating states. There are no PDOs (Process Data Objects).
As there is no operating state and no process data, node guarding and heartbeat do not need to be supported.
Note: This is a violation to DS 301 V4.01, which states that every CANopen node MUST support either node guarding or heartbeat.
The communication channels required are the boot-up message and the SDO (Service Data Object). Optionally the Emergency message may be used when debugging is supported.
Background info: the node transmits the boot-up message after start-up. It informs other nodes on the network that this node now started up and awaits configuration. The SDO communication channel is used for transmitting configuration data.
The CANopen Object Dictionary
Mandatory object dictionary entries for a CANopen compliant boot loader:
"Device Type" as specified in DS 301 V4.01
Value reported: 0x424F4F54 ("BOOT")
"Error Register" as specified in DS 301 V4.01
Bits 0 and 7 are set if the last Flash operation was unsuccessful
Bits 0 and 7 are cleared with each successful Flash operation
"Identity Object" as specified in DS 301 V4.01
The number of sub-indexes may be application specific. The sub-indexes 0 "Number of Entries" and 1 "Vendor ID" are mandatory. The sub-indexes 2 "Product Code", 3 "Revision Number" and 4 "Serial Number" are optional. It is recommended to make these entries configurable (for instance using an especially protected configuration area in the Flash memory). This way an OEM can ensure that the boot loader identifies itself as a special product instead of identifying itself as a microcontroller from a certain chip manufacturer.
"Download Program Data" as specified in DSP 302 V2.0
The number of sub-indexes is application specific. If multiple program code areas are supported, each entry needs to support a dedicated memory sector. Writes to that entry should be filtered - meaning they do not allow writes to memory areas outside the specified segment. If an illegal write attempt is made or there is any other write error, an appropriate "SDO Abort Message" must be generated. The file format used is (Intel-) hex file.
"Program Control" as specified in DSP 302 V2.0
The command supported is "Reset Program" which automatically discontinues the boot loader and starts the application program.
Optional entry for password and erase command
The functionality implemented so far is sufficient to allow re-programming of Flash memory in a device. However, it does not offer much security. There is no protection mechanism to protect the Flash memory from unintentional overwrite.
Additional security can be added by implementing an additional object dictionary containing a password. Only after the correct value is written to that password does the object 1F50h get enabled/functional.
If this functionality is used, it is recommended to do so using the following object dictionary entry:
"Enable Flash Programming"
The number of sub-indexes n is identical to the implementation of 1F50h. Each sub-index 1 to n is a write-only value of 32-bit. Writing the correct value to it will erase the target Flash memory and enable the functionality of entry 1F50. The default value/password to be used is 0x494E4954 ("INIT").
Adding debugging support to the boot loader is optional. However, if debugging is supported, all of the following functions and object dictionary entries must be supported.
Not all details of debugging are specified in this part of the document, as data and address types depend on the microcontroller architecture used. However, in order to cover as many microcontroller architectures as possible, all address values are using 4 bytes. The byte ordering is CANopen compatible (lowest byte comes first, followed by each higher significant byte). If a microcontroller uses the Harvard architecture, addresses need to be mapped to a van Neuman model (as done on 8051 architectures by "generic pointers").
The following debugger functions are defined in this document:
- Load a user program using entry 1F50h
- Start, stop or reset the user program using entry 1F51h
- Read to or write from any memory location using 1025h 4.) Report "breakpoint hit" using the emergency message
Object dictionary entry for debug-functionality
"OS Debugger Interface" mostly as specified in DSP 302 V2.0
In this implementation, the only purpose of this entry is to allow read and write accesses to and from the entire memory space of the target microcontroller. The read/write functions can be used to implement all debugger functions such as set or clear breakpoints or read the contents of special function registers.
It should be noted that it is possible to access this object dictionary entry while the user code is running, allowing access to variables at run-time.
Sub-index 1 "Command"
Byte 0: 0=read, 1=write
Byte 1: reserved
Byte 2, 3: Number of bytes to be read/written
Byte 4-7: Start address (exact contents is microcontroller architecture specific)
Sub-index 2 "Status"
as specified in DSP 302 V2.0
Sub-index 3 "Reply"
Not implemented in this version
Sub-index 4 "Data"
After sending a command the data can be read/written from/to this sub-index. Device type is "domain". However, the length of the transferred data must match the number of bytes specified with the "Command". In case of a data length mismatch an appropriate SDO Abort message gets generated.
Using the emergency message for debug information
As usual with SDOs (Service Data Objects), the SDO client initiates all communication. In this case the host PC running the debugger software. This means that only the host PC can initiate accesses to the Object Dictionary entries.
If the monitor/debugger firmware needs to report an urgent change-of-debugging-state to the host, it does so with the emergency message. The Error code to be used is 6200h "User Software".
The 5 manufacturer specific bytes in the emergency message are used as follows:
- Byte 1: Emergency Type
"1" for regular code breakpoint
- Byte 2-5: 32-bit address value
In case of a breakpoint this is the address of the breakpoint.