FreeScale Bootloader
FreeScale Bootloader
FreeScale Bootloader
Application Note
Derek Snell
Freescale
Contents
1 Introduction
Introduction................................................................1
Functional description...............................................2
Conclusion...............................................................20
Functional description
2 Functional description
2.1 General overview
This section provides an overview of the USB MSD device bootloader architecture and its software flow.
Functional description
Personal Computer
Figure 1. USB MSD bootloader architecture
The USB MSD device bootloader includes:
Bootloader application: Controls complete loading process and implements general tasks
Pseudo-FAT structure: Contains structures to respond to SCSI commands from host.
Bootloader driver: Uses SCSI command server to receive data from host computer, then parses image files and
downloads them to flash memory. The bootloader driver supports parsing image files in CodeWarrior binary, S-Record,
and raw binary file formats.
Flash driver: Supports functions to erase, read, and write flash memory.
SCSI
command server: Responds to SCSI commands from host.
USB MSD device class: Provides APIs specified in MSD class.
device driver and device controller: Communicate with the USB host though USB protocols.
USB
Functional description
After the firmware image file has been transferred to the device and the device reprograms itself, the device re-enumerates
with the host. A file is displayed in the drive that represents the status of the bootloader operation.
Reset
Enumerate as
USB MSD
SCSI
command
received
?
Yes
Read
Bootloader
mode
?
No
Jump to user
entry vector
Main()
Write
No
Write to
root directory
?
Yes
Parse image file
Erase/program
flash
Update bootloader
status file
Re-enumerate
Functional description
The bootloader mode can also be forced during a reset. The included examples monitor a button, and if the button is held
during reset, the bootloader mode is entered regardless of the values of the stack pointer and reset vector of the application.
The button used to enter this mode depends on the development board; see Using the bootloader on a demo board for the
specific button. Many applications need to change the method used to force bootloader mode, which can be done by
modifying the Boot_loader_task.c file.
2.4 Pseudo-FAT
After the host has configured the bootloader as a storage drive, it attempts to read the file allocation table (FAT) of the drive
and read the drives contents. The bootloader responds to these queries with information that looks like a 1 GB drive. The
drive has the volume name BOOTLOADER. It looks as if it has no subdirectories but has a file called READY.TXT in the
root directory.
The bootloader does not use a true file system, and is only capable of appearing as a drive to the host. It will accept files that
can be written to it which can then be transferred to the firmware image files. However, because the bootloader is only a
Pseudo-FAT system, it does not update the FAT when the host attempts to change it. The FAT is always fixed, and the only
change is the name of the file in the root directory that specifies the status of the bootloader.
When the host writes data to the drive, the bootloader ignores all data that is not written to the root directory of the drive.
When file data is written to the root directory, the bootloader assumes it is a firmware image file. It erases the application
flash and starts the firmware image parser to get the new firmware update. Only one file can be transferred to the drive after
reset. After a file is transferred, the bootloader needs to restart to accept another file.
Functional description
2.6 Re-enumeration
After the parser finishes, the device re-enumerates with the host to update the status file on the drive. The status files are
discussed in Bootloader status. Within the host computer, the drive disappears as the device drops off the USB bus. After a
few seconds, the device re-enumerates and the drive re-appears. You can read the status file on the drive to see the status of
the bootloader.
The bootloader re-enumerates because some host operating systems cache the file data on the storage drive and do not
refresh. Other operating systems do a delayed write and do not write the file to the device until the drive is unmounted. After
unmounting, the device receives the firmware image file, updates the firmware, and then re-enumerates to display the status.
In Windows XP and Vista, the OS caches the drive's FAT without re-reading it and the status file is not updated. Reenumeration forces the host to re-read the FAT and display the bootloader status file.
Functional description
Here is a list of the flash protection registers by core and the sectors protected. Refer to Table 4 to see how the flash memory
usage is affected. These protection values can be modified in Bootloader.h.
ColdFire V2 Register CFMPROT at 0x408 is set to 0x7 and protects the flash address range 0x0 to 0xBFFF.
ColdFire V1 Register NVPROT at 0x40D is set to 0xD7 and protects the flash address range 0x0 to 0x9FFF.
Kinetis K60N512 Register FPROT at 0x408 is set to 0xFFFFFFF8 and protects the flash address range 0x0 to
0xBFFF.
NOTE
If the bootloader is modified, these flash-protected sectors can be increased or decreased
to properly protect the bootloader. If the address range is changed, change the above
registers, and also change the memory map in the linker file and in Bootloader.h.
Bootloader
Application
0x0000_0000 to 0x0000_03FF
0x0000_0400 to 0x0000_041F
0x0000_0420 to 0x0000_BFFF
0x0000_C000 to 0x0000_C3FF
0x0000_C400 to 0x0000_C41F
0x0000_C500 to 0x0007_FFFF
Functional description
Bootloader
Application
0x0008_0000 to 0x1FFF_FFFF
Reserved
Reserved
0x2000_0000 to 0x2000_03FF
Redirected interrupt vector table in RAM Redirected interrupt vector table in RAM
0x2000_0400 to 0x2000_FFFF
Bootloader
Application
0x(00)00_0000 to 0x(00)00_03FF
0x(00)00_0400 to 0x(00)00_040F
0x(00)00_0410 to 0x(00)00_9FFF
0x(00)00_A000 to 0x(00)00_A3FF
0x(00)00_A400 to 0x(00)00_A40F
0x(00)00_A410 to 0x(00)01_FFFF
0x(00)20_0000 to 0x(00)7F_FFFF
Reserved
Reserved
0x(00)80_0000 to 0x(00)80_01BB
Redirected interrupt vector table in RAM Redirected interrupt vector table in RAM
0x(00)80_01BC to 0x(00)80_3FFF
Bootloader
Application
0x0000_0000 to 0x0000_03FF
0x0000_0400 to 0x0000_040F
0x0000_0410 to 0x0000_BFFF
0x0000_C000 to 0x0000_C3FF
0x0000_C400 to 0x0000_C410
0x0000_C410 to 0x0007_FFFF
0x0008_0000 to 0x1FFE_FFFF
Reserved
Reserved
0x1FFF_0000 to 0x1FFF_03FF
Redirected interrupt vector table in RAM Redirected interrupt vector table in RAM
0x1FFF_0400 to 0x2000_FFFF
MCF52259
33
48
MCF51JM128
32
40
K60N512
33
48
See Stack and RAM usage for an explanation of why the bootloader uses no RAM.
image_files: Contains some example firmware image files of applications to test with the bootloader. See Using the
bootloader on a demo board for more details.
CodeWarrior: Contains projects for CodeWarrior for Microcontrollers v6.3 to use with ColdFire V1 and CodeWarrior
for ColdFire v7.2 to use with ColdFire V2.
cw10: Contains projects for CodeWarrior v10.1 for ColdFire and Kinetis.
Flash_driver: Contains flash driver source code for many microcontrollers.
Boot_loader_task.c: Source file for general Bootloader tasks.
Boot_loader_task.h: Function prototypes
Bootloader.h: Includes memory map definitions for specified boards.
disk.c: Contains mass storage disk functions.
disk.h: Contains disk parameter definitions.
FAT16.c: Contains pseudo-FAT structures.
FAT16.h: Contains FAT parameter definitions.
Loader.c: Contains functions to parse and load firmware image to flash memory.
usb_descriptor.c: Contains USB descriptor structures and functions.
usb_descriptor.h: Contains USB descriptor parameters.
user_config.h: Contains user configurations for USB stack.
11
This example shows why linking between the application and the bootloader should always be avoided except through
absolute addresses. The only interaction this bootloader has with the application is when the bootloader launches the
application, which is done using the absolute address of the application reset vector. If the bootloader is included in the
application project, the linker should link only to a binary image of the bootloader, not to the source code or a library. With
this method, the linker will not be aware of the functions in the bootloader when compiling the application.
This section provides a high-level overview of how to port the USB MSD device bootloader to other Freescale devices, with
these assumptions:
The device is supported by a USB stack with MSD class.
There is a simple flash driver for this device.
Perform these steps to port the bootloader to other platforms:
1. Create a new project under \USB_MSD_Device_bootloader\Source\Device\app\msd_bootloader
\codewarrior\ or \USB_MSD_Device_bootloader\Source\Device\app\msd_bootloader\cw10\ directory.
13
Flash driver
Bootloader application
Pseudo-FAT
Bootloader driver
To be compatible with the bootloader, the application code should start after the protected flash and application stored vector
table, from address 0xA410. Also, the RAM used for the redirected vector table should be excluded from application RAM.
In this case, RAM should start at 0x8001BC. The modified linker file should look like this:
# Sample Linker Command File for CodeWarrior for ColdFire MCF51JM128
# Memory ranges
MEMORY {
code
userram
}
15
(RX)
(RX)
(RX)
(RWX)
(RWX)
:
:
:
:
:
ORIGIN
ORIGIN
ORIGIN
ORIGIN
ORIGIN
=
=
=
=
=
0x00000000,
0x00000400,
0x00000500,
0x20000000,
0x20000400,
LENGTH
LENGTH
LENGTH
LENGTH
LENGTH
=
=
=
=
=
0x00000400
0x00000020
0x0007FB00
0x00000400
0x00005C00
To be compatible with the bootloader, the stored application interrupt vectors (vectorrom) need to start after the protected
flash memory, from address 0xC000. The application code should start after the application stored vector table, from address
0xC500. The modified linker file should look like this:
# Sample Linker Command File for CodeWarrior for ColdFire
KEEP_SECTION {.vectortable}
# Memory ranges
MEMORY {
vectorrom
cfmprotrom
code
vectorram
userram
}
(RX)
(RX)
(RX)
(RWX)
(RWX)
:
:
:
:
:
ORIGIN
ORIGIN
ORIGIN
ORIGIN
ORIGIN
=
=
=
=
=
0x0000C000,
0x0000C400,
0x0000C500,
0x20000000,
0x20000400,
LENGTH
LENGTH
LENGTH
LENGTH
LENGTH
=
=
=
=
=
0x00000400
0x00000020
0x00073B00
0x00000400
0x00005C00
LENGTH
LENGTH
LENGTH
LENGTH
=
=
=
=
0x000001E0
0x00080000-0x00000800
0x00020000
0x00000010
To be compatible with the bootloader, the stored application interrupt vectors (vectorrom) need to start after the protected
flash memory, from address 0xC000. The application code should start after the application stored vector table, from address
0xC410. Also, the RAM used for the redirected vector table should be excluded from application RAM. In this case, RAM
should start at 0x1FFF_0400.The modified linker file should look like this:
# Default linker command file.
MEMORY {
m_interrupts (RX) : ORIGIN = 0x0000C000,
m_cfmprotrom (RX) : ORIGIN = 0x0000C400,
m_text
(RX) : ORIGIN = 0x0000C410,
m_data
(RW) : ORIGIN = 0x1FFF0400,
}
LENGTH
LENGTH
LENGTH
LENGTH
=
=
=
=
0x00000400
0x00000010
0x00073BF0
0x0001FC00
5.2.2.1
CFV1 microcontrollers
CodeWarrior projects are typically configured for ease of use, with the vector table fixed at the default location in flash
memory at address 0x0000. Therefore, a new vector table can be created in the application to store the interrupt vectors in the
application section of flash memory.
An example vector table is provided below that can be included in the application. The whole vector table is not shown here,
but the full table is available in the application software example provided. This vector table should be located at the
beginning of unprotected flash, in this case 0xA000, because the bootloader will look for the application reset vector at that
address.
Just as with the default vector table, vector 0 should have the initial stack pointer value and vector 1 needs the application
reset vector. This example fills the rest of the vectors with the dummy interrupt service routine dummy_ISR. To add a new
ISR, replace the address of the dummy_ISR with that of the new ISR, like Timer_Overflow shown below. The new vector
table in the application is declared by using this code:
// Declare the stored vector table for the application,
// and locate it at the beginning of unprotected flash
void (* const RAM_vector[])()@0xA000= {
(pFun)&__SP_INIT,
// vector_0 INITSP
(pFun)&_startup,
// vector_1 INITPC
(pFun)&dummy_ISR,
// vector_2 Vaccerr
(pFun)&dummy_ISR,
// vector_3 Vadderr
(pFun)&dummy_ISR,
// vector_4 Viinstr
(pFun)&dummy_ISR,
(pFun)&dummy_ISR,
(pFun)&dummy_ISR,
(pFun)&Timer_Overflow,
(pFun)&dummy_ISR,
(pFun)&dummy_ISR,
// vector_74 Vtpm1ch3
// vector_75 Vtpm1ch4
// vector_76 Vtpm1ch5
// vector_77 Vtpm1ovf
// vector_78 Vtpm2ch0
// vector_79 Vtpm2ch1
17
// vector_80 Vtpm2ovf
(pFun)&dummy_ISR,
(pFun)&dummy_ISR,
(pFun)&dummy_ISR,
// vector_108 VL3swi
// vector_109 VL2swi
// vector_110 VL1swi
};
In the application, this table should be copied to the base of RAM. This code copies the above table (RAM_Vector) to the
vector table region in RAM:
// Copy stored application interrupt vectors
// to re-directed vector table in RAM
pdst=(uint_32_ptr)0x00800000;
psrc=(uint_32_ptr)&RAM_vector;
for (i=0;i<111;i++,pdst++,psrc++)
{
*pdst=*psrc;
}
CFV1 has a register named Vector Base Register (VBR) that contains the base address of the exception vector table. This
register is used to relocate the exception vector table from its default position in flash memory (address 0x0) to the base of
the RAM (0x800000).
// Move vector table to start of RAM, 0x800000
asm (move.l #0x00800000,d0);
asm (movec d0,vbr);
5.2.2.2
CFV2 microcontrollers
5.2.2.2.1
With the CFV2 version, the Freescale USB stack includes a function to copy the interrupt vector table to a specified area in
RAM.
void initialize_exceptions(void);
This function copies the interrupt vector table to RAM at __VECTOR_RAM address. This address is defined in the linker
command file. It also moves the vector table to RAM by changing the VBR.
This function is called at startup by default so the application does not need to call this function.
5.2.2.2.2
For other applications, the application needs to copy the stored vector table from flash to RAM and move the vector table by
changing VBR. This code can be used to copy the vector table:
// Copy Application Stored Interrupt Vector table to RAM
pdst=(uint_32*)0x20000000;
psrc=(uint_32*)0xC000;
for (i=0;i<0x100;i++,pdst++,psrc++)
{
*pdst=*psrc;
}
CFV2 has a register named Vector Base Register (VBR) that contains the base address of the exception vector table. This
register is used to relocate the exception vector table from its default position in the flash memory (address 0x0) to the base
of the RAM (0x2000_0000).
The following code is used to redirect vector table to the RAM with address 0x2000_0000.
5.2.2.3
Kinetis microcontrollers
In Kinetis, the SCB_VTOR register contains the base address of the exception vector table. To redirect the vector table, the
vector table has to be copied to RAM, then the value of SCB_VTOR changed to the copied address. These steps describe the
way to redirect the vector table for Kinetis.
Implement this code to copy the interrupt vector table to RAM:
// Copy Application Stored Interrupt Vector table to RAM
pdst=(uint_32*)0x1FFF0000;
psrc=(uint_32*)0xC000;
for (i=0;i<0x100;i++,pdst++,psrc++)
{
*pdst=*psrc;
}
Then redirect the vector table to RAM by changing the SCB_VTOR like this:
// Redirect the vector table to the new copy in RAM
SCB_VTOR = (uint_32)0x1FFF0000;
19
Conclusion
6 Conclusion
Freescales USB Mass Storage Device Bootloader allows for very easy firmware updates. It does not require a driver, does
not require any software on the host computer, and can be performed by anyone. This bootloader also works with a broad
selection of Freescale microcontrollers. The information in this application note should allow any application to be integrated
with the bootloader.
Web Support:
http://www.freescale.com/support
Japan:
Freescale Semiconductor Japan Ltd.
Headquarters
ARCO Tower 15F
1-8-1, Shimo-Meguro, Meguro-ku,
Tokyo 153-0064
Japan
0120 191014 or +81 3 5437 9125
[email protected]
Asia/Pacific:
Freescale Semiconductor China Ltd.
Exchange Building 23F
No. 118 Jianguo Road
Chaoyang District
Beijing 100022
China
+86 10 5879 8000
[email protected]