0% found this document useful (0 votes)
56 views

Microcontroller Advanced Topics: #4: Bootloading

Microcontroller Advanced Topics #4 discusses bootloading. It defines important terms like bootloader, program, interrupt, and memory. It explains how a bootloader can be used to program new code onto a device from a host by communicating over UART using a protocol with start, data, checksum, and finish sentinels. The memory model divides flash memory into regions for the bootloader and target program with sections like text and data. It also recaps the ARM core registers and stack.

Uploaded by

cosmin1234
Copyright
© © All Rights Reserved
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
56 views

Microcontroller Advanced Topics: #4: Bootloading

Microcontroller Advanced Topics #4 discusses bootloading. It defines important terms like bootloader, program, interrupt, and memory. It explains how a bootloader can be used to program new code onto a device from a host by communicating over UART using a protocol with start, data, checksum, and finish sentinels. The memory model divides flash memory into regions for the bootloader and target program with sections like text and data. It also recaps the ARM core registers and stack.

Uploaded by

cosmin1234
Copyright
© © All Rights Reserved
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 31

Microcontroller Advanced

Topics
#4: Bootloading

Kevin Balke
[email protected]
UCLA IEEE 2016
Rationale
1. We are engineers…
2. Fun!
3. …
4. Profit!
CODE FOR THIS WORKSHOP:

https://goo.gl/Tc07Yh
Overview
1. What are we trying to achieve, and why is it important?
a. Some motivating examples
2. Definitions
3. File Formats
4. Communication Systems
5. Memory Model
6. Recap of ARM Registers, Stack, Execution, and Instructions
7. Program startup procedure
8. Linker Scripts
9. Programming Flash
10. Additional Resources
You are Building a Satellite...
● It's going to space
● You can't plug a cable into it once it leaves
● How do you fix it if it stops working?
● Need some way to load new code… and then boot that code...

You need a...

BOOTLOADER
You're doing NATCAR...
● You want to change your algorithms
○ Not just live tuning, actually a different implementation!
○ How can we achieve this?
○ What code actually needs to be changed?
■ Does the code that runs the servo need to be changed?
■ Is it possible to change just the control code?

The answer is YES! But you have to do some


clever engineering first...
Some definitions...
PROGRAM: a piece of code, more or less independent of other code, that runs on a computer
BOOT: the process of a computer starting up (generally in the presence of an operating system)
BOOTLOADER: a software component (program) responsible for putting other programs in memory, and
executing them
INTERRUPT: an event that causes the processor to stop what it's doing and start executing some other
code
INTERRUPT SERVICE ROUTINE (ISR): the code that runs when the corresponding interrupt arrives (fires)
INTERRUPT VECTOR (IV): the address of an ISR; this is loaded into the PC (program counter) when the
interrupt fires
INTERRUPT VECTOR TABLE (IVT, VTABLE): an array of IVs in memory that can be used to look up the
correct ISR for a given interrupt
HUMAN READABLE: any information capable of being understood readily[dubious, discuss] by a human
Some definitions… (cont.)
COMPILER: a piece of software that converts a program from a high level language (C, C++, Python, etc.),
to a low-level language (often assembly)
PREPROCESSOR: a piece of software that substitutes macros in source code (e.g., #define)
TRANSLATION UNIT: a program source file, after being processed by the preprocessor, ready to be
compiled
OBJECT FILE: the result of compiling a single translation unit (.c or .cpp or other source file)
SYMBOL: a name for a primitive in a program (function, variable, pointer, etc.), agreed upon by the
programmer, compiler, linker, and assembler
LINKER: a piece of software that resolves references (symbols) between translation units in a program
LIBRARY: a collection of program functionality labeled by symbols (in the form of object files), rolled into a
bigger file, that can be linked against (called and used from another piece of code) to provide common
functionality (C's runtime and math functions are examples)
ASSEMBLER: a piece of software that converts assembly (human-readable) into machine code (binary
format)
Some definitions… (cont.)
MEMORY: any device that can be used to store state or information across instants in time
READ ONLY, WRITE ONLY, etc.: (in regards to memory) only allowed to be read, only allowed to be
written, only allowed to be executed, etc. These permissions can often be chosen and combined in cases
where the memory is physically capable of being more than one, or hardware limitations may
prevent/restrict a particular memory from being/to a particular type
VOLATILE: (in regards to memory) not persisting its contents across power cycles
FLASH: (n.) a non-volatile memory type that is used to store program code and other constants; (v.) the act
of programming a flash memory
RAM (RANDOM ACCESS MEMORY): a volatile memory type that is used to store variables and other
program objects that change during the lifetime of the program (stack, heap, etc.)
Binary Files
Which one is probably a binary file? Which one is probably a text file?

file1 file2

kb@box:~$ cat file1 kb@box:~$ cat file2


���� CAFEBABE
kb@box:~$ cat file1 | hexdump -Cv kb@box:~$ cat file2 | hexdump -Cv
00000000 ca fe ba be 0a |.....| 00000000 43 41 46 45 42 41 42 45 0a |CAFEBABE.|
00000005 00000009
kb@box:~$ ▯ kb@box:~$ ▯

Contains
arbitrary binary Contains ASCII
data characters
Programs are Data
● Machine code = binary data
● Try this:
kb@box:~$ cat /bin/cat | hexdump -Cv

● Or this:
kb@box:~$ objdump -D /bin/cat

● Notice anything interesting?


○ Strings are in there! So are we seeing data? Are we seeing instructions?
○ BOTH!
Programs are Data (cont.)
● How can we represent this data?
○ Binary files?
○ Hexadecimal?
○ Drawings of flying machines?
○ Smoke signals?
● More importantly: how do we send this data?
○ Send the bytes?
■ All at once?
○ What if we mess up?
○ How do we handle state?
■ Start/stop/etc.
TX RX

Communication Systems UART UART


RX TX

● How do we transmit this data reliably?


○ Error correction!
■ Forward
■ Reverse
● What channel do we have?
○ UART → we can assume it to be a relatively well-behaved character pipe
● How do we signal about control across the channel?
○ Some symbols (characters) will have to be allocated to control!
■ 1 char = 1 byte, but we're using some chars as control! How do we send all possible bytes,
then?
○ What kinds of control do we want?
■ Start/Stop/Ack/Nack/Reboot
Total symbol alphabet:
0123456789ABCDEFabcdefSTKXstkx
The Scheme
● Writing to the device
○ Start sentinel 'S'
○ Send data, encoded as ASCII hexadecimal; first 4 octets are address of block to write; blocks
are up to 1024 bytes in size
○ Terminator 'T'
○ Remote device either sends 'K' to signal ACK, or 'X' to signal NACK
● Verifying written data
○ After block is written, device echos block back
○ Start sentinel 's'
○ Send data
○ Terminator 't'
○ Host bootloader driver either sends 'k' to signal ACK, or 'x' to signal NACK
● Process repeats for as many blocks as are necessary to represent the entire
program
Total symbol alphabet:
0123456789ABCDEFabcdefSTKXstkxq
0123456789ABCDEFabcdefSTKXstkx
The Scheme
● Finishing programming/booting the target application
○ Need some way to indicate that we're done sending the program!
○ Finish sentinel 'q'
Memory Model
● FLASH: Located at address 0x00000000, of length 0x00040000 (256kB)
● SRAM: Located at address 0x20000000, of length 0x00008000 (32kB)
● We further divide the flash into two regions:
○ Bootloader code region (0x00000000, length 0x00001000 (4kB))
○ Target program code region (0x00001000, length 0x0003F000 (252kB))
○ In each of these regions there are several sections:
■ .isr_vector: this section contains the interrupt vector table (flash)
■ .vtable: this section contains the relocated interrupt vector table, if you register interrupt handlers at
runtime with XXXIntRegister() in TivaWare (RAM)
■ .text: this section stores program code (flash)
■ .rodata: this section stores constants (flash)
■ .data: this section stores variables that get initialized at program start; space is reserved in RAM, and
the initial values are allocated in flash
■ .ARM.exidx/.ARM.extab: this section stores annotations to perform stack unwinding (flash)
■ .bss: this section stores variables that are uninitialized (zero-initialized) at program start (RAM)
■ .heap: this section stores the heap, where malloc(), free(), new, and delete operate (RAM)
■ .stack: this section stores the program call stack (RAM)
ARM core registers (RECAP)
Taken from Texas
Instruments TM4C123GH6PM
datasheet
(http://goo.gl/ObHu8b), p. 75

We’ll take a look at


this next... Stores special
processor status
including THUMB
Stores return address state, exception
number, and
Points to currently arithmetic flags
executing instruction
in memory
The stack (RECAP)
● Type of data structure
● Think stack of books
○ Operations are push (put a new book on top), pop (take the top book off), and peek (look at the
top book)
● Special case: call stack (top is indexed by the SP register or stack pointer)
○ Stack frame: a range of addresses in the stack that corresponds to the data on the stack for a
given function call (top of each frame is indexed by FP register or frame pointer)

Note: Our call stack grows down


(SP decrements on push, and
increments on pop). It is also Fully
Descending, meaning that the SP
points to the most recent pushed
item, and is decremented before
placing the next item at SP.
The call stack (RECAP)

An example call stack snapshot


for a case where a function f()
calls a function g(). The stack
frame for a function can also be
called an activation record.
Value interpreted
as ARM instruction ARM instruction
The call stack: an example (RECAP) operands

0000829c <main>:
int main(void) { 829c: e52db004 push {fp} ; (str fp, [sp, #-
int foo = 4]!)
82a0: e28db000 add fp, sp, #0
1; 82a4: e24dd00c sub sp, sp, #12
foo = 2; 82a8: e3a03001 mov r3, #1
Compile 82ac: e50b3008 str r3, [fp, #-8]
return 82b0: e3a03002 mov r3, #2
foo; 82b4: e50b3008 str r3, [fp, #-8]
82b8: e51b3008 ldr r3, [fp, #-8]
} 82bc: e1a00003 mov r0, r3
82c0: e24bd000 sub sp, fp, #0
C program code 82c4: e49db004 pop {fp} ; (ldr fp, [sp], #4)
82c8: e12fff1e bx lr

Memory address ARM Disassembly


Memory value
The call stack: an example (RECAP)
= PC
0000829c <main>:
int main(void) { 829c: e52db004 push {fp} ; (str fp, [sp, #-
int foo = 4]!)
82a0: e28db000 add fp, sp, #0
1; 82a4: e24dd00c sub sp, sp, #12
foo = 2; 82a8: e3a03001 mov r3, #1
Compile 82ac: e50b3008 str r3, [fp, #-8]
return 82b0: e3a03002 mov r3, #2
foo; 82b4: e50b3008 str r3, [fp, #-8]
High addresses R3:
R3: 21
82b8: e51b3008 ldr r3, [fp, #-8]
} 82bc: e1a00003 mov r0, r3
SP Previous frame R0: 2 82c0: e24bd000 sub sp, fp, #0
SP Old FP FP 82c4: e49db004 pop {fp} ; (ldr fp, [sp], #4)
82c8: e12fff1e bx lr

21 foo
SP

Low addresses
ARM Assembly (Cortex-M4) http://goo.gl/KIzC6L
● Calling convention:
○ Function arguments stored in registers
○ Return value in R0
○ LR set to return address on branch to routine ({bl #label} instruction, “branch and link”)
● Some useful instructions:
Instruction Op1 Op2 Op3 Desc.

ldr Rd [Rn]; =LABEL N/A Load register (-> Rd)

str Rd [Rn]; =LABEL N/A Store register (Rd ->)

push {Ra, Rb, … , Rz} N/A N/A Push registers to stack

pop {Ra, Rb, … , Rz} N/A N/A Pop registers from stack

add Rd Rn (optional) #imm; Rb Add (-> Rd)


Program startup procedure
● Load the SP from the 0th entry of the interrupt vector table:
(__prog_text_start__)
● Load the PC from the 1st entry of the interrupt vector table:
(__prog_text_start__ + 4)
○ Begins executing the "ResetISR" (whatever code happens to be pointed at by
(__prog_text_start__ + 4)
● We need to write some assembly…
○ perform the above steps manually, and the target program will not know the difference
Linker Scripts
● We need a way to tell the compiler where to put stuff!
○ The sections and regions from the memory map are explicit in a special file, called a Linker
Script
○ Define start and length of regions
○ Define aliases for regions
○ Define symbols that refer to addresses in the memory map
○ Specify where to place objects exported by the compiler
Linker Scripts (cont.)
MEMORY {
BOOT_FLASH (RX) : ORIGIN = 0x00000000, LENGTH = 0x00001000
PROG_FLASH (RX) : ORIGIN = 0x00001000, LENGTH = 0x0003F000
SRAM (WX) : ORIGIN = 0x20000000, LENGTH = 0x00008000
Regions
}

REGION_ALIAS("REGION_BOOT_TEXT", BOOT_FLASH);
REGION_ALIAS("REGION_PROG_TEXT", PROG_FLASH); Region Aliases
REGION_ALIAS("REGION_BSS", SRAM);
...

SECTIONS {
PROVIDE (__prog_text_start__ = 0x00001000);
PROVIDE (__prog_text_end__ = 0x00040000);
Provisions
...

PROVIDE (_intvecs_base_address = 0x0);

.isr_vector (_intvecs_base_address) : AT (_intvecs_base_address) {


__text_start__ = .; Put some stuff
KEEP (*(.isr_vector)) in the region
} > REGION_BOOT_TEXT
...
}
Programming Flash
● Flash is divided into 1024B blocks
○ Individually erasable
● Can only write to flash after performing an erase
○ erase sets bits to all 1
○ write clears bits as appropriate
● Write procedure (8.2.3.7 - 8.2.3.9, Pg. 531)
● We've already done our due diligence with registers!
○ Let's just use TivaWare library calls
○ FlashErase(u32 addr) ← erases the flash page at addr, given that addr % 1024 == 0
○ FlashProgram(u32* buf, u32 addr, u32 len) ← programs the buffer buf of length len
into the flash starting at address addr, given that addr % 4 == 0, len % 4 == 0, and that
addr + len - 1 is in the same flash page as addr
Total Procedure
● Device resets
● Enter bootloader code
○ Bootloader waits for host program to attach

● Bootloader host attaches


○ host sends program, one block at a time, and verifies contents with bootloader after each block
○ host terminates transmission with 'q', triggering bootloader to start target application

OR

● Bootloader host does not attach, bootloader times out


○ bootloader starts target application
Let’s get cracking!
Assignment: Implement the missing snippets in the program_block_write and
runTargetProgram routines indicated by the comments.

This presentation:
https://goo.gl/jX0lGN
Thanks for coming!
My contact info:
Kevin Balke
[email protected]
Extra credit
First 3 people to complete one of the following assignments get free 3D printing
credit!

1. Error correction / checksums


2. Write only on block change
3. Load multiple programs (and choose between them at boot)
4. Program integrity check / slot filled before execution
5. Support for reading images back out
6. SD card bootloading / other interfaces
Additional Resources
https://www.lri.fr/~de/ARM.pdf ← ARM instruction set cheat sheet

https://www.scss.tcd.ie/~waldroj/3d1/arm_arm.pdf ← ARM ARM (Architecture


Reference Manual)

http://www.ti.com/lit/ds/symlink/tm4c123gh6pm.pdf ← TM4C123GH6PM Datasheet

http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0553a/CIHJJEIH.ht
ml ← ARM Cortex-M4 online instruction set reference
Installing Drivers
● http://energia.nu/guide/guide_windows/ ← Installing the TivaC driver
● https://learn.sparkfun.com/tutorials/disabling-driver-signature-on-windows-8 ←
disabling driver signing enforcement (requires reboot)
● http://energia.nu/download/ ← Energia download (flash drive available at
presentation)

You might also like