Updated WEEK03

This commit is contained in:
Kevin Thomas
2026-05-03 18:00:53 -04:00
parent 7c956ee514
commit d05687b79b
69 changed files with 2296 additions and 189 deletions
-3
View File
@@ -1,3 +0,0 @@
{
"cmake.sourceDirectory": "C:/Users/assem.KEVINTHOMAS/OneDrive/Documents/Embedded-Hacking/0x0001_hello-world"
}
+4 -2
View File
@@ -261,9 +261,11 @@ These are the most frequent mistakes. Avoid them.
---
## ⏰ Time Limit
## ⏰ Deadline & Submission
You have **4 hours** to complete this examination.
- This is a **take-home final project**. See the course syllabus for the due date.
- Submit all deliverables as a single ZIP file or as specified by your instructor.
- Late submissions: see syllabus late work policy.
---
Binary file not shown.
Binary file not shown.
+312 -82
View File
@@ -70,14 +70,17 @@ Each of these steps has a corresponding piece of code. Let's explore them all!
│ STEP 2: Bootrom Executes (32KB on-chip ROM) │
│ - This code is burned into the chip - can't be changed! │
│ - It looks for valid firmware in flash memory │
│ - It checks for the IMAGE_DEF structure at 0x10000000
│ - It scans the first 4 kB of the image for a valid IMAGE_DEF
│ (Datasheet §4.1, p. 338: 32KB ROM; §5.9.5, p. 429: IMAGE_DEF) │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ STEP 3: Boot Stage 2 (boot2)
│ - Configures the flash interface for fast reading
│ STEP 3: Flash XIP Setup (bootrom-managed)
│ - The bootrom configures the flash interface automatically
│ - Sets up XIP (Execute In Place) mode │
│ - Returns control to the bootrom
│ - NOTE: Unlike RP2040, there is NO separate boot2 in flash!
│ (Datasheet §5.2, p. 375: "removal of a boot2 in the first │
│ 256 bytes of the image") │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
@@ -119,8 +122,8 @@ Think of the bootrom like the BIOS in your computer - it's the first thing that
### What Does the Bootrom Do?
1. **Initialize Hardware**: Sets up clocks, resets peripherals
2. **Check Boot Sources**: Looks for valid firmware in flash
3. **Validate Firmware**: Checks for magic markers (IMAGE_DEF)
2. **Check Boot Sources (Discovery)**: Scans configured boot sources (for this course: flash) to find a candidate firmware image region.
3. **Validate Firmware (Validation)**: Verifies that candidate by finding IMAGE_DEF start/end markers and parsing the block.
4. **Configure Flash**: Sets up the XIP interface
5. **Jump to Your Code**: Reads the vector table and jumps to your reset handler
@@ -131,22 +134,70 @@ The bootrom looks for a special marker in your firmware called **IMAGE_DEF**. Th
Here's what it looks like in the Pico SDK:
```assembly
.section .picobin_block, "a" // placed in flash
.word 0xffffded3 // PICOBIN_BLOCK_MARKER_START ← ROM looks for this!
.byte 0x42 // PICOBIN_BLOCK_ITEM_1BS_IMAGE_TYPE
.byte 0x1 // item is 1 word in size
.hword 0b0001000000100001 // SECURE mode (0x1021)
.byte 0xff // PICOBIN_BLOCK_ITEM_2BS_LAST
.hword 0x0001 // item is 1 word in size
.byte 0x0 // pad
.word 0x0 // relative pointer to next block (0 = loop to self)
.word 0xab123579 // PICOBIN_BLOCK_MARKER_END
.section .picobin_block, "a" // placed in flash
.word 0xffffded3 // PICOBIN_BLOCK_MARKER_START ← ROM looks for this!
.byte 0x42 // PICOBIN_BLOCK_ITEM_1BS_IMAGE_TYPE
.byte 0x1 // item is 1 word in size
.hword 0b0001000000100001 // SECURE mode (0x1021)
.byte 0xff // PICOBIN_BLOCK_ITEM_2BS_LAST
.hword 0x0001 // item is 1 word in size
.byte 0x0 // pad
.word 0x0 // relative pointer to next block (0 = loop to self)
.word 0xab123579 // PICOBIN_BLOCK_MARKER_END
```
**The magic numbers:**
- `0xffffded3` = Start marker ("I'm a valid Pico binary!")
- `0xab123579` = End marker ("End of the header block")
### See This Exact Block in Your ELF (Commands + Real Output)
Use these commands to view the IMAGE_DEF bytes directly in the ELF:
```powershell
arm-none-eabi-objdump -s --start-address=0x1000013c --stop-address=0x10000150 build/0x0001_hello-world.elf
arm-none-eabi-objdump -s --start-address=0x10000130 --stop-address=0x10000154 build/0x0001_hello-world.elf
arm-none-eabi-gdb build/0x0001_hello-world.elf -ex "x/20bx 0x1000013c" -ex quit
```
Actual output from this lesson build:
```text
build/0x0001_hello-world.elf: file format elf32-littlearm
Contents of section .text:
1000013c 42012110 ff010000 b01b0000 793512ab B.!.........y5..
1000014c 4ff00000 O...
build/0x0001_hello-world.elf: file format elf32-littlearm
Contents of section .text:
10000130 a0010010 90a31ae7 d3deffff 42012110 ............B.!.
10000140 ff010000 b01b0000 793512ab 4ff00000 ........y5..O...
10000150 1e490860 .I.`
```
Command 1 explained (`--start-address=0x1000013c --stop-address=0x10000150`):
- Starts at `0x1000013c`, so it does **not** include the start marker at `0x10000138` (`d3deffff`).
- Shows IMAGE_DEF body fields and the end marker:
- `42012110` = `42 01 21 10` (item type/size + secure mode field)
- `ff010000` = last-item marker + size + pad
- `b01b0000` = next word in the block payload for this build
- `793512ab` = `PICOBIN_BLOCK_MARKER_END` (`0xab123579` in little-endian)
- `4ff00000` at `0x1000014c` is already the next instruction word after IMAGE_DEF.
Command 2 explained (`--start-address=0x10000130 --stop-address=0x10000154`):
- Starts earlier, so it captures context **and** both IMAGE_DEF markers.
- `a0010010 90a31ae7` = binary-info context before IMAGE_DEF.
- `d3deffff` at `0x10000138` = `PICOBIN_BLOCK_MARKER_START`.
- `793512ab` at `0x10000148` = `PICOBIN_BLOCK_MARKER_END`.
- `4ff00000 1e490860` = code words after the IMAGE_DEF block.
- This command proves the full block location for this build: `0x10000138` to `0x1000014b`.
Important: IMAGE_DEF offset can vary by build. In this build, the start marker `d3deffff`
is at `0x10000138` (not `0x1000013c`), so always search for the marker bytes instead of
assuming a fixed address.
---
## 📚 Part 3: Understanding XIP (Execute In Place)
@@ -327,7 +378,7 @@ arm-none-eabi-gdb build\0x0001_hello-world.elf
**Connect to target:**
```gdb
(gdb) target remote :3333
(gdb) target extended-remote :3333
(gdb) monitor reset halt
```
@@ -360,7 +411,7 @@ Let's look at the first 4 entries of the vector table at `0x10000000`:
### Step 2: Understanding What We See
> 🔄 **REVIEW:** In Week 1, we saw `sp = 0x20081fc8` when stopped at `main`. That's *after* some stack was used during boot. Here we see the *initial* stack pointer before any code runs!
> 🔄 **REVIEW:** In Weeks 1-2, we saw both `sp = 0x20082000` at the clean breakpoint at `main` and lower values like `0x20081fc8` or `0x20081ff8` after additional stack activity. Here we are looking at the *initial* stack pointer from the vector table before any code runs.
Let's decode each value:
@@ -466,39 +517,39 @@ Let's look at more instructions to see the full picture:
(gdb) x/20i 0x1000015c
```
**You should see something like:**
**You should see:**
```
0x1000015c <_reset_handler>: mov.w r0, #3489660928 @ 0xd0000000
0x10000160 <_reset_handler+4>: ldr r0, [r0, #0]
0x10000162 <_reset_handler+6>:
cbz r0, 0x1000016a <hold_non_core0_in_bootrom+6>
0x10000164 <hold_non_core0_in_bootrom>: mov.w r0, #0
0x10000168 <hold_non_core0_in_bootrom+4>:
b.n 0x10000150 <_enter_vtable_in_r0>
0x1000016a <hold_non_core0_in_bootrom+6>:
add r4, pc, #52 @ (adr r4, 0x100001a0 <data_cpy_table>)
0x1000016c <hold_non_core0_in_bootrom+8>: ldmia r4!, {r1, r2, r3}
0x1000016e <hold_non_core0_in_bootrom+10>: cmp r1, #0
0x10000170 <hold_non_core0_in_bootrom+12>:
beq.n 0x10000178 <hold_non_core0_in_bootrom+20>
0x10000172 <hold_non_core0_in_bootrom+14>:
bl 0x1000019a <data_cpy>
0x10000176 <hold_non_core0_in_bootrom+18>:
b.n 0x1000016c <hold_non_core0_in_bootrom+8>
0x10000178 <hold_non_core0_in_bootrom+20>:
ldr r1, [pc, #84] @ (0x100001d0 <data_cpy_table+48>)
0x1000017a <hold_non_core0_in_bootrom+22>:
ldr r2, [pc, #88] @ (0x100001d4 <data_cpy_table+52>)
0x1000017c <hold_non_core0_in_bootrom+24>: movs r0, #0
0x1000017e <hold_non_core0_in_bootrom+26>:
b.n 0x10000182 <bss_fill_test>
0x10000180 <bss_fill_loop>: stmia r1!, {r0}
0x10000182 <bss_fill_test>: cmp r1, r2
0x10000184 <bss_fill_test+2>: bne.n 0x10000180 <bss_fill_loop>
0x10000186 <platform_entry>:
ldr r1, [pc, #80] @ (0x100001d8 <data_cpy_table+56>)
0x10000188 <platform_entry+2>: blx r1
0x1000015c <_reset_handler>: mov.w r0, #3489660928 @ 0xd0000000
0x10000160 <_reset_handler+4>: ldr r0, [r0, #0]
0x10000162 <_reset_handler+6>:
cbz r0, 0x1000016a <hold_non_core0_in_bootrom+6>
0x10000164 <hold_non_core0_in_bootrom>: mov.w r0, #0
0x10000168 <hold_non_core0_in_bootrom+4>:
b.n 0x10000150 <_enter_vtable_in_r0>
0x1000016a <hold_non_core0_in_bootrom+6>:
add r4, pc, #52 @ (adr r4, 0x100001a0 <data_cpy_table>)
0x1000016c <hold_non_core0_in_bootrom+8>: ldmia r4!, {r1, r2, r3}
0x1000016e <hold_non_core0_in_bootrom+10>: cmp r1, #0
0x10000170 <hold_non_core0_in_bootrom+12>:
beq.n 0x10000178 <hold_non_core0_in_bootrom+20>
0x10000172 <hold_non_core0_in_bootrom+14>:
bl 0x1000019a <data_cpy>
0x10000176 <hold_non_core0_in_bootrom+18>:
b.n 0x1000016c <hold_non_core0_in_bootrom+8>
0x10000178 <hold_non_core0_in_bootrom+20>:
ldr r1, [pc, #84] @ (0x100001d0 <data_cpy_table+48>)
0x1000017a <hold_non_core0_in_bootrom+22>:
ldr r2, [pc, #88] @ (0x100001d4 <data_cpy_table+52>)
0x1000017c <hold_non_core0_in_bootrom+24>: movs r0, #0
0x1000017e <hold_non_core0_in_bootrom+26>:
b.n 0x10000182 <bss_fill_test>
0x10000180 <bss_fill_loop>: stmia r1!, {r0}
0x10000182 <bss_fill_test>: cmp r1, r2
0x10000184 <bss_fill_test+2>: bne.n 0x10000180 <bss_fill_loop>
0x10000186 <platform_entry>:
ldr r1, [pc, #80] @ (0x100001d8 <data_cpy_table+56>)
0x10000188 <platform_entry+2>: blx r1
```
### Step 7: Understanding the Startup Phases
@@ -513,22 +564,23 @@ The reset handler performs several phases:
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ PHASE 2: Data Copy (0x1000016a - 0x10000176)
│ PHASE 2: Data Copy Setup & Loop (0x1000016a - 0x10000176) │
│ - Set up the data_cpy_table pointer and load each copy triplet │
│ - Copy initialized variables from flash to RAM │
│ - Uses data_cpy_table for source/destination info │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ PHASE 3: BSS Clear (0x10000178 - 0x10000184)
│ PHASE 3: BSS Setup & Clear (0x10000178 - 0x10000184) │
│ - Load the BSS start/end addresses into r1 and r2 │
│ - GDB labels those literals as `data_cpy_table+48/+52` │
│ - Zero out all uninitialized global variables │
│ - C standard requires BSS to start at zero │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ PHASE 4: Runtime Init & Main (0x10000186+)
│ - Call runtime_init() for SDK setup
│ - Call __libc_init_array() for C++ constructors
│ - Finally call main()!
│ PHASE 4: Platform Entry Begins (0x10000186 - 0x10000188 shown)
│ - Load the runtime_init() pointer from the table
│ - Branch to runtime_init() with `blx r1`
│ - `main()` and `exit()` appear a few instructions later
└─────────────────────────────────────────────────────────────────┘
```
@@ -562,7 +614,8 @@ The data copy table contains entries that describe what to copy where. Let's exa
```
0x100001a0 <data_cpy_table>: 0x10001b4c 0x20000110 0x200002ac 0x10001ce8
...
0x100001b0 <data_cpy_table+16>: 0x20080000 0x20080000 0x10001ce8 0x20081000
0x100001c0 <data_cpy_table+32>: 0x20081000 0x00000000 0x00004770 0xe000ed08
```
The data_cpy_table contains multiple entries. Each entry has three values:
@@ -641,6 +694,8 @@ b.n 0x10000182 <bss_fill_test>
0x10000180 <bss_fill_loop>: stmia r1!, {r0}
```
The first two `ldr` instructions are still part of the **BSS clear setup**, even though GDB shows the source words as `data_cpy_table+48` and `data_cpy_table+52`. That label means the two literal words live in the same nearby constant block as the copy-table entries; it does **not** mean the code is still performing `.data` copies. At this point, `r1` becomes the BSS start address, `r2` becomes the BSS end address, and the loop beginning at `0x10000180` zeros that range.
### Understanding the Loop
```
@@ -762,7 +817,8 @@ Let's verify we understand the boot process by setting a breakpoint at main:
**You should see:**
```
Breakpoint 1 at 0x10000234: file 0x0001_hello-world.c, line 5.
Breakpoint 1 at 0x10000234: file C:/Users/flare-vm/Desktop/Embedded-Hacking-main/0x0001_hello-world/0x0001_hello-world.c, line 5.
Note: automatically using hardware breakpoints for read-only addresses.
```
**Now continue:**
@@ -776,8 +832,10 @@ Breakpoint 1 at 0x10000234: file 0x0001_hello-world.c, line 5.
```
Continuing.
Breakpoint 1, main () at 0x0001_hello-world.c:5
5 stdio_init_all();
Thread 1 "rp2350.cm0" hit Breakpoint 1, main ()
at C:/Users/flare-vm/Desktop/Embedded-Hacking-main/0x0001_hello-world/0x0001_hello-world.c:5
5 stdio_init_all();
(gdb)
```
🎉 We've traced the entire boot process from power-on to `main()`!
@@ -822,7 +880,7 @@ GDB doesn't know this is data, not code! It tries to disassemble it as Thumb ins
```
```
0x10000138 <__binary_info_header_end>: udf #211 @ 0xd3
0x10000138 <__binary_info_header_end>: udf #211 @ 0xd3
```
That's not real code - it's the magic number `0xffffded3` being misinterpreted!
@@ -884,6 +942,7 @@ While GDB is excellent for dynamic analysis (watching code execute), Ghidra exce
1000000d 01 ?? 01h
1000000e 00 ?? 00h
1000000f 10 ?? 10h
...
```
> 💡 **Notice:** Ghidra shows the vector table data as individual bytes by default. You can see it has labeled the start as `__vectors`, `__flash_binary_start`, `__VECTOR_TABLE`, and `__logical_binary_start`. The arrows (like `? -> 1000015d`) show that Ghidra recognizes these bytes as pointers to code addresses! To see the data formatted as 32-bit addresses instead of bytes, you can right-click and retype the data.
@@ -953,9 +1012,9 @@ Let's find how the boot code eventually calls `main()`:
| Location | Type | Label |
| ------------------------- | ---- | ------------------ |
| `platform_entry+6` | CALL | `blx r1` (to main) |
| `1000018c` | CALL | `blx r1` (to main) |
4. Double-click on the reference to jump to `platform_entry`
4. Double-click on the reference to jump to `1000018c`
### Step 19: Examine Platform Entry
@@ -991,7 +1050,7 @@ Ghidra can visualize the call flow:
1. With `_reset_handler` selected, go to **Window → Function Call Graph**
2. This shows a visual graph of all function calls from the reset handler
3. You can see the path: `_reset_handler` `platform_entry``main`
3. You will see `_reset_handler` at the top with arrows going down to its four direct callees: `data_cpy`, `runtime_init`, `main`, and `exit`
### Comparing GDB and Ghidra for Boot Analysis
@@ -1023,8 +1082,8 @@ Ghidra can visualize the call flow:
├─────────────────────────────────────────────────────────────────┤
│ 2. BOOTROM │
│ - Initializes hardware │
│ - Finds IMAGE_DEF at 0x10000000
│ - Runs boot2 to configure flash
│ - Configures flash XIP (no separate boot2 on RP2350)
│ - Finds IMAGE_DEF within first 4 kB of flash image
├─────────────────────────────────────────────────────────────────┤
│ 3. VECTOR TABLE (0x10000000) │
│ - Reads SP from offset 0x00 → 0x20082000 │
@@ -1129,21 +1188,18 @@ Ghidra can visualize the call flow:
- Is it a valid code address (starts with `0x1000...`)?
- What handler does it point to?
### Exercise 4: Find Your Main Function
### Exercise 4: Find Your Main Function and Trace Back
1. Use `info functions main` to find main
2. Examine 10 instructions at that address
3. Identify the first function call in main
4. What does that function do?
5. When stopped at main, examine `$lr` (link register)
6. What address is stored there?
7. Disassemble that address - what function is it?
8. This shows you where main was called from!
### Exercise 5: Trace Back from Main
1. When stopped at main, examine `$lr` (link register)
2. What address is stored there?
3. Disassemble that address - what function is it?
4. This shows you where main was called from!
### Exercise 6: Ghidra Boot Analysis
### Exercise 5: Ghidra Boot Analysis
1. In Ghidra, navigate to `_reset_handler`
2. Use **Window → Function Call Graph** to visualize the call tree
@@ -1221,9 +1277,7 @@ Understanding the boot process is critical for both attackers and defenders. Kno
│ ↓ │
│ Verify IMAGE_DEF signature │
│ ↓ │
│ Verify boot2 signature
│ ↓ │
│ Verify application signature │
│ Verify application image signature
│ ↓ │
│ If all valid: Jump to reset handler │
│ If any invalid: Refuse to boot │
@@ -1342,9 +1396,11 @@ https://datasheets.raspberrypi.com/rp2350/rp2350-datasheet.pdf
### Pico SDK Source Code
The startup code lives in:
- `crt0.S` - Main startup assembly
- `memmap_default.ld` - Default linker script
- `boot2_generic_03h.S` - Second stage bootloader
- `crt0.S` - Main startup assembly (vector table at `.section .vectors`, reset handler, data copy, BSS clear, platform_entry)
- `memmap_default.ld` - Default linker script (section ordering: `.vectors` -> `.binary_info_header` -> `.embedded_block` -> `.reset`)
- `embedded_start_block.inc.S` - IMAGE_DEF block (replaces RP2040's `boot2_generic_03h.S`)
> ⚠️ **Note:** The RP2040 used a `boot2_generic_03h.S` second-stage bootloader occupying the first 256 bytes of flash. The RP2350 eliminated this; the bootrom handles flash XIP setup directly. The SDK still includes a `boot2` mechanism for compatibility, but it is **not** placed at flash address 0 - it is embedded in the data copy table and executed from the stack during startup.
### Bootrom Source
@@ -1353,6 +1409,180 @@ https://github.com/raspberrypi/pico-bootrom-rp2350
---
## 🔬 Part 17: Proving the Boot Sequence with objdump
Everything we have learned about the boot sequence can be proven directly from the compiled ELF binary using `arm-none-eabi-objdump`. The bootrom is not in your ELF (it is mask ROM burned into the chip at `0x00000000`), but everything your firmware provides — the vector table, the IMAGE_DEF, and the reset handler — lives in your ELF starting at `0x10000000`.
### Step 1: List All Sections
```bash
arm-none-eabi-objdump -h build/0x0001_hello-world.elf
```
Expected output (key sections):
```
Idx Name Size VMA LMA
0 .text 000019cc 10000000 10000000
3 .binary_info 0000002c 10001b20 10001b20
4 .ram_vector_table 00000110 20000000 20000000
6 .data 0000019c 20000110 10001b4c
```
> 💡 The Pico SDK merges `.vectors`, `.embedded_block`, and `.reset` all into `.text` at `0x10000000`. They are not separate named ELF sections — they are sub-regions inside `.text`.
### Step 2: Dump the First 0x150 Bytes of Flash — One Command, Zero Skips
```bash
arm-none-eabi-objdump -s --start-address=0x10000000 --stop-address=0x10000150 build/0x0001_hello-world.elf
```
Raw output from that command:
```
10000000 00200820 5d010010 1b010010 1d010010 . . ]...........
10000010 11010010 11010010 11010010 11010010 ................
10000020 11010010 11010010 11010010 11010010 ................
10000030 11010010 11010010 11010010 11010010 ................
10000040 11010010 11010010 11010010 11010010 ................
10000050 11010010 11010010 11010010 11010010 ................
10000060 11010010 11010010 11010010 11010010 ................
10000070 11010010 11010010 11010010 11010010 ................
10000080 11010010 11010010 11010010 11010010 ................
10000090 11010010 11010010 11010010 11010010 ................
100000a0 11010010 11010010 11010010 11010010 ................
100000b0 11010010 11010010 11010010 11010010 ................
100000c0 11010010 11010010 11010010 11010010 ................
100000d0 11010010 11010010 11010010 11010010 ................
100000e0 11010010 11010010 11010010 11010010 ................
100000f0 11010010 11010010 11010010 11010010 ................
10000100 11010010 11010010 11010010 11010010 ................
10000110 eff30580 103800be 00be00be 00be00be .....8..........
10000120 00be00be f2eb8871 201b0010 4c1b0010 .......q ...L...
10000130 a0010010 90a31ae7 d3deffff 42012110 ............B.!.
10000140 ff010000 b01b0000 793512ab ........y5..
```
Every address annotated, no skips:
#### 0x10000000 — Vector Table, Mandatory Entries
| Address | Raw Bytes (LE) | Decoded | What it is |
|---------|----------------|---------|------------|
| `0x10000000` | `00 20 08 20` | `0x20082000` | **Initial SP** — top of SCRATCH_Y RAM. Bootrom loads MSP from here before doing anything else. |
| `0x10000004` | `5d 01 00 10` | `0x1000015d` | **Reset_Handler** address with Thumb bit set. Strip bit 0 → real address `0x1000015c`. Bootrom jumps here. |
| `0x10000008` | `1b 01 00 10` | `0x1000011b` | **NMI** handler address (Thumb, → `0x1000011a`). |
| `0x1000000c` | `1d 01 00 10` | `0x1000011d` | **HardFault** handler address (Thumb, → `0x1000011c`). |
#### 0x100000100x1000010f — Vector Table, IRQ Slots (all 52 external IRQs)
```
10000010 11010010 11010010 ...(repeats through 0x1000010f)...
```
Every 4-byte word here is `11 01 00 10` = pointer `0x10000111`.
That is the **default IRQ handler** address with Thumb bit set (→ `0x10000110`).
The RP2350 Cortex-M33 has 16 system vectors (offsets 0x000x3f) plus up to 52
external IRQ vectors (offsets 0x400xff = addresses `0x10000040``0x1000010f`).
Every IRQ the application does not register gets this default handler pointer.
This block is 240 bytes (`0x10000010` to `0x1000010f`) of nothing but that one
repeated pointer.
#### 0x100001100x10000127 — Default IRQ Handler Code
```
10000110 eff30580 103800be 00be00be 00be00be
10000120 00be00be f2eb8871
```
| Address | Bytes | ARM Thumb-2 Instruction | What it does |
|---------|-------|-------------------------|--------------|
| `0x10000110` | `ef f3 05 80` | `MRS r0, IPSR` | Read the Interrupt Program Status Register into r0. The low 9 bits = the active vector number. |
| `0x10000114` | `10 38` | `SUBS r0, #16` | Vector 16 = IRQ0, so subtract 16 to convert vector number → IRQ index. |
| `0x10000116` | `00 be` | `BKPT #0` | Software breakpoint. If a debugger is attached, it stops here and you can inspect r0 to see which IRQ fired. If no debugger is attached, the CPU enters a fault loop and the chip hangs. |
| `0x10000118``0x10000127` | `00 be` ×12 | `BKPT #0` repeating | Alignment padding to the next 4-byte boundary. |
This is the **entire** default IRQ handler. It is intentionally minimal: if your
code triggers an IRQ you did not register, it crashes visibly instead of silently.
#### 0x100001280x1000013b — Binary Info Pointer Table
```
10000120 201b0010 4c1b0010
10000130 a0010010 90a31ae7
```
| Address | Bytes (LE) | Decoded Value | What it is |
|---------|------------|---------------|------------|
| `0x10000128` | `20 1b 00 10` | `0x10001b20` | Pointer to **start** of `.binary_info` data section in flash. |
| `0x1000012c` | `4c 1b 00 10` | `0x10001b4c` | Pointer to **end** of `.binary_info` data section in flash. |
| `0x10000130` | `a0 01 00 10` | `0x100001a0` | Pointer to `binary_info_callback` function. |
| `0x10000134` | `90 a3 1a e7` | (magic marker) | `BINARY_INFO_MARKER_END` — marks the end of this pointer table. |
`picotool` reads this table to extract the program name, version string, URL,
and GPIO pin map from any compiled binary without running it.
#### 0x100001380x1000014c — IMAGE_DEF Block (this build)
```
10000130 a0010010 90a31ae7 d3deffff 42012110
10000140 ff010000 b01b0000 793512ab 4ff00000
```
| Address | Bytes | What it is |
|---------|-------|------------|
| `0x10000138` | `d3 de ff ff` | `PICOBIN_BLOCK_MARKER_START` — the bootrom scans flash for this exact 4-byte sequence to locate the IMAGE_DEF. |
| `0x1000013c` | `42 01 21 10` | IMAGE_DEF content (image type, flags, version). |
| `0x10000140` | `ff 01 00 00` | IMAGE_DEF content (continuation). |
| `0x10000144` | `b0 1b 00 00` | IMAGE_DEF content (continuation). |
| `0x10000148` | `79 35 12 ab` | `PICOBIN_BLOCK_MARKER_END` — bootrom stops scanning here. |
The IMAGE_DEF sits at `0x10000138``0x1000014b` in this build,
well within the 4 KB scan window the bootrom uses (Datasheet §5.9.5, p. 429).
#### Full Flash Map: 0x100000000x1000015c
```
0x100000000x1000000f Vector Table: mandatory entries (SP, Reset, NMI, HardFault)
0x100000100x1000010f Vector Table: 52 external IRQ slots → all point to default handler
0x100001100x10000127 Default IRQ handler code (MRS / SUBS / BKPT)
0x100001280x10000137 Binary info pointer table (start / end / callback / magic end)
0x100001380x1000014b IMAGE_DEF block (d3 de ff ff ... 79 35 12 ab)
0x100001500x1000015b (padding / alignment)
0x1000015c Reset_Handler (_reset_handler in crt0.S) ← bootrom jumps here
```
### Step 4: Confirmed Boot Sequence (proven from ELF)
```
┌─────────────────────────────────────────────────────────────────┐
│ PROVEN BOOT SEQUENCE (0x0001_hello-world) │
├─────────────────────────────────────────────────────────────────┤
│ 1. Bootrom reads 0x10000000 │
│ → SP = 0x20082000 (offset +0x00 of vector table) │
│ → RST = 0x1000015d (offset +0x04, Thumb → 0x1000015c) │
├─────────────────────────────────────────────────────────────────┤
│ 2. Bootrom scans first 4 kB for IMAGE_DEF │
│ → Found at 0x10000138 (this build) │
│ → Start marker: d3 de ff ff │
│ → End marker: 79 35 12 ab │
├─────────────────────────────────────────────────────────────────┤
│ 3. Bootrom jumps to reset handler at 0x1000015c │
│ → _reset_handler (crt0.S) runs │
│ → Checks CPUID — Core 1 sent back to bootrom │
│ → Core 0: .data copied, .bss zeroed, platform_entry called │
├─────────────────────────────────────────────────────────────────┤
│ 4. platform_entry calls runtime_init → main → exit │
└─────────────────────────────────────────────────────────────────┘
```
> 📖 **Datasheet References:**
> - §5.1.5.1 (p. 357): Block markers `0xffffded3` (start) and `0xab123579` (end)
> - §5.9.5 (p. 429): IMAGE_DEF must appear within first 4 kB of flash image
> - §5.9.5.1 (p. 429): Bootrom enters via reset handler at vector table offset +4
---
**Remember:** Understanding the boot process is fundamental to embedded systems work. Whether you're debugging a system that won't start, reverse engineering firmware, or building secure boot chains, this knowledge is essential!
Happy exploring! 🔍
+79
View File
@@ -0,0 +1,79 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 800">
<style>
.bg{fill:#0a0a0f}.pnl{fill:#12121a;stroke:#1a1a2e}.hdr{fill:#12121a}
.title{font:bold 42px 'Courier New',monospace;fill:#00ff41}
.sub{font:bold 28px 'Courier New',monospace;fill:#00d4ff}
.txt{font:24px 'Courier New',monospace;fill:#c0c0c0}
.dim{font:20px 'Courier New',monospace;fill:#888}
.grn{font:bold 24px 'Courier New',monospace;fill:#00ff41}
.red{font:bold 24px 'Courier New',monospace;fill:#ff0040}
.cyn{font:bold 24px 'Courier New',monospace;fill:#00d4ff}
.amb{font:bold 24px 'Courier New',monospace;fill:#ffaa00}
.badge{stroke:#00ff41;rx:14}
</style>
<rect class="bg" width="1200" height="800"/>
<!-- Background grid decoration -->
<g opacity="0.06">
<line x1="0" y1="100" x2="1200" y2="100" stroke="#00ff41" stroke-width="1"/>
<line x1="0" y1="200" x2="1200" y2="200" stroke="#00ff41" stroke-width="1"/>
<line x1="0" y1="300" x2="1200" y2="300" stroke="#00ff41" stroke-width="1"/>
<line x1="0" y1="400" x2="1200" y2="400" stroke="#00ff41" stroke-width="1"/>
<line x1="0" y1="500" x2="1200" y2="500" stroke="#00ff41" stroke-width="1"/>
<line x1="0" y1="600" x2="1200" y2="600" stroke="#00ff41" stroke-width="1"/>
<line x1="0" y1="700" x2="1200" y2="700" stroke="#00ff41" stroke-width="1"/>
<line x1="200" y1="0" x2="200" y2="800" stroke="#00ff41" stroke-width="1"/>
<line x1="400" y1="0" x2="400" y2="800" stroke="#00ff41" stroke-width="1"/>
<line x1="600" y1="0" x2="600" y2="800" stroke="#00ff41" stroke-width="1"/>
<line x1="800" y1="0" x2="800" y2="800" stroke="#00ff41" stroke-width="1"/>
<line x1="1000" y1="0" x2="1000" y2="800" stroke="#00ff41" stroke-width="1"/>
</g>
<!-- Hex rain decoration -->
<g opacity="0.04" font-family="'Courier New',monospace" font-size="14" fill="#00ff41">
<text x="50" y="80">4F 70 65 6E 4F 43 44</text>
<text x="900" y="120">10 00 02 34 08 B5 01</text>
<text x="150" y="180">47 44 42 20 52 45 56</text>
<text x="800" y="240">20 08 20 00 FF AA 00</text>
<text x="80" y="350">52 50 32 33 35 30 00</text>
<text x="950" y="380">0A 0A 0F 12 12 1A 1A</text>
<text x="100" y="520">41 52 4D 76 38 2D 4D</text>
<text x="870" y="560">00 FF 41 00 D4 FF 88</text>
<text x="60" y="680">47 48 49 44 52 41 00</text>
<text x="920" y="720">FF 00 40 C0 C0 C0 00</text>
</g>
<!-- Corner accents -->
<polyline points="30,30 30,80 80,80" fill="none" stroke="#00ff41" stroke-width="2" opacity="0.3"/>
<polyline points="1170,30 1170,80 1120,80" fill="none" stroke="#00ff41" stroke-width="2" opacity="0.3"/>
<polyline points="30,770 30,720 80,720" fill="none" stroke="#00ff41" stroke-width="2" opacity="0.3"/>
<polyline points="1170,770 1170,720 1120,720" fill="none" stroke="#00ff41" stroke-width="2" opacity="0.3"/>
<!-- Top accent line -->
<rect x="100" y="140" width="1000" height="2" fill="#00ff41" opacity="0.4"/>
<!-- Course Title -->
<text x="600" y="210" text-anchor="middle" font-family="'Courier New',monospace" font-size="56" font-weight="bold" fill="#00ff41">Embedded Systems</text>
<text x="600" y="278" text-anchor="middle" font-family="'Courier New',monospace" font-size="56" font-weight="bold" fill="#00ff41">Reverse Engineering</text>
<!-- Divider -->
<rect x="300" y="310" width="600" height="2" fill="#00d4ff" opacity="0.6"/>
<!-- Week Number -->
<text x="600" y="380" text-anchor="middle" font-family="'Courier New',monospace" font-size="42" font-weight="bold" fill="#00d4ff">// WEEK 03</text>
<!-- Week Topic -->
<text x="600" y="440" text-anchor="middle" font-family="'Courier New',monospace" font-size="28" fill="#c0c0c0">Embedded System Analysis:</text>
<text x="600" y="478" text-anchor="middle" font-family="'Courier New',monospace" font-size="28" fill="#c0c0c0">Understanding the RP2350 Architecture</text>
<text x="600" y="516" text-anchor="middle" font-family="'Courier New',monospace" font-size="28" fill="#c0c0c0">w/ Comprehensive Firmware Analysis</text>
<!-- Bottom accent line -->
<rect x="100" y="570" width="1000" height="2" fill="#00ff41" opacity="0.4"/>
<!-- University -->
<text x="600" y="635" text-anchor="middle" font-family="'Courier New',monospace" font-size="36" font-weight="bold" fill="#ffaa00">George Mason University</text>
<!-- Bottom badge -->
<rect x="400" y="670" width="400" height="40" rx="20" fill="none" stroke="#00ff41" stroke-width="1.5" opacity="0.5"/>
<text x="600" y="697" text-anchor="middle" font-family="'Courier New',monospace" font-size="20" fill="#00ff41" opacity="0.7">RP2350 // ARM Cortex-M33</text>
</svg>

After

Width:  |  Height:  |  Size: 4.4 KiB

+70
View File
@@ -0,0 +1,70 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 800">
<style>
.bg{fill:#0a0a0f}.pnl{fill:#12121a;stroke:#1a1a2e}.hdr{fill:#12121a}
.title{font:bold 42px 'Courier New',monospace;fill:#00ff41}
.sub{font:bold 28px 'Courier New',monospace;fill:#00d4ff}
.txt{font:24px 'Courier New',monospace;fill:#c0c0c0}
.dim{font:20px 'Courier New',monospace;fill:#888}
.grn{font:bold 24px 'Courier New',monospace;fill:#00ff41}
.red{font:bold 24px 'Courier New',monospace;fill:#ff0040}
.cyn{font:bold 24px 'Courier New',monospace;fill:#00d4ff}
.amb{font:bold 24px 'Courier New',monospace;fill:#ffaa00}
.badge{stroke:#00ff41;rx:14}
</style>
<rect class="bg" width="1200" height="800"/>
<!-- Title -->
<text x="600" y="52" text-anchor="middle" class="title">RP2350 Boot Sequence</text>
<text x="600" y="88" text-anchor="middle" class="dim">Power-On to main() — 5 Steps</text>
<!-- Step 1 -->
<rect x="40" y="110" width="1120" height="70" rx="6" fill="#12121a" stroke="#ffaa00" stroke-width="2"/>
<text x="60" y="137" class="amb">STEP 1</text>
<text x="220" y="137" class="txt">Power On</text>
<text x="60" y="167" class="dim">Cortex-M33 wakes, execution at 0x00000000 (Bootrom)</text>
<!-- Arrow -->
<text x="600" y="200" text-anchor="middle" class="grn"></text>
<!-- Step 2 -->
<rect x="40" y="208" width="1120" height="70" rx="6" fill="#12121a" stroke="#ffaa00" stroke-width="2"/>
<text x="60" y="235" class="amb">STEP 2</text>
<text x="220" y="235" class="txt">Bootrom Executes</text>
<text x="60" y="265" class="dim">32KB on-chip ROM — finds IMAGE_DEF at 0x10000000</text>
<!-- Arrow -->
<text x="600" y="298" text-anchor="middle" class="grn"></text>
<!-- Step 3 -->
<rect x="40" y="306" width="1120" height="70" rx="6" fill="#12121a" stroke="#ffaa00" stroke-width="2"/>
<text x="60" y="333" class="amb">STEP 3</text>
<text x="220" y="333" class="txt">Flash XIP Setup (bootrom-managed)</text>
<text x="60" y="363" class="dim">Bootrom configures flash interface &amp; XIP (no boot2 on RP2350)</text>
<!-- Arrow -->
<text x="600" y="396" text-anchor="middle" class="grn"></text>
<!-- Step 4 -->
<rect x="40" y="404" width="1120" height="90" rx="6" fill="#12121a" stroke="#ffaa00" stroke-width="2"/>
<text x="60" y="431" class="amb">STEP 4</text>
<text x="220" y="431" class="txt">Vector Table &amp; Reset Handler</text>
<text x="60" y="463" class="dim">Reads SP from offset 0x00 -> 0x20082000</text>
<text x="60" y="489" class="dim">Reads Reset Handler from 0x04 -> 0x1000015d</text>
<!-- Arrow -->
<text x="600" y="514" text-anchor="middle" class="grn"></text>
<!-- Step 5 -->
<rect x="40" y="524" width="1120" height="110" rx="6" fill="#12121a" stroke="#ffaa00" stroke-width="2"/>
<text x="60" y="551" class="amb">STEP 5</text>
<text x="220" y="551" class="txt">C Runtime Startup (crt0.S)</text>
<text x="60" y="579" class="dim">Copy .data from flash -> RAM</text>
<text x="60" y="603" class="dim">Zero .bss section</text>
<text x="60" y="627" class="dim">Call runtime_init() -> main()</text>
<!-- Bottom summary -->
<rect x="40" y="660" width="1120" height="110" rx="6" fill="#12121a" stroke="#ffaa00" stroke-width="2"/>
<text x="60" y="695" class="sub">Key Insight</text>
<text x="60" y="730" class="txt">Your main() is the LAST thing to run.</text>
<text x="60" y="760" class="txt">All 5 steps must complete first!</text>
</svg>
+84
View File
@@ -0,0 +1,84 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 800">
<style>
.bg{fill:#0a0a0f}.pnl{fill:#12121a;stroke:#1a1a2e}.hdr{fill:#12121a}
.title{font:bold 42px 'Courier New',monospace;fill:#00ff41}
.sub{font:bold 28px 'Courier New',monospace;fill:#00d4ff}
.txt{font:24px 'Courier New',monospace;fill:#c0c0c0}
.dim{font:20px 'Courier New',monospace;fill:#888}
.grn{font:bold 24px 'Courier New',monospace;fill:#00ff41}
.red{font:bold 24px 'Courier New',monospace;fill:#ff0040}
.cyn{font:bold 24px 'Courier New',monospace;fill:#00d4ff}
.amb{font:bold 24px 'Courier New',monospace;fill:#ffaa00}
.badge{stroke:#00ff41;rx:14}
</style>
<rect class="bg" width="1200" height="800"/>
<!-- Title -->
<text x="600" y="52" text-anchor="middle" class="title">The Bootrom</text>
<text x="600" y="88" text-anchor="middle" class="dim">32KB Factory-Programmed ROM — Where It All Begins</text>
<!-- Left Panel: Properties -->
<rect x="40" y="110" width="540" height="340" rx="8" class="pnl"/>
<text x="60" y="148" class="sub">Bootrom Properties</text>
<rect x="60" y="170" width="500" height="42" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
<text x="75" y="198" class="txt">Size</text>
<text x="340" y="198" class="grn">32 KB</text>
<rect x="60" y="222" width="500" height="42" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
<text x="75" y="250" class="txt">Location</text>
<text x="340" y="250" class="cyn">0x00000000</text>
<rect x="60" y="274" width="500" height="42" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
<text x="75" y="302" class="txt">Modifiable?</text>
<text x="340" y="302" class="red">NO — mask ROM</text>
<rect x="60" y="326" width="500" height="42" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
<text x="75" y="354" class="txt">Purpose</text>
<text x="340" y="354" class="amb">Boot the chip</text>
<text x="60" y="420" class="dim">Burned into silicon at factory</text>
<text x="60" y="445" class="dim">Like BIOS in your computer</text>
<!-- Right Panel: What It Does -->
<rect x="620" y="110" width="540" height="340" rx="8" class="pnl"/>
<text x="640" y="148" class="sub">What It Does</text>
<rect x="640" y="170" width="500" height="42" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
<text x="655" y="198" class="grn">1.</text>
<text x="700" y="198" class="txt">Initialize hardware</text>
<rect x="640" y="222" width="500" height="42" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
<text x="655" y="250" class="grn">2.</text>
<text x="700" y="250" class="txt">Check boot sources</text>
<rect x="640" y="274" width="500" height="42" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
<text x="655" y="302" class="grn">3.</text>
<text x="700" y="302" class="txt">Validate IMAGE_DEF</text>
<rect x="640" y="326" width="500" height="42" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
<text x="655" y="354" class="grn">4.</text>
<text x="700" y="354" class="txt">Configure flash</text>
<rect x="640" y="378" width="500" height="42" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
<text x="655" y="406" class="grn">5.</text>
<text x="700" y="406" class="txt">Jump to your code</text>
<!-- Bottom Panel: IMAGE_DEF -->
<rect x="40" y="475" width="1120" height="295" rx="8" class="pnl"/>
<text x="60" y="513" class="sub">IMAGE_DEF — Magic Markers</text>
<text x="60" y="548" class="dim">Bootrom looks for these to validate firmware</text>
<rect x="60" y="565" width="1080" height="50" rx="4" fill="#0a0a0f" stroke="#00ff41" stroke-width="2"/>
<text x="80" y="598" class="grn">Start Marker</text>
<text x="380" y="598" class="cyn">0xFFFFDED3</text>
<text x="680" y="598" class="dim">"I'm a valid Pico binary!"</text>
<rect x="60" y="625" width="1080" height="50" rx="4" fill="#0a0a0f" stroke="#00ff41" stroke-width="2"/>
<text x="80" y="658" class="grn">End Marker</text>
<text x="380" y="658" class="cyn">0xAB123579</text>
<text x="680" y="658" class="dim">"End of header block"</text>
<text x="60" y="718" class="txt">Bootrom reads flash at 0x10000000,</text>
<text x="60" y="748" class="txt">finds these markers, then boots.</text>
</svg>

After

Width:  |  Height:  |  Size: 3.9 KiB

+74
View File
@@ -0,0 +1,74 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 800">
<style>
.bg{fill:#0a0a0f}.pnl{fill:#12121a;stroke:#1a1a2e}.hdr{fill:#12121a}
.title{font:bold 42px 'Courier New',monospace;fill:#00ff41}
.sub{font:bold 28px 'Courier New',monospace;fill:#00d4ff}
.txt{font:24px 'Courier New',monospace;fill:#c0c0c0}
.dim{font:20px 'Courier New',monospace;fill:#888}
.grn{font:bold 24px 'Courier New',monospace;fill:#00ff41}
.red{font:bold 24px 'Courier New',monospace;fill:#ff0040}
.cyn{font:bold 24px 'Courier New',monospace;fill:#00d4ff}
.amb{font:bold 24px 'Courier New',monospace;fill:#ffaa00}
.badge{stroke:#00ff41;rx:14}
</style>
<rect class="bg" width="1200" height="800"/>
<!-- Title -->
<text x="600" y="52" text-anchor="middle" class="title">XIP — Execute In Place</text>
<text x="600" y="88" text-anchor="middle" class="dim">Run Code Directly from Flash — No Copy Needed</text>
<!-- Left Panel: Analogy -->
<rect x="40" y="110" width="540" height="220" rx="8" class="pnl"/>
<text x="60" y="148" class="sub">Book Analogy</text>
<rect x="60" y="168" width="500" height="60" rx="4" fill="#0a0a0f" stroke="#ff0040" stroke-width="1"/>
<text x="75" y="195" class="red">Without XIP</text>
<text x="75" y="220" class="dim">Photocopy every page, read copy</text>
<rect x="60" y="240" width="500" height="60" rx="4" fill="#0a0a0f" stroke="#00ff41" stroke-width="1"/>
<text x="75" y="267" class="grn">With XIP</text>
<text x="75" y="292" class="dim">Read directly from the book!</text>
<!-- Right Panel: Advantages -->
<rect x="620" y="110" width="540" height="220" rx="8" class="pnl"/>
<text x="640" y="148" class="sub">Why Use XIP?</text>
<rect x="640" y="168" width="500" height="42" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
<text x="655" y="196" class="grn">Saves RAM</text>
<text x="900" y="196" class="dim">Code stays in flash</text>
<rect x="640" y="220" width="500" height="42" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
<text x="655" y="248" class="grn">Faster Boot</text>
<text x="900" y="248" class="dim">No bulk copy needed</text>
<rect x="640" y="272" width="500" height="42" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
<text x="655" y="300" class="grn">Simpler</text>
<text x="900" y="300" class="dim">Less memory mgmt</text>
<!-- Bottom Panel: Flash Layout at 0x10000000 -->
<rect x="40" y="355" width="1120" height="415" rx="8" class="pnl"/>
<text x="60" y="393" class="sub">XIP Flash Region at 0x10000000</text>
<!-- Vector Table block -->
<rect x="60" y="415" width="1080" height="80" rx="4" fill="#0f1a0f" stroke="#00ff41" stroke-width="2"/>
<text x="80" y="445" class="grn">Vector Table</text>
<text x="80" y="475" class="dim">SP at offset 0x00 | Reset Handler at offset 0x04 | Exception handlers...</text>
<!-- Your Code block -->
<rect x="60" y="510" width="1080" height="80" rx="4" fill="#0a0a0f" stroke="#00d4ff" stroke-width="2"/>
<text x="80" y="540" class="cyn">Your Code</text>
<text x="80" y="570" class="dim">_reset_handler | main() | other functions</text>
<!-- Read-Only Data block -->
<rect x="60" y="605" width="1080" height="80" rx="4" fill="#0a0a0f" stroke="#ffaa00" stroke-width="2"/>
<text x="80" y="635" class="amb">Read-Only Data</text>
<text x="80" y="665" class="dim">Strings like "hello, world" | constant values</text>
<!-- Address labels -->
<text x="1040" y="445" class="dim" text-anchor="end">0x10000000</text>
<text x="1040" y="540" class="dim" text-anchor="end">0x100001xx</text>
<text x="1040" y="635" class="dim" text-anchor="end">0x10001xxx</text>
<text x="60" y="730" class="txt">CPU fetches instructions directly</text>
<text x="60" y="760" class="txt">from flash via XIP cache.</text>
</svg>

After

Width:  |  Height:  |  Size: 3.6 KiB

+80
View File
@@ -0,0 +1,80 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 800">
<style>
.bg{fill:#0a0a0f}.pnl{fill:#12121a;stroke:#1a1a2e}.hdr{fill:#12121a}
.title{font:bold 42px 'Courier New',monospace;fill:#00ff41}
.sub{font:bold 28px 'Courier New',monospace;fill:#00d4ff}
.txt{font:24px 'Courier New',monospace;fill:#c0c0c0}
.dim{font:20px 'Courier New',monospace;fill:#888}
.grn{font:bold 24px 'Courier New',monospace;fill:#00ff41}
.red{font:bold 24px 'Courier New',monospace;fill:#ff0040}
.cyn{font:bold 24px 'Courier New',monospace;fill:#00d4ff}
.amb{font:bold 24px 'Courier New',monospace;fill:#ffaa00}
.badge{stroke:#00ff41;rx:14}
</style>
<rect class="bg" width="1200" height="800"/>
<!-- Title -->
<text x="600" y="52" text-anchor="middle" class="title">The Vector Table</text>
<text x="600" y="88" text-anchor="middle" class="dim">CPU's Instruction Manual at 0x10000000</text>
<!-- Main Panel -->
<rect x="40" y="110" width="1120" height="440" rx="8" class="pnl"/>
<text x="60" y="148" class="sub">Vector Table Layout</text>
<!-- Header row -->
<rect x="60" y="168" width="1080" height="42" rx="4" fill="#1a1a2e"/>
<text x="80" y="196" class="cyn">Offset</text>
<text x="220" y="196" class="cyn">Address</text>
<text x="440" y="196" class="cyn">Value</text>
<text x="680" y="196" class="cyn">Meaning</text>
<!-- Row 0x00 -->
<rect x="60" y="220" width="1080" height="50" rx="4" fill="#0a0a0f" stroke="#00ff41" stroke-width="2"/>
<text x="80" y="252" class="grn">0x00</text>
<text x="220" y="252" class="txt">0x10000000</text>
<text x="440" y="252" class="grn">0x20082000</text>
<text x="680" y="252" class="txt">Initial SP</text>
<!-- Row 0x04 -->
<rect x="60" y="280" width="1080" height="50" rx="4" fill="#0a0a0f" stroke="#00d4ff" stroke-width="2"/>
<text x="80" y="312" class="cyn">0x04</text>
<text x="220" y="312" class="txt">0x10000004</text>
<text x="440" y="312" class="cyn">0x1000015D</text>
<text x="680" y="312" class="txt">Reset Handler</text>
<!-- Row 0x08 -->
<rect x="60" y="340" width="1080" height="50" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
<text x="80" y="372" class="dim">0x08</text>
<text x="220" y="372" class="txt">0x10000008</text>
<text x="440" y="372" class="txt">0x1000011B</text>
<text x="680" y="372" class="txt">NMI Handler</text>
<!-- Row 0x0C -->
<rect x="60" y="400" width="1080" height="50" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
<text x="80" y="432" class="dim">0x0C</text>
<text x="220" y="432" class="txt">0x1000000C</text>
<text x="440" y="432" class="txt">0x1000011D</text>
<text x="680" y="432" class="txt">HardFault Handler</text>
<!-- GDB command -->
<rect x="60" y="470" width="1080" height="50" rx="4" fill="#0a0a0f" stroke="#ffaa00" stroke-width="1"/>
<text x="80" y="502" class="amb">GDB:</text>
<text x="180" y="502" class="txt">x/4x 0x10000000</text>
<!-- Bottom Panel: What happens -->
<rect x="40" y="575" width="540" height="195" rx="8" class="pnl"/>
<text x="60" y="613" class="sub">On Power-On</text>
<text x="60" y="650" class="txt">1. CPU reads SP from 0x00</text>
<text x="60" y="682" class="txt">2. Sets SP = 0x20082000</text>
<text x="60" y="714" class="txt">3. Reads Reset from 0x04</text>
<text x="60" y="746" class="txt">4. Jumps to 0x1000015C</text>
<!-- Bottom Right: Handlers -->
<rect x="620" y="575" width="540" height="195" rx="8" class="pnl"/>
<text x="640" y="613" class="sub">Default Handlers</text>
<text x="640" y="650" class="txt">NMI, HardFault, SVCall,</text>
<text x="640" y="682" class="txt">PendSV, SysTick all use:</text>
<rect x="660" y="700" width="480" height="42" rx="4" fill="#0a0a0f" stroke="#ff0040" stroke-width="1"/>
<text x="680" y="728" class="red">bkpt 0x0000</text>
<text x="880" y="728" class="dim">&lt;- stops debugger</text>
</svg>
+70
View File
@@ -0,0 +1,70 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 800">
<style>
.bg{fill:#0a0a0f}.pnl{fill:#12121a;stroke:#1a1a2e}.hdr{fill:#12121a}
.title{font:bold 42px 'Courier New',monospace;fill:#00ff41}
.sub{font:bold 28px 'Courier New',monospace;fill:#00d4ff}
.txt{font:24px 'Courier New',monospace;fill:#c0c0c0}
.dim{font:20px 'Courier New',monospace;fill:#888}
.grn{font:bold 24px 'Courier New',monospace;fill:#00ff41}
.red{font:bold 24px 'Courier New',monospace;fill:#ff0040}
.cyn{font:bold 24px 'Courier New',monospace;fill:#00d4ff}
.amb{font:bold 24px 'Courier New',monospace;fill:#ffaa00}
.badge{stroke:#00ff41;rx:14}
</style>
<rect class="bg" width="1200" height="800"/>
<!-- Title -->
<text x="600" y="52" text-anchor="middle" class="title">Thumb Mode Addressing</text>
<text x="600" y="88" text-anchor="middle" class="dim">Why Addresses End in Odd Numbers</text>
<!-- Top Panel: The Rule -->
<rect x="40" y="110" width="1120" height="200" rx="8" class="pnl"/>
<text x="60" y="148" class="sub">The LSB Rule</text>
<text x="60" y="185" class="txt">ARM Cortex-M uses the Least Significant</text>
<text x="60" y="215" class="txt">Bit (LSB) to indicate instruction mode:</text>
<!-- LSB = 1 -->
<rect x="60" y="240" width="520" height="50" rx="4" fill="#0a0a0f" stroke="#00ff41" stroke-width="2"/>
<text x="80" y="272" class="grn">LSB = 1 (odd)</text>
<text x="370" y="272" class="txt">Thumb mode</text>
<!-- LSB = 0 -->
<rect x="620" y="240" width="520" height="50" rx="4" fill="#0a0a0f" stroke="#ff0040" stroke-width="1"/>
<text x="640" y="272" class="red">LSB = 0 (even)</text>
<text x="940" y="272" class="dim">ARM mode</text>
<!-- Middle Panel: Example -->
<rect x="40" y="335" width="1120" height="210" rx="8" class="pnl"/>
<text x="60" y="373" class="sub">Reset Handler Example</text>
<text x="60" y="415" class="txt">Vector table stores:</text>
<text x="460" y="415" class="cyn">0x1000015D</text>
<text x="60" y="460" class="txt">Actual code address:</text>
<text x="460" y="460" class="grn">0x1000015C</text>
<text x="60" y="505" class="txt">The +1 means:</text>
<text x="460" y="505" class="amb">"Use Thumb mode"</text>
<!-- Bottom: GDB vs Ghidra -->
<rect x="40" y="570" width="540" height="200" rx="8" class="pnl"/>
<text x="60" y="608" class="sub">GDB Shows</text>
<rect x="60" y="625" width="500" height="50" rx="4" fill="#0a0a0f" stroke="#00d4ff" stroke-width="1"/>
<text x="80" y="657" class="cyn">0x1000015D</text>
<text x="320" y="657" class="dim">with Thumb bit</text>
<rect x="60" y="685" width="500" height="50" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
<text x="80" y="717" class="txt">Vector table raw value</text>
<!-- Ghidra -->
<rect x="620" y="570" width="540" height="200" rx="8" class="pnl"/>
<text x="640" y="608" class="sub">Ghidra Shows</text>
<rect x="640" y="625" width="500" height="50" rx="4" fill="#0a0a0f" stroke="#00ff41" stroke-width="1"/>
<text x="660" y="657" class="grn">0x1000015C</text>
<text x="900" y="657" class="dim">actual address</text>
<rect x="640" y="685" width="500" height="50" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
<text x="660" y="717" class="txt">Real instruction location</text>
<text x="600" y="757" text-anchor="middle" class="amb">Both are correct — just displayed differently!</text>
</svg>

After

Width:  |  Height:  |  Size: 3.2 KiB

+69
View File
@@ -0,0 +1,69 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 800">
<style>
.bg{fill:#0a0a0f}.pnl{fill:#12121a;stroke:#1a1a2e}.hdr{fill:#12121a}
.title{font:bold 42px 'Courier New',monospace;fill:#00ff41}
.sub{font:bold 28px 'Courier New',monospace;fill:#00d4ff}
.txt{font:24px 'Courier New',monospace;fill:#c0c0c0}
.dim{font:20px 'Courier New',monospace;fill:#888}
.grn{font:bold 24px 'Courier New',monospace;fill:#00ff41}
.red{font:bold 24px 'Courier New',monospace;fill:#ff0040}
.cyn{font:bold 24px 'Courier New',monospace;fill:#00d4ff}
.amb{font:bold 24px 'Courier New',monospace;fill:#ffaa00}
.badge{stroke:#00ff41;rx:14}
</style>
<rect class="bg" width="1200" height="800"/>
<!-- Title -->
<text x="600" y="52" text-anchor="middle" class="title">Linker Script Memory Map</text>
<text x="600" y="88" text-anchor="middle" class="dim">memmap_default.ld — Where Everything Lives</text>
<!-- Main Panel: Memory Regions -->
<rect x="40" y="110" width="1120" height="380" rx="8" class="pnl"/>
<text x="60" y="148" class="sub">Memory Regions</text>
<!-- Flash -->
<rect x="60" y="168" width="1080" height="60" rx="4" fill="#0f1a0f" stroke="#00ff41" stroke-width="2"/>
<text x="80" y="198" class="grn">Flash (XIP)</text>
<text x="380" y="198" class="cyn">0x10000000</text>
<text x="640" y="198" class="txt">varies</text>
<text x="820" y="198" class="dim">Your code (read-only)</text>
<!-- RAM -->
<rect x="60" y="240" width="1080" height="60" rx="4" fill="#0a0a1f" stroke="#00d4ff" stroke-width="2"/>
<text x="80" y="270" class="cyn">RAM</text>
<text x="380" y="270" class="cyn">0x20000000</text>
<text x="640" y="270" class="txt">512 KB</text>
<text x="820" y="270" class="dim">Main RAM (r/w)</text>
<!-- SCRATCH_X -->
<rect x="60" y="312" width="1080" height="60" rx="4" fill="#0a0a0f" stroke="#ffaa00" stroke-width="1"/>
<text x="80" y="342" class="amb">SCRATCH_X</text>
<text x="380" y="342" class="cyn">0x20080000</text>
<text x="640" y="342" class="txt">4 KB</text>
<text x="820" y="342" class="dim">Core 0 scratch (HW: SRAM8)</text>
<!-- SCRATCH_Y -->
<rect x="60" y="384" width="1080" height="60" rx="4" fill="#1a0a0a" stroke="#ff0040" stroke-width="2"/>
<text x="80" y="414" class="red">SCRATCH_Y</text>
<text x="380" y="414" class="cyn">0x20081000</text>
<text x="640" y="414" class="txt">4 KB</text>
<text x="820" y="414" class="dim">Core 0 stack! (HW: SRAM9)</text>
<!-- Bottom Panel: Stack Calculation -->
<rect x="40" y="515" width="1120" height="255" rx="8" class="pnl"/>
<text x="60" y="553" class="sub">Stack Pointer Calculation</text>
<text x="60" y="593" class="txt">__StackTop = ORIGIN(SCRATCH_Y)</text>
<text x="60" y="623" class="txt"> + LENGTH(SCRATCH_Y)</text>
<rect x="60" y="650" width="1080" height="100" rx="4" fill="#0a0a0f" stroke="#00ff41" stroke-width="2"/>
<text x="80" y="682" class="amb">ORIGIN</text>
<text x="260" y="682" class="cyn">0x20081000</text>
<text x="500" y="682" class="amb">+ LENGTH</text>
<text x="700" y="682" class="cyn">0x1000</text>
<text x="830" y="682" class="dim">(4 KB)</text>
<text x="80" y="728" class="grn">= __StackTop = 0x20082000</text>
<text x="680" y="728" class="dim">&lt;- matches vector table!</text>
</svg>
+87
View File
@@ -0,0 +1,87 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 800">
<style>
.bg{fill:#0a0a0f}.pnl{fill:#12121a;stroke:#1a1a2e}.hdr{fill:#12121a}
.title{font:bold 42px 'Courier New',monospace;fill:#00ff41}
.sub{font:bold 28px 'Courier New',monospace;fill:#00d4ff}
.txt{font:24px 'Courier New',monospace;fill:#c0c0c0}
.dim{font:20px 'Courier New',monospace;fill:#888}
.grn{font:bold 24px 'Courier New',monospace;fill:#00ff41}
.red{font:bold 24px 'Courier New',monospace;fill:#ff0040}
.cyn{font:bold 24px 'Courier New',monospace;fill:#00d4ff}
.amb{font:bold 24px 'Courier New',monospace;fill:#ffaa00}
.badge{stroke:#00ff41;rx:14}
</style>
<rect class="bg" width="1200" height="800"/>
<!-- Title -->
<text x="600" y="52" text-anchor="middle" class="title">Reset Handler — 4 Phases</text>
<text x="600" y="88" text-anchor="middle" class="dim">_reset_handler at 0x1000015C</text>
<!-- Phase 1 -->
<rect x="40" y="110" width="555" height="150" rx="8" class="pnl" stroke="#ffaa00" stroke-width="2"/>
<text x="60" y="143" class="amb">Phase 1: Core Check</text>
<text x="60" y="170" class="dim">0x1000015C — 0x10000168</text>
<rect x="60" y="185" width="515" height="42" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
<text x="75" y="213" class="txt">mov r0, #0xD0000000</text>
<text x="75" y="248" class="dim">Read CPUID -> Core 0 continues</text>
<!-- Phase 2 -->
<rect x="625" y="110" width="535" height="150" rx="8" class="pnl" stroke="#00d4ff" stroke-width="2"/>
<text x="645" y="143" class="cyn">Phase 2: Data Copy</text>
<text x="645" y="170" class="dim">0x1000016A — 0x10000176</text>
<rect x="645" y="185" width="495" height="42" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
<text x="660" y="213" class="txt">ldmia r4!, {r1,r2,r3}</text>
<text x="645" y="248" class="dim">Copy .data from flash -> RAM</text>
<!-- Phase 3 -->
<rect x="40" y="280" width="555" height="150" rx="8" class="pnl" stroke="#00ff41" stroke-width="2"/>
<text x="60" y="313" class="grn">Phase 3: BSS Clear</text>
<text x="60" y="340" class="dim">0x10000178 — 0x10000184</text>
<rect x="60" y="355" width="515" height="42" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
<text x="75" y="383" class="txt">stmia r1!, {r0}</text>
<text x="340" y="383" class="dim">r0 = 0</text>
<text x="60" y="418" class="dim">Zero all uninitialized globals</text>
<!-- Phase 4 -->
<rect x="625" y="280" width="535" height="150" rx="8" class="pnl" stroke="#ff0040" stroke-width="2"/>
<text x="645" y="313" class="red">Phase 4: Platform Entry</text>
<text x="645" y="340" class="dim">0x10000186+</text>
<rect x="645" y="355" width="495" height="42" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
<text x="660" y="383" class="txt">blx r1</text>
<text x="800" y="383" class="dim">-> main()</text>
<text x="645" y="418" class="dim">runtime_init -> main -> exit</text>
<!-- Bottom: Flow Diagram -->
<rect x="40" y="455" width="1120" height="315" rx="8" class="pnl"/>
<text x="60" y="493" class="sub">Execution Flow</text>
<!-- Step boxes -->
<rect x="60" y="513" width="220" height="70" rx="6" fill="#0a0a0f" stroke="#ffaa00" stroke-width="2"/>
<text x="170" y="543" text-anchor="middle" class="amb">Core Check</text>
<text x="170" y="569" text-anchor="middle" class="dim">CPUID == 0?</text>
<text x="303" y="553" text-anchor="middle" class="grn">-></text>
<rect x="325" y="513" width="200" height="70" rx="6" fill="#0a0a0f" stroke="#00d4ff" stroke-width="2"/>
<text x="425" y="543" text-anchor="middle" class="cyn">Data Copy</text>
<text x="425" y="569" text-anchor="middle" class="dim">flash -> RAM</text>
<text x="548" y="553" text-anchor="middle" class="grn">-></text>
<rect x="570" y="513" width="200" height="70" rx="6" fill="#0a0a0f" stroke="#00ff41" stroke-width="2"/>
<text x="670" y="543" text-anchor="middle" class="grn">BSS Clear</text>
<text x="670" y="569" text-anchor="middle" class="dim">zero globals</text>
<text x="793" y="553" text-anchor="middle" class="grn">-></text>
<rect x="815" y="513" width="305" height="70" rx="6" fill="#0a0a0f" stroke="#ff0040" stroke-width="2"/>
<text x="967" y="543" text-anchor="middle" class="red">Platform Entry</text>
<text x="967" y="569" text-anchor="middle" class="dim">-> main()!</text>
<!-- Dual core note -->
<rect x="60" y="610" width="1080" height="150" rx="6" fill="#0a0a0f" stroke="#ffaa00" stroke-width="1"/>
<text x="80" y="645" class="amb">Why check cores?</text>
<text x="80" y="680" class="txt">RP2350 has 2 cores.</text>
<text x="80" y="710" class="txt">Only Core 0 runs startup.</text>
<text x="80" y="740" class="dim">Core 1 returns to bootrom and waits.</text>
</svg>
+93
View File
@@ -0,0 +1,93 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 800">
<style>
.bg{fill:#0a0a0f}.pnl{fill:#12121a;stroke:#1a1a2e}.hdr{fill:#12121a}
.title{font:bold 42px 'Courier New',monospace;fill:#00ff41}
.sub{font:bold 28px 'Courier New',monospace;fill:#00d4ff}
.txt{font:24px 'Courier New',monospace;fill:#c0c0c0}
.dim{font:20px 'Courier New',monospace;fill:#888}
.grn{font:bold 24px 'Courier New',monospace;fill:#00ff41}
.red{font:bold 24px 'Courier New',monospace;fill:#ff0040}
.cyn{font:bold 24px 'Courier New',monospace;fill:#00d4ff}
.amb{font:bold 24px 'Courier New',monospace;fill:#ffaa00}
.badge{stroke:#00ff41;rx:14}
</style>
<rect class="bg" width="1200" height="800"/>
<!-- Title -->
<text x="600" y="52" text-anchor="middle" class="title">Data Copy &amp; BSS Clear</text>
<text x="600" y="88" text-anchor="middle" class="dim">Initializing RAM Before main() Can Run</text>
<!-- Left Panel: Data Copy -->
<rect x="40" y="110" width="555" height="420" rx="8" class="pnl" stroke="#00d4ff" stroke-width="2"/>
<text x="60" y="148" class="cyn">Phase 2: Data Copy</text>
<text x="60" y="178" class="dim">Copy initialized variables flash -> RAM</text>
<text x="60" y="218" class="txt">C code:</text>
<rect x="60" y="230" width="515" height="42" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
<text x="75" y="258" class="amb">int counter = 42;</text>
<text x="60" y="300" class="txt">Value 42 stored in flash</text>
<text x="60" y="330" class="txt">but variables live in RAM!</text>
<!-- Flash -> RAM diagram -->
<rect x="60" y="358" width="210" height="60" rx="4" fill="#0f1a0f" stroke="#00ff41" stroke-width="2"/>
<text x="165" y="395" text-anchor="middle" class="grn">Flash</text>
<text x="290" y="395" class="amb">-></text>
<rect x="320" y="358" width="210" height="60" rx="4" fill="#0a0a1f" stroke="#00d4ff" stroke-width="2"/>
<text x="425" y="395" text-anchor="middle" class="cyn">RAM</text>
<!-- data_cpy_table -->
<text x="60" y="448" class="dim">data_cpy_table has entries:</text>
<rect x="60" y="458" width="515" height="55" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
<text x="75" y="482" class="dim">src: 0x10001B4C (flash)</text>
<text x="75" y="507" class="dim">dst: 0x20000110 (RAM)</text>
<!-- Right Panel: BSS Clear -->
<rect x="625" y="110" width="535" height="420" rx="8" class="pnl" stroke="#00ff41" stroke-width="2"/>
<text x="645" y="148" class="grn">Phase 3: BSS Clear</text>
<text x="645" y="178" class="dim">Zero uninitialized global variables</text>
<text x="645" y="218" class="txt">C code:</text>
<rect x="645" y="230" width="495" height="42" rx="4" fill="#0a0a0f" stroke="#1a1a2e"/>
<text x="660" y="258" class="amb">int my_counter;</text>
<text x="645" y="300" class="txt">C standard requires</text>
<text x="645" y="330" class="txt">this to start at zero.</text>
<!-- BSS loop diagram -->
<rect x="645" y="358" width="495" height="110" rx="4" fill="#0a0a0f" stroke="#00ff41" stroke-width="1"/>
<text x="665" y="388" class="txt">r1 = BSS start</text>
<text x="665" y="418" class="txt">r2 = BSS end</text>
<text x="665" y="448" class="txt">r0 = 0</text>
<text x="645" y="498" class="dim">Loop: store 0, advance r1</text>
<text x="645" y="524" class="dim">Until r1 == r2 -> done!</text>
<!-- Bottom Panel: Assembly -->
<rect x="40" y="555" width="1120" height="215" rx="8" class="pnl"/>
<text x="60" y="593" class="sub">Key Assembly Instructions</text>
<!-- Data Copy ASM -->
<rect x="60" y="610" width="530" height="42" rx="4" fill="#0a0a0f" stroke="#00d4ff" stroke-width="1"/>
<text x="75" y="638" class="cyn">ldmia r4!, {r1,r2,r3}</text>
<text x="60" y="672" class="dim">Load source, dest, end from table</text>
<rect x="60" y="690" width="530" height="42" rx="4" fill="#0a0a0f" stroke="#00d4ff" stroke-width="1"/>
<text x="75" y="718" class="cyn">bl data_cpy</text>
<text x="60" y="750" class="dim">Copy word-by-word until done</text>
<!-- BSS Clear ASM -->
<rect x="630" y="610" width="510" height="42" rx="4" fill="#0a0a0f" stroke="#00ff41" stroke-width="1"/>
<text x="645" y="638" class="grn">movs r0, #0</text>
<text x="630" y="672" class="dim">Load zero into r0</text>
<rect x="630" y="690" width="510" height="42" rx="4" fill="#0a0a0f" stroke="#00ff41" stroke-width="1"/>
<text x="645" y="718" class="grn">stmia r1!, {r0}</text>
<text x="630" y="750" class="dim">Store zero, advance pointer</text>
</svg>
+82
View File
@@ -0,0 +1,82 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 800">
<style>
.bg{fill:#0a0a0f}.pnl{fill:#12121a;stroke:#1a1a2e}.hdr{fill:#12121a}
.title{font:bold 42px 'Courier New',monospace;fill:#00ff41}
.sub{font:bold 28px 'Courier New',monospace;fill:#00d4ff}
.txt{font:24px 'Courier New',monospace;fill:#c0c0c0}
.dim{font:20px 'Courier New',monospace;fill:#888}
.grn{font:bold 24px 'Courier New',monospace;fill:#00ff41}
.red{font:bold 24px 'Courier New',monospace;fill:#ff0040}
.cyn{font:bold 24px 'Courier New',monospace;fill:#00d4ff}
.amb{font:bold 24px 'Courier New',monospace;fill:#ffaa00}
.badge{stroke:#00ff41;rx:14}
</style>
<rect class="bg" width="1200" height="800"/>
<!-- Title -->
<text x="600" y="52" text-anchor="middle" class="title">Platform Entry -> main()</text>
<text x="600" y="88" text-anchor="middle" class="dim">The Final Step — 3 Function Calls at 0x10000186</text>
<!-- Top Panel: Assembly -->
<rect x="40" y="110" width="1120" height="250" rx="8" class="pnl"/>
<text x="60" y="148" class="sub">platform_entry Assembly</text>
<rect x="60" y="168" width="1080" height="42" rx="4" fill="#0a0a0f" stroke="#ffaa00" stroke-width="1"/>
<text x="80" y="196" class="amb">0x10000186</text>
<text x="310" y="196" class="txt">ldr r1, [DAT]</text>
<text x="640" y="196" class="dim">-> load runtime_init addr</text>
<rect x="60" y="218" width="1080" height="42" rx="4" fill="#0a0a0f" stroke="#ffaa00" stroke-width="1"/>
<text x="80" y="246" class="amb">0x10000188</text>
<text x="310" y="246" class="txt">blx r1</text>
<text x="640" y="246" class="cyn">-> call runtime_init()</text>
<rect x="60" y="268" width="1080" height="42" rx="4" fill="#0a0a0f" stroke="#00ff41" stroke-width="2"/>
<text x="80" y="296" class="grn">0x1000018C</text>
<text x="310" y="296" class="txt">blx r1</text>
<text x="640" y="296" class="grn">-> call main()</text>
<rect x="60" y="318" width="1080" height="42" rx="4" fill="#0a0a0f" stroke="#ff0040" stroke-width="1"/>
<text x="80" y="346" class="red">0x10000190</text>
<text x="310" y="346" class="txt">blx r1</text>
<text x="640" y="346" class="red">-> call exit()</text>
<!-- Middle: Flow boxes -->
<rect x="40" y="385" width="1120" height="160" rx="8" class="pnl"/>
<text x="60" y="423" class="sub">Call Sequence</text>
<rect x="60" y="443" width="300" height="80" rx="6" fill="#0a0a0f" stroke="#ffaa00" stroke-width="2"/>
<text x="210" y="478" text-anchor="middle" class="amb">runtime_init()</text>
<text x="210" y="508" text-anchor="middle" class="dim">SDK setup</text>
<text x="390" y="488" text-anchor="middle" class="grn">-></text>
<rect x="420" y="443" width="300" height="80" rx="6" fill="#0a0a0f" stroke="#00ff41" stroke-width="2"/>
<text x="570" y="478" text-anchor="middle" class="grn">main()</text>
<text x="570" y="508" text-anchor="middle" class="dim">YOUR CODE</text>
<text x="750" y="488" text-anchor="middle" class="grn">-></text>
<rect x="780" y="443" width="300" height="80" rx="6" fill="#0a0a0f" stroke="#ff0040" stroke-width="2"/>
<text x="930" y="478" text-anchor="middle" class="red">exit()</text>
<text x="930" y="508" text-anchor="middle" class="dim">cleanup</text>
<!-- Bottom Panel: Details -->
<rect x="40" y="570" width="540" height="200" rx="8" class="pnl"/>
<text x="60" y="608" class="sub">runtime_init()</text>
<text x="60" y="645" class="txt">Initializes SDK systems:</text>
<text x="60" y="677" class="dim">• Clock configuration</text>
<text x="60" y="705" class="dim">• GPIO setup</text>
<text x="60" y="733" class="dim">• C++ constructor calls</text>
<text x="60" y="761" class="dim">• Peripheral initialization</text>
<rect x="620" y="570" width="540" height="200" rx="8" class="pnl"/>
<text x="640" y="608" class="sub">After main() Returns</text>
<text x="640" y="645" class="txt">exit() handles cleanup.</text>
<text x="640" y="677" class="txt">Then:</text>
<rect x="660" y="700" width="480" height="42" rx="4" fill="#0a0a0f" stroke="#ff0040" stroke-width="1"/>
<text x="680" y="728" class="red">bkpt 0x0000</text>
<text x="900" y="728" class="dim">&lt;- infinite halt</text>
<text x="640" y="760" class="dim">Should never be reached!</text>
</svg>
+92
View File
@@ -0,0 +1,92 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 800">
<style>
.bg{fill:#0a0a0f}.pnl{fill:#12121a;stroke:#1a1a2e}.hdr{fill:#12121a}
.title{font:bold 42px 'Courier New',monospace;fill:#00ff41}
.sub{font:bold 28px 'Courier New',monospace;fill:#00d4ff}
.txt{font:24px 'Courier New',monospace;fill:#c0c0c0}
.dim{font:20px 'Courier New',monospace;fill:#888}
.grn{font:bold 24px 'Courier New',monospace;fill:#00ff41}
.red{font:bold 24px 'Courier New',monospace;fill:#ff0040}
.cyn{font:bold 24px 'Courier New',monospace;fill:#00d4ff}
.amb{font:bold 24px 'Courier New',monospace;fill:#ffaa00}
.badge{stroke:#00ff41;rx:14}
</style>
<rect class="bg" width="1200" height="800"/>
<!-- Title -->
<text x="600" y="52" text-anchor="middle" class="title">Secure Boot &amp; Attack Vectors</text>
<text x="600" y="88" text-anchor="middle" class="dim">Why Boot Sequence Knowledge Matters for Security</text>
<!-- Left Panel: Attack Scenarios -->
<rect x="40" y="110" width="555" height="380" rx="8" class="pnl" stroke="#ff0040" stroke-width="2"/>
<text x="60" y="148" class="red">Attack Scenarios</text>
<rect x="60" y="168" width="515" height="60" rx="4" fill="#0a0a0f" stroke="#ff0040" stroke-width="1"/>
<text x="75" y="193" class="red">Firmware Replacement</text>
<text x="75" y="218" class="dim">Replace flash with malicious code</text>
<rect x="60" y="238" width="515" height="60" rx="4" fill="#0a0a0f" stroke="#ff0040" stroke-width="1"/>
<text x="75" y="263" class="red">Vector Table Hijack</text>
<text x="75" y="288" class="dim">Modify reset handler address</text>
<rect x="60" y="308" width="515" height="60" rx="4" fill="#0a0a0f" stroke="#ff0040" stroke-width="1"/>
<text x="75" y="333" class="red">Debug Port Attack</text>
<text x="75" y="358" class="dim">SWD/JTAG to dump or inject code</text>
<rect x="60" y="378" width="515" height="60" rx="4" fill="#0a0a0f" stroke="#ff0040" stroke-width="1"/>
<text x="75" y="403" class="red">Startup Code Modification</text>
<text x="75" y="428" class="dim">Change crt0 data copy / BSS init</text>
<text x="60" y="472" class="amb">Physical access = game over</text>
<!-- Right Panel: Defense Strategies -->
<rect x="625" y="110" width="535" height="380" rx="8" class="pnl" stroke="#00ff41" stroke-width="2"/>
<text x="645" y="148" class="grn">Defense Strategies</text>
<rect x="645" y="168" width="495" height="50" rx="4" fill="#0a0a0f" stroke="#00ff41" stroke-width="1"/>
<text x="660" y="200" class="grn">1. Secure Boot</text>
<rect x="645" y="228" width="495" height="50" rx="4" fill="#0a0a0f" stroke="#00ff41" stroke-width="1"/>
<text x="660" y="260" class="grn">2. Debug Port Lock</text>
<rect x="645" y="288" width="495" height="50" rx="4" fill="#0a0a0f" stroke="#00ff41" stroke-width="1"/>
<text x="660" y="320" class="grn">3. Flash Read Protect</text>
<rect x="645" y="348" width="495" height="50" rx="4" fill="#0a0a0f" stroke="#00ff41" stroke-width="1"/>
<text x="660" y="380" class="grn">4. MPU Configuration</text>
<rect x="645" y="408" width="495" height="50" rx="4" fill="#0a0a0f" stroke="#00ff41" stroke-width="1"/>
<text x="660" y="440" class="grn">5. Integrity Checks</text>
<text x="645" y="478" class="amb">Defense in depth!</text>
<!-- Bottom Panel: Secure Boot Flow -->
<rect x="40" y="515" width="1120" height="255" rx="8" class="pnl"/>
<text x="60" y="553" class="sub">Secure Boot Chain</text>
<rect x="60" y="573" width="220" height="70" rx="6" fill="#0a0a0f" stroke="#00ff41" stroke-width="2"/>
<text x="170" y="603" text-anchor="middle" class="grn">Bootrom</text>
<text x="170" y="629" text-anchor="middle" class="dim">immutable</text>
<text x="300" y="613" text-anchor="middle" class="amb">-></text>
<rect x="320" y="573" width="220" height="70" rx="6" fill="#0a0a0f" stroke="#00d4ff" stroke-width="2"/>
<text x="430" y="603" text-anchor="middle" class="cyn">Verify Sig</text>
<text x="430" y="629" text-anchor="middle" class="dim">IMAGE_DEF</text>
<text x="560" y="613" text-anchor="middle" class="amb">-></text>
<rect x="580" y="573" width="220" height="70" rx="6" fill="#0a0a0f" stroke="#ffaa00" stroke-width="2"/>
<text x="690" y="603" text-anchor="middle" class="amb">Verify App</text>
<text x="690" y="629" text-anchor="middle" class="dim">signature</text>
<text x="820" y="613" text-anchor="middle" class="amb">-></text>
<rect x="840" y="573" width="280" height="70" rx="6" fill="#0a0a0f" stroke="#00ff41" stroke-width="2"/>
<text x="980" y="603" text-anchor="middle" class="grn">Boot!</text>
<text x="980" y="629" text-anchor="middle" class="dim">or refuse</text>
<text x="60" y="688" class="txt">Each stage cryptographically verifies</text>
<text x="60" y="718" class="txt">the next before handing off control.</text>
<text x="60" y="748" class="dim">Bootrom = trust anchor (can't be changed)</text>
</svg>
Binary file not shown.
Binary file not shown.
+275 -53
View File
@@ -130,8 +130,8 @@ Think of the bootrom like the BIOS in your computer - it's the first thing that
### What Does the Bootrom Do?
1. **Initialize Hardware**: Sets up clocks, resets peripherals
2. **Check Boot Sources**: Looks for valid firmware in flash
3. **Validate Firmware**: Checks for magic markers (IMAGE_DEF)
2. **Check Boot Sources (Discovery)**: Scans configured boot sources (for this course: flash) to find a candidate firmware image region.
3. **Validate Firmware (Validation)**: Verifies that candidate by finding IMAGE_DEF start/end markers and parsing the block.
4. **Configure Flash**: Sets up the XIP interface
5. **Jump to Your Code**: Reads the vector table and jumps to your reset handler
@@ -158,6 +158,54 @@ Here's what it looks like in the Pico SDK:
- `0xffffded3` = Start marker ("I'm a valid Pico binary!")
- `0xab123579` = End marker ("End of the header block")
### See This Exact Block in Your ELF (Commands + Real Output)
Use these commands to view the IMAGE_DEF bytes directly in the ELF:
```powershell
arm-none-eabi-objdump -s --start-address=0x1000013c --stop-address=0x10000150 build/0x0001_hello-world.elf
arm-none-eabi-objdump -s --start-address=0x10000130 --stop-address=0x10000154 build/0x0001_hello-world.elf
arm-none-eabi-gdb build/0x0001_hello-world.elf -ex "x/20bx 0x1000013c" -ex quit
```
Actual output from this lesson build:
```text
build/0x0001_hello-world.elf: file format elf32-littlearm
Contents of section .text:
1000013c 42012110 ff010000 b01b0000 793512ab B.!.........y5..
1000014c 4ff00000 O...
build/0x0001_hello-world.elf: file format elf32-littlearm
Contents of section .text:
10000130 a0010010 90a31ae7 d3deffff 42012110 ............B.!.
10000140 ff010000 b01b0000 793512ab 4ff00000 ........y5..O...
10000150 1e490860 .I.`
```
Command 1 explained (`--start-address=0x1000013c --stop-address=0x10000150`):
- Starts at `0x1000013c`, so it does **not** include the start marker at `0x10000138` (`d3deffff`).
- Shows IMAGE_DEF body fields and the end marker:
- `42012110` = `42 01 21 10` (item type/size + secure mode field)
- `ff010000` = last-item marker + size + pad
- `b01b0000` = next word in the block payload for this build
- `793512ab` = `PICOBIN_BLOCK_MARKER_END` (`0xab123579` in little-endian)
- `4ff00000` at `0x1000014c` is already the next instruction word after IMAGE_DEF.
Command 2 explained (`--start-address=0x10000130 --stop-address=0x10000154`):
- Starts earlier, so it captures context **and** both IMAGE_DEF markers.
- `a0010010 90a31ae7` = binary-info context before IMAGE_DEF.
- `d3deffff` at `0x10000138` = `PICOBIN_BLOCK_MARKER_START`.
- `793512ab` at `0x10000148` = `PICOBIN_BLOCK_MARKER_END`.
- `4ff00000 1e490860` = code words after the IMAGE_DEF block.
- This command proves the full block location for this build: `0x10000138` to `0x1000014b`.
Important: IMAGE_DEF offset can vary by build. In this build, the start marker `d3deffff`
is at `0x10000138` (not `0x1000013c`), so always search for the marker bytes instead of
assuming a fixed address.
> 📖 **Datasheet Reference:** Block markers are defined in Section 5.1.5.1 "Blocks" (p. 357): *"it must begin with the 4 byte magic header, PICOBIN_BLOCK_MARKER_START (0xffffded3)"* and *"it must end with the 4 byte magic footer, PICOBIN_BLOCK_MARKER_END (0xab123579)"*. The minimum Arm IMAGE_DEF is detailed in Section 5.9.5.1 (p. 429).
> ⚠️ **RP2350 vs RP2040 Key Difference:** Unlike the RP2040, the RP2350 does **not** require a checksummed "boot2" function at flash address 0. The RP2350 bootrom performs its own flash XIP setup. Instead, the RP2350 requires a valid IMAGE_DEF block **anywhere within the first 4 kB** of the image (Datasheet §5.9.5, p. 429: *"This must appear within the first 4 kB of a flash image"*; §5.2, p. 375: *"the main differences being the removal of a boot2 in the first 256 bytes of the image"*).
@@ -350,7 +398,7 @@ arm-none-eabi-gdb build\0x0001_hello-world.elf
**Connect to target:**
```gdb
(gdb) target remote :3333
(gdb) target extended-remote :3333
(gdb) monitor reset halt
```
@@ -383,7 +431,7 @@ Let's look at the first 4 entries of the vector table at `0x10000000`:
### Step 2: Understanding What We See
> 🔄 **REVIEW:** In Week 1, we saw `sp = 0x20081fc8` when stopped at `main`. That's *after* some stack was used during boot. Here we see the *initial* stack pointer before any code runs!
> 🔄 **REVIEW:** In Weeks 1-2, we saw both `sp = 0x20082000` at the clean breakpoint at `main` and lower values like `0x20081fc8` or `0x20081ff8` after additional stack activity. Here we are looking at the *initial* stack pointer from the vector table before any code runs.
Let's decode each value:
@@ -491,39 +539,39 @@ Let's look at more instructions to see the full picture:
(gdb) x/20i 0x1000015c
```
**You should see something like:**
**You should see:**
```
0x1000015c <_reset_handler>: mov.w r0, #3489660928 @ 0xd0000000
0x10000160 <_reset_handler+4>: ldr r0, [r0, #0]
0x10000162 <_reset_handler+6>:
cbz r0, 0x1000016a <hold_non_core0_in_bootrom+6>
0x10000164 <hold_non_core0_in_bootrom>: mov.w r0, #0
0x10000168 <hold_non_core0_in_bootrom+4>:
b.n 0x10000150 <_enter_vtable_in_r0>
0x1000016a <hold_non_core0_in_bootrom+6>:
add r4, pc, #52 @ (adr r4, 0x100001a0 <data_cpy_table>)
0x1000016c <hold_non_core0_in_bootrom+8>: ldmia r4!, {r1, r2, r3}
0x1000016e <hold_non_core0_in_bootrom+10>: cmp r1, #0
0x10000170 <hold_non_core0_in_bootrom+12>:
beq.n 0x10000178 <hold_non_core0_in_bootrom+20>
0x10000172 <hold_non_core0_in_bootrom+14>:
bl 0x1000019a <data_cpy>
0x10000176 <hold_non_core0_in_bootrom+18>:
b.n 0x1000016c <hold_non_core0_in_bootrom+8>
0x10000178 <hold_non_core0_in_bootrom+20>:
ldr r1, [pc, #84] @ (0x100001d0 <data_cpy_table+48>)
0x1000017a <hold_non_core0_in_bootrom+22>:
ldr r2, [pc, #88] @ (0x100001d4 <data_cpy_table+52>)
0x1000017c <hold_non_core0_in_bootrom+24>: movs r0, #0
0x1000017e <hold_non_core0_in_bootrom+26>:
b.n 0x10000182 <bss_fill_test>
0x10000180 <bss_fill_loop>: stmia r1!, {r0}
0x10000182 <bss_fill_test>: cmp r1, r2
0x10000184 <bss_fill_test+2>: bne.n 0x10000180 <bss_fill_loop>
0x10000186 <platform_entry>:
ldr r1, [pc, #80] @ (0x100001d8 <data_cpy_table+56>)
0x10000188 <platform_entry+2>: blx r1
0x1000015c <_reset_handler>: mov.w r0, #3489660928 @ 0xd0000000
0x10000160 <_reset_handler+4>: ldr r0, [r0, #0]
0x10000162 <_reset_handler+6>:
cbz r0, 0x1000016a <hold_non_core0_in_bootrom+6>
0x10000164 <hold_non_core0_in_bootrom>: mov.w r0, #0
0x10000168 <hold_non_core0_in_bootrom+4>:
b.n 0x10000150 <_enter_vtable_in_r0>
0x1000016a <hold_non_core0_in_bootrom+6>:
add r4, pc, #52 @ (adr r4, 0x100001a0 <data_cpy_table>)
0x1000016c <hold_non_core0_in_bootrom+8>: ldmia r4!, {r1, r2, r3}
0x1000016e <hold_non_core0_in_bootrom+10>: cmp r1, #0
0x10000170 <hold_non_core0_in_bootrom+12>:
beq.n 0x10000178 <hold_non_core0_in_bootrom+20>
0x10000172 <hold_non_core0_in_bootrom+14>:
bl 0x1000019a <data_cpy>
0x10000176 <hold_non_core0_in_bootrom+18>:
b.n 0x1000016c <hold_non_core0_in_bootrom+8>
0x10000178 <hold_non_core0_in_bootrom+20>:
ldr r1, [pc, #84] @ (0x100001d0 <data_cpy_table+48>)
0x1000017a <hold_non_core0_in_bootrom+22>:
ldr r2, [pc, #88] @ (0x100001d4 <data_cpy_table+52>)
0x1000017c <hold_non_core0_in_bootrom+24>: movs r0, #0
0x1000017e <hold_non_core0_in_bootrom+26>:
b.n 0x10000182 <bss_fill_test>
0x10000180 <bss_fill_loop>: stmia r1!, {r0}
0x10000182 <bss_fill_test>: cmp r1, r2
0x10000184 <bss_fill_test+2>: bne.n 0x10000180 <bss_fill_loop>
0x10000186 <platform_entry>:
ldr r1, [pc, #80] @ (0x100001d8 <data_cpy_table+56>)
0x10000188 <platform_entry+2>: blx r1
```
> 💡 **About GDB Label Offsets:** You may notice GDB shows instructions like `<hold_non_core0_in_bootrom+8>` for code that is clearly part of the data copy loop, not the core-parking function. This is **not** a GDB bug or "symbol snapping" — `hold_non_core0_in_bootrom` is a **real label** defined in the SDK's `crt0.S` (line 454). The `+8` offset simply means "8 bytes past that label." GDB always displays addresses relative to the nearest preceding symbol. The data copy code falls through from the `cbz` branch at the core check, landing right after the `hold_non_core0_in_bootrom` label, hence the offset.
@@ -540,22 +588,23 @@ The reset handler performs several phases:
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ PHASE 2: Data Copy (0x1000016a - 0x10000176)
│ PHASE 2: Data Copy Setup & Loop (0x1000016a - 0x10000176) │
│ - Set up the data_cpy_table pointer and load each copy triplet │
│ - Copy initialized variables from flash to RAM │
│ - Uses data_cpy_table for source/destination info │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ PHASE 3: BSS Clear (0x10000178 - 0x10000184)
│ PHASE 3: BSS Setup & Clear (0x10000178 - 0x10000184) │
│ - Load the BSS start/end addresses into r1 and r2 │
│ - GDB labels those literals as `data_cpy_table+48/+52` │
│ - Zero out all uninitialized global variables │
│ - C standard requires BSS to start at zero │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ PHASE 4: Runtime Init & Main (0x10000186+)
│ - Call runtime_init() for SDK setup
│ - Call __libc_init_array() for C++ constructors
│ - Finally call main()!
│ PHASE 4: Platform Entry Begins (0x10000186 - 0x10000188 shown)
│ - Load the runtime_init() pointer from the table
│ - Branch to runtime_init() with `blx r1`
│ - `main()` and `exit()` appear a few instructions later
└─────────────────────────────────────────────────────────────────┘
```
@@ -668,6 +717,8 @@ b.n 0x10000182 <bss_fill_test>
0x10000180 <bss_fill_loop>: stmia r1!, {r0}
```
The first two `ldr` instructions are still part of the **BSS clear setup**, even though GDB shows the source words as `data_cpy_table+48` and `data_cpy_table+52`. That label means the two literal words live in the same nearby constant block as the copy-table entries; it does **not** mean the code is still performing `.data` copies. At this point, `r1` becomes the BSS start address, `r2` becomes the BSS end address, and the loop beginning at `0x10000180` zeros that range.
### Understanding the Loop
```
@@ -1018,7 +1069,7 @@ Ghidra can visualize the call flow:
1. With `_reset_handler` selected, go to **Window → Function Call Graph**
2. This shows a visual graph of all function calls from the reset handler
3. You can see the path: `_reset_handler` `platform_entry``main`
3. You will see `_reset_handler` at the top with arrows going down to its four direct callees: `data_cpy`, `runtime_init`, `main`, and `exit`
### Comparing GDB and Ghidra for Boot Analysis
@@ -1156,21 +1207,18 @@ Ghidra can visualize the call flow:
- Is it a valid code address (starts with `0x1000...`)?
- What handler does it point to?
### Exercise 4: Find Your Main Function
### Exercise 4: Find Your Main Function and Trace Back
1. Use `info functions main` to find main
2. Examine 10 instructions at that address
3. Identify the first function call in main
4. What does that function do?
5. When stopped at main, examine `$lr` (link register)
6. What address is stored there?
7. Disassemble that address - what function is it?
8. This shows you where main was called from!
### Exercise 5: Trace Back from Main
1. When stopped at main, examine `$lr` (link register)
2. What address is stored there?
3. Disassemble that address - what function is it?
4. This shows you where main was called from!
### Exercise 6: Ghidra Boot Analysis
### Exercise 5: Ghidra Boot Analysis
1. In Ghidra, navigate to `_reset_handler`
2. Use **Window → Function Call Graph** to visualize the call tree
@@ -1398,6 +1446,180 @@ https://github.com/raspberrypi/pico-bootrom-rp2350
---
## 🔬 Part 17: Proving the Boot Sequence with objdump
Everything we have learned about the boot sequence can be proven directly from the compiled ELF binary using `arm-none-eabi-objdump`. The bootrom is not in your ELF (it is mask ROM burned into the chip at `0x00000000`), but everything your firmware provides — the vector table, the IMAGE_DEF, and the reset handler — lives in your ELF starting at `0x10000000`.
### Step 1: List All Sections
```bash
arm-none-eabi-objdump -h build/0x0001_hello-world.elf
```
Expected output (key sections):
```
Idx Name Size VMA LMA
0 .text 000019cc 10000000 10000000
3 .binary_info 0000002c 10001b20 10001b20
4 .ram_vector_table 00000110 20000000 20000000
6 .data 0000019c 20000110 10001b4c
```
> 💡 The Pico SDK merges `.vectors`, `.embedded_block`, and `.reset` all into `.text` at `0x10000000`. They are not separate named ELF sections — they are sub-regions inside `.text`.
### Step 2: Dump the First 0x150 Bytes of Flash — One Command, Zero Skips
```bash
arm-none-eabi-objdump -s --start-address=0x10000000 --stop-address=0x10000150 build/0x0001_hello-world.elf
```
Raw output from that command:
```
10000000 00200820 5d010010 1b010010 1d010010 . . ]...........
10000010 11010010 11010010 11010010 11010010 ................
10000020 11010010 11010010 11010010 11010010 ................
10000030 11010010 11010010 11010010 11010010 ................
10000040 11010010 11010010 11010010 11010010 ................
10000050 11010010 11010010 11010010 11010010 ................
10000060 11010010 11010010 11010010 11010010 ................
10000070 11010010 11010010 11010010 11010010 ................
10000080 11010010 11010010 11010010 11010010 ................
10000090 11010010 11010010 11010010 11010010 ................
100000a0 11010010 11010010 11010010 11010010 ................
100000b0 11010010 11010010 11010010 11010010 ................
100000c0 11010010 11010010 11010010 11010010 ................
100000d0 11010010 11010010 11010010 11010010 ................
100000e0 11010010 11010010 11010010 11010010 ................
100000f0 11010010 11010010 11010010 11010010 ................
10000100 11010010 11010010 11010010 11010010 ................
10000110 eff30580 103800be 00be00be 00be00be .....8..........
10000120 00be00be f2eb8871 201b0010 4c1b0010 .......q ...L...
10000130 a0010010 90a31ae7 d3deffff 42012110 ............B.!.
10000140 ff010000 b01b0000 793512ab ........y5..
```
Every address annotated, no skips:
#### 0x10000000 — Vector Table, Mandatory Entries
| Address | Raw Bytes (LE) | Decoded | What it is |
|---------|----------------|---------|------------|
| `0x10000000` | `00 20 08 20` | `0x20082000` | **Initial SP** — top of SCRATCH_Y RAM. Bootrom loads MSP from here before doing anything else. |
| `0x10000004` | `5d 01 00 10` | `0x1000015d` | **Reset_Handler** address with Thumb bit set. Strip bit 0 → real address `0x1000015c`. Bootrom jumps here. |
| `0x10000008` | `1b 01 00 10` | `0x1000011b` | **NMI** handler address (Thumb, → `0x1000011a`). |
| `0x1000000c` | `1d 01 00 10` | `0x1000011d` | **HardFault** handler address (Thumb, → `0x1000011c`). |
#### 0x100000100x1000010f — Vector Table, IRQ Slots (all 52 external IRQs)
```
10000010 11010010 11010010 ...(repeats through 0x1000010f)...
```
Every 4-byte word here is `11 01 00 10` = pointer `0x10000111`.
That is the **default IRQ handler** address with Thumb bit set (→ `0x10000110`).
The RP2350 Cortex-M33 has 16 system vectors (offsets 0x000x3f) plus up to 52
external IRQ vectors (offsets 0x400xff = addresses `0x10000040``0x1000010f`).
Every IRQ the application does not register gets this default handler pointer.
This block is 240 bytes (`0x10000010` to `0x1000010f`) of nothing but that one
repeated pointer.
#### 0x100001100x10000127 — Default IRQ Handler Code
```
10000110 eff30580 103800be 00be00be 00be00be
10000120 00be00be f2eb8871
```
| Address | Bytes | ARM Thumb-2 Instruction | What it does |
|---------|-------|-------------------------|--------------|
| `0x10000110` | `ef f3 05 80` | `MRS r0, IPSR` | Read the Interrupt Program Status Register into r0. The low 9 bits = the active vector number. |
| `0x10000114` | `10 38` | `SUBS r0, #16` | Vector 16 = IRQ0, so subtract 16 to convert vector number → IRQ index. |
| `0x10000116` | `00 be` | `BKPT #0` | Software breakpoint. If a debugger is attached, it stops here and you can inspect r0 to see which IRQ fired. If no debugger is attached, the CPU enters a fault loop and the chip hangs. |
| `0x10000118``0x10000127` | `00 be` ×12 | `BKPT #0` repeating | Alignment padding to the next 4-byte boundary. |
This is the **entire** default IRQ handler. It is intentionally minimal: if your
code triggers an IRQ you did not register, it crashes visibly instead of silently.
#### 0x100001280x1000013b — Binary Info Pointer Table
```
10000120 201b0010 4c1b0010
10000130 a0010010 90a31ae7
```
| Address | Bytes (LE) | Decoded Value | What it is |
|---------|------------|---------------|------------|
| `0x10000128` | `20 1b 00 10` | `0x10001b20` | Pointer to **start** of `.binary_info` data section in flash. |
| `0x1000012c` | `4c 1b 00 10` | `0x10001b4c` | Pointer to **end** of `.binary_info` data section in flash. |
| `0x10000130` | `a0 01 00 10` | `0x100001a0` | Pointer to `binary_info_callback` function. |
| `0x10000134` | `90 a3 1a e7` | (magic marker) | `BINARY_INFO_MARKER_END` — marks the end of this pointer table. |
`picotool` reads this table to extract the program name, version string, URL,
and GPIO pin map from any compiled binary without running it.
#### 0x100001380x1000014c — IMAGE_DEF Block (this build)
```
10000130 a0010010 90a31ae7 d3deffff 42012110
10000140 ff010000 b01b0000 793512ab 4ff00000
```
| Address | Bytes | What it is |
|---------|-------|------------|
| `0x10000138` | `d3 de ff ff` | `PICOBIN_BLOCK_MARKER_START` — the bootrom scans flash for this exact 4-byte sequence to locate the IMAGE_DEF. |
| `0x1000013c` | `42 01 21 10` | IMAGE_DEF content (image type, flags, version). |
| `0x10000140` | `ff 01 00 00` | IMAGE_DEF content (continuation). |
| `0x10000144` | `b0 1b 00 00` | IMAGE_DEF content (continuation). |
| `0x10000148` | `79 35 12 ab` | `PICOBIN_BLOCK_MARKER_END` — bootrom stops scanning here. |
The IMAGE_DEF sits at `0x10000138``0x1000014b` in this build,
well within the 4 KB scan window the bootrom uses (Datasheet §5.9.5, p. 429).
#### Full Flash Map: 0x100000000x1000015c
```
0x100000000x1000000f Vector Table: mandatory entries (SP, Reset, NMI, HardFault)
0x100000100x1000010f Vector Table: 52 external IRQ slots → all point to default handler
0x100001100x10000127 Default IRQ handler code (MRS / SUBS / BKPT)
0x100001280x10000137 Binary info pointer table (start / end / callback / magic end)
0x100001380x1000014b IMAGE_DEF block (d3 de ff ff ... 79 35 12 ab)
0x100001500x1000015b (padding / alignment)
0x1000015c Reset_Handler (_reset_handler in crt0.S) ← bootrom jumps here
```
### Step 4: Confirmed Boot Sequence (proven from ELF)
```
┌─────────────────────────────────────────────────────────────────┐
│ PROVEN BOOT SEQUENCE (0x0001_hello-world) │
├─────────────────────────────────────────────────────────────────┤
│ 1. Bootrom reads 0x10000000 │
│ → SP = 0x20082000 (offset +0x00 of vector table) │
│ → RST = 0x1000015d (offset +0x04, Thumb → 0x1000015c) │
├─────────────────────────────────────────────────────────────────┤
│ 2. Bootrom scans first 4 kB for IMAGE_DEF │
│ → Found at 0x10000138 (this build) │
│ → Start marker: d3 de ff ff │
│ → End marker: 79 35 12 ab │
├─────────────────────────────────────────────────────────────────┤
│ 3. Bootrom jumps to reset handler at 0x1000015c │
│ → _reset_handler (crt0.S) runs │
│ → Checks CPUID — Core 1 sent back to bootrom │
│ → Core 0: .data copied, .bss zeroed, platform_entry called │
├─────────────────────────────────────────────────────────────────┤
│ 4. platform_entry calls runtime_init → main → exit │
└─────────────────────────────────────────────────────────────────┘
```
> 📖 **Datasheet References:**
> - §5.1.5.1 (p. 357): Block markers `0xffffded3` (start) and `0xab123579` (end)
> - §5.9.5 (p. 429): IMAGE_DEF must appear within first 4 kB of flash image
> - §5.9.5.1 (p. 429): Bootrom enters via reset handler at vector table offset +4
---
**Remember:** Understanding the boot process is fundamental to embedded systems work. Whether you're debugging a system that won't start, reverse engineering firmware, or building secure boot chains, this knowledge is essential!
Happy exploring! 🔍
+6 -6
View File
@@ -24,7 +24,7 @@
<text x="60" y="167" class="dim">Cortex-M33 wakes, execution at 0x00000000 (Bootrom)</text>
<!-- Arrow -->
<text x="600" y="198" text-anchor="middle" class="grn"></text>
<text x="600" y="200" text-anchor="middle" class="grn"></text>
<!-- Step 2 -->
<rect x="40" y="208" width="1120" height="70" rx="6" fill="#12121a" stroke="#ffaa00" stroke-width="2"/>
@@ -33,7 +33,7 @@
<text x="60" y="265" class="dim">32KB on-chip ROM — finds IMAGE_DEF at 0x10000000</text>
<!-- Arrow -->
<text x="600" y="296" text-anchor="middle" class="grn"></text>
<text x="600" y="298" text-anchor="middle" class="grn"></text>
<!-- Step 3 -->
<rect x="40" y="306" width="1120" height="70" rx="6" fill="#12121a" stroke="#ffaa00" stroke-width="2"/>
@@ -42,7 +42,7 @@
<text x="60" y="363" class="dim">Bootrom configures flash interface &amp; XIP (no boot2 on RP2350)</text>
<!-- Arrow -->
<text x="600" y="394" text-anchor="middle" class="grn"></text>
<text x="600" y="396" text-anchor="middle" class="grn"></text>
<!-- Step 4 -->
<rect x="40" y="404" width="1120" height="90" rx="6" fill="#12121a" stroke="#ffaa00" stroke-width="2"/>
@@ -58,9 +58,9 @@
<rect x="40" y="524" width="1120" height="110" rx="6" fill="#12121a" stroke="#ffaa00" stroke-width="2"/>
<text x="60" y="551" class="amb">STEP 5</text>
<text x="220" y="551" class="txt">C Runtime Startup (crt0.S)</text>
<text x="60" y="583" class="dim">Copy .data from flash -> RAM</text>
<text x="60" y="608" class="dim">Zero .bss section</text>
<text x="60" y="633" class="dim">Call runtime_init() -> main()</text>
<text x="60" y="579" class="dim">Copy .data from flash -> RAM</text>
<text x="60" y="603" class="dim">Zero .bss section</text>
<text x="60" y="627" class="dim">Call runtime_init() -> main()</text>
<!-- Bottom summary -->
<rect x="40" y="660" width="1120" height="110" rx="6" fill="#12121a" stroke="#ffaa00" stroke-width="2"/>
+1 -1
View File
@@ -76,5 +76,5 @@
<text x="640" y="682" class="txt">PendSV, SysTick all use:</text>
<rect x="660" y="700" width="480" height="42" rx="4" fill="#0a0a0f" stroke="#ff0040" stroke-width="1"/>
<text x="680" y="728" class="red">bkpt 0x0000</text>
<text x="880" y="728" class="dim"><- stops debugger</text>
<text x="880" y="728" class="dim">&lt;- stops debugger</text>
</svg>
+3 -3
View File
@@ -60,19 +60,19 @@
<text x="170" y="543" text-anchor="middle" class="amb">Core Check</text>
<text x="170" y="569" text-anchor="middle" class="dim">CPUID == 0?</text>
<text x="300" y="553" class="grn">-></text>
<text x="303" y="553" text-anchor="middle" class="grn">-></text>
<rect x="325" y="513" width="200" height="70" rx="6" fill="#0a0a0f" stroke="#00d4ff" stroke-width="2"/>
<text x="425" y="543" text-anchor="middle" class="cyn">Data Copy</text>
<text x="425" y="569" text-anchor="middle" class="dim">flash -> RAM</text>
<text x="545" y="553" class="grn">-></text>
<text x="548" y="553" text-anchor="middle" class="grn">-></text>
<rect x="570" y="513" width="200" height="70" rx="6" fill="#0a0a0f" stroke="#00ff41" stroke-width="2"/>
<text x="670" y="543" text-anchor="middle" class="grn">BSS Clear</text>
<text x="670" y="569" text-anchor="middle" class="dim">zero globals</text>
<text x="790" y="553" class="grn">-></text>
<text x="793" y="553" text-anchor="middle" class="grn">-></text>
<rect x="815" y="513" width="305" height="70" rx="6" fill="#0a0a0f" stroke="#ff0040" stroke-width="2"/>
<text x="967" y="543" text-anchor="middle" class="red">Platform Entry</text>
+3 -3
View File
@@ -49,13 +49,13 @@
<text x="210" y="478" text-anchor="middle" class="amb">runtime_init()</text>
<text x="210" y="508" text-anchor="middle" class="dim">SDK setup</text>
<text x="385" y="488" class="grn">-></text>
<text x="390" y="488" text-anchor="middle" class="grn">-></text>
<rect x="420" y="443" width="300" height="80" rx="6" fill="#0a0a0f" stroke="#00ff41" stroke-width="2"/>
<text x="570" y="478" text-anchor="middle" class="grn">main()</text>
<text x="570" y="508" text-anchor="middle" class="dim">YOUR CODE</text>
<text x="745" y="488" class="grn">-></text>
<text x="750" y="488" text-anchor="middle" class="grn">-></text>
<rect x="780" y="443" width="300" height="80" rx="6" fill="#0a0a0f" stroke="#ff0040" stroke-width="2"/>
<text x="930" y="478" text-anchor="middle" class="red">exit()</text>
@@ -76,7 +76,7 @@
<text x="640" y="677" class="txt">Then:</text>
<rect x="660" y="700" width="480" height="42" rx="4" fill="#0a0a0f" stroke="#ff0040" stroke-width="1"/>
<text x="680" y="728" class="red">bkpt 0x0000</text>
<text x="900" y="728" class="dim"><- infinite halt</text>
<text x="900" y="728" class="dim">&lt;- infinite halt</text>
<text x="640" y="760" class="dim">Should never be reached!</text>
</svg>
+3 -3
View File
@@ -68,19 +68,19 @@
<text x="170" y="603" text-anchor="middle" class="grn">Bootrom</text>
<text x="170" y="629" text-anchor="middle" class="dim">immutable</text>
<text x="298" y="613" class="amb">-></text>
<text x="300" y="613" text-anchor="middle" class="amb">-></text>
<rect x="320" y="573" width="220" height="70" rx="6" fill="#0a0a0f" stroke="#00d4ff" stroke-width="2"/>
<text x="430" y="603" text-anchor="middle" class="cyn">Verify Sig</text>
<text x="430" y="629" text-anchor="middle" class="dim">IMAGE_DEF</text>
<text x="558" y="613" class="amb">-></text>
<text x="560" y="613" text-anchor="middle" class="amb">-></text>
<rect x="580" y="573" width="220" height="70" rx="6" fill="#0a0a0f" stroke="#ffaa00" stroke-width="2"/>
<text x="690" y="603" text-anchor="middle" class="amb">Verify App</text>
<text x="690" y="629" text-anchor="middle" class="dim">signature</text>
<text x="818" y="613" class="amb">-></text>
<text x="820" y="613" text-anchor="middle" class="amb">-></text>
<rect x="840" y="573" width="280" height="70" rx="6" fill="#0a0a0f" stroke="#00ff41" stroke-width="2"/>
<text x="980" y="603" text-anchor="middle" class="grn">Boot!</text>
@@ -38,10 +38,38 @@
extern int main(void);
extern uint32_t __data_lma;
extern uint32_t __data_start;
extern uint32_t __data_end;
extern uint32_t __bss_start;
extern uint32_t __bss_end;
static void _data_copy_init(void)
{
uint32_t *src = &__data_lma;
uint32_t *dst = &__data_start;
while (dst < &__data_end)
*dst++ = *src++;
}
static void _bss_zero_init(void)
{
uint32_t *dst = &__bss_start;
while (dst < &__bss_end)
*dst++ = 0U;
}
void _ram_init(void)
{
stack_init();
_data_copy_init();
_bss_zero_init();
}
void __attribute__((naked, noreturn)) Reset_Handler(void)
{
__asm__ volatile (
"bl stack_init\n\t"
"bl _ram_init\n\t"
"bl xosc_init\n\t"
"bl xosc_enable_peri_clk\n\t"
"bl reset_init_subsystem\n\t"
Binary file not shown.
+30
View File
@@ -50,6 +50,7 @@ MEMORY
PHDRS
{
text PT_LOAD FLAGS(5);
data PT_LOAD FLAGS(6);
}
/**
@@ -94,6 +95,35 @@ SECTIONS
KEEP(*(.embedded_block))
} > FLASH :text
/**
* Initialized data and RAM-resident code (LMA in flash, VMA in RAM).
* Startup copies from __data_lma to __data_start..__data_end.
*/
.data :
{
. = ALIGN(4);
__data_start = .;
*(.ram_func*)
*(.data*)
. = ALIGN(4);
__data_end = .;
} > RAM AT> FLASH :data
__data_lma = LOADADDR(.data);
/**
* Uninitialized data (BSS) in RAM.
*/
.bss (NOLOAD) :
{
. = ALIGN(4);
__bss_start = .;
*(.bss*)
*(COMMON)
. = ALIGN(4);
__bss_end = .;
} > RAM
/**
* Non-secure stack symbols.
*/
@@ -38,10 +38,38 @@
extern int main(void);
extern uint32_t __data_lma;
extern uint32_t __data_start;
extern uint32_t __data_end;
extern uint32_t __bss_start;
extern uint32_t __bss_end;
static void _data_copy_init(void)
{
uint32_t *src = &__data_lma;
uint32_t *dst = &__data_start;
while (dst < &__data_end)
*dst++ = *src++;
}
static void _bss_zero_init(void)
{
uint32_t *dst = &__bss_start;
while (dst < &__bss_end)
*dst++ = 0U;
}
void _ram_init(void)
{
stack_init();
_data_copy_init();
_bss_zero_init();
}
void __attribute__((naked, noreturn)) Reset_Handler(void)
{
__asm__ volatile (
"bl stack_init\n\t"
"bl _ram_init\n\t"
"bl xosc_init\n\t"
"bl xosc_enable_peri_clk\n\t"
"bl reset_init_subsystem\n\t"
Binary file not shown.
+30
View File
@@ -50,6 +50,7 @@ MEMORY
PHDRS
{
text PT_LOAD FLAGS(5);
data PT_LOAD FLAGS(6);
}
/**
@@ -94,6 +95,35 @@ SECTIONS
KEEP(*(.embedded_block))
} > FLASH :text
/**
* Initialized data and RAM-resident code (LMA in flash, VMA in RAM).
* Startup copies from __data_lma to __data_start..__data_end.
*/
.data :
{
. = ALIGN(4);
__data_start = .;
*(.ram_func*)
*(.data*)
. = ALIGN(4);
__data_end = .;
} > RAM AT> FLASH :data
__data_lma = LOADADDR(.data);
/**
* Uninitialized data (BSS) in RAM.
*/
.bss (NOLOAD) :
{
. = ALIGN(4);
__bss_start = .;
*(.bss*)
*(COMMON)
. = ALIGN(4);
__bss_end = .;
} > RAM
/**
* Non-secure stack symbols.
*/
@@ -38,10 +38,38 @@
extern int main(void);
extern uint32_t __data_lma;
extern uint32_t __data_start;
extern uint32_t __data_end;
extern uint32_t __bss_start;
extern uint32_t __bss_end;
static void _data_copy_init(void)
{
uint32_t *src = &__data_lma;
uint32_t *dst = &__data_start;
while (dst < &__data_end)
*dst++ = *src++;
}
static void _bss_zero_init(void)
{
uint32_t *dst = &__bss_start;
while (dst < &__bss_end)
*dst++ = 0U;
}
void _ram_init(void)
{
stack_init();
_data_copy_init();
_bss_zero_init();
}
void __attribute__((naked, noreturn)) Reset_Handler(void)
{
__asm__ volatile (
"bl stack_init\n\t"
"bl _ram_init\n\t"
"bl xosc_init\n\t"
"bl xosc_enable_peri_clk\n\t"
"bl reset_init_subsystem\n\t"
Binary file not shown.
+30
View File
@@ -50,6 +50,7 @@ MEMORY
PHDRS
{
text PT_LOAD FLAGS(5);
data PT_LOAD FLAGS(6);
}
/**
@@ -94,6 +95,35 @@ SECTIONS
KEEP(*(.embedded_block))
} > FLASH :text
/**
* Initialized data and RAM-resident code (LMA in flash, VMA in RAM).
* Startup copies from __data_lma to __data_start..__data_end.
*/
.data :
{
. = ALIGN(4);
__data_start = .;
*(.ram_func*)
*(.data*)
. = ALIGN(4);
__data_end = .;
} > RAM AT> FLASH :data
__data_lma = LOADADDR(.data);
/**
* Uninitialized data (BSS) in RAM.
*/
.bss (NOLOAD) :
{
. = ALIGN(4);
__bss_start = .;
*(.bss*)
*(COMMON)
. = ALIGN(4);
__bss_end = .;
} > RAM
/**
* Non-secure stack symbols.
*/
@@ -39,6 +39,34 @@
extern int main(void);
extern uint32_t __data_lma;
extern uint32_t __data_start;
extern uint32_t __data_end;
extern uint32_t __bss_start;
extern uint32_t __bss_end;
static void _data_copy_init(void)
{
uint32_t *src = &__data_lma;
uint32_t *dst = &__data_start;
while (dst < &__data_end)
*dst++ = *src++;
}
static void _bss_zero_init(void)
{
uint32_t *dst = &__bss_start;
while (dst < &__bss_end)
*dst++ = 0U;
}
void _ram_init(void)
{
stack_init();
_data_copy_init();
_bss_zero_init();
}
void _late_init(void)
{
pwm_release_reset();
@@ -48,7 +76,7 @@ void _late_init(void)
void __attribute__((naked, noreturn)) Reset_Handler(void)
{
__asm__ volatile (
"bl stack_init\n\t"
"bl _ram_init\n\t"
"bl xosc_init\n\t"
"bl xosc_enable_peri_clk\n\t"
"bl reset_init_subsystem\n\t"
Binary file not shown.
+30
View File
@@ -50,6 +50,7 @@ MEMORY
PHDRS
{
text PT_LOAD FLAGS(5);
data PT_LOAD FLAGS(6);
}
/**
@@ -94,6 +95,35 @@ SECTIONS
KEEP(*(.embedded_block))
} > FLASH :text
/**
* Initialized data and RAM-resident code (LMA in flash, VMA in RAM).
* Startup copies from __data_lma to __data_start..__data_end.
*/
.data :
{
. = ALIGN(4);
__data_start = .;
*(.ram_func*)
*(.data*)
. = ALIGN(4);
__data_end = .;
} > RAM AT> FLASH :data
__data_lma = LOADADDR(.data);
/**
* Uninitialized data (BSS) in RAM.
*/
.bss (NOLOAD) :
{
. = ALIGN(4);
__bss_start = .;
*(.bss*)
*(COMMON)
. = ALIGN(4);
__bss_end = .;
} > RAM
/**
* Non-secure stack symbols.
*/
@@ -39,6 +39,34 @@
extern int main(void);
extern uint32_t __data_lma;
extern uint32_t __data_start;
extern uint32_t __data_end;
extern uint32_t __bss_start;
extern uint32_t __bss_end;
static void _data_copy_init(void)
{
uint32_t *src = &__data_lma;
uint32_t *dst = &__data_start;
while (dst < &__data_end)
*dst++ = *src++;
}
static void _bss_zero_init(void)
{
uint32_t *dst = &__bss_start;
while (dst < &__bss_end)
*dst++ = 0U;
}
void _ram_init(void)
{
stack_init();
_data_copy_init();
_bss_zero_init();
}
void _late_init(void)
{
servo_release_reset();
@@ -48,7 +76,7 @@ void _late_init(void)
void __attribute__((naked, noreturn)) Reset_Handler(void)
{
__asm__ volatile (
"bl stack_init\n\t"
"bl _ram_init\n\t"
"bl xosc_init\n\t"
"bl xosc_enable_peri_clk\n\t"
"bl reset_init_subsystem\n\t"
Binary file not shown.
+30
View File
@@ -50,6 +50,7 @@ MEMORY
PHDRS
{
text PT_LOAD FLAGS(5);
data PT_LOAD FLAGS(6);
}
/**
@@ -94,6 +95,35 @@ SECTIONS
KEEP(*(.embedded_block))
} > FLASH :text
/**
* Initialized data and RAM-resident code (LMA in flash, VMA in RAM).
* Startup copies from __data_lma to __data_start..__data_end.
*/
.data :
{
. = ALIGN(4);
__data_start = .;
*(.ram_func*)
*(.data*)
. = ALIGN(4);
__data_end = .;
} > RAM AT> FLASH :data
__data_lma = LOADADDR(.data);
/**
* Uninitialized data (BSS) in RAM.
*/
.bss (NOLOAD) :
{
. = ALIGN(4);
__bss_start = .;
*(.bss*)
*(COMMON)
. = ALIGN(4);
__bss_end = .;
} > RAM
/**
* Non-secure stack symbols.
*/
@@ -39,10 +39,38 @@
extern int main(void);
extern uint32_t __data_lma;
extern uint32_t __data_start;
extern uint32_t __data_end;
extern uint32_t __bss_start;
extern uint32_t __bss_end;
static void _data_copy_init(void)
{
uint32_t *src = &__data_lma;
uint32_t *dst = &__data_start;
while (dst < &__data_end)
*dst++ = *src++;
}
static void _bss_zero_init(void)
{
uint32_t *dst = &__bss_start;
while (dst < &__bss_end)
*dst++ = 0U;
}
void _ram_init(void)
{
stack_init();
_data_copy_init();
_bss_zero_init();
}
void __attribute__((naked, noreturn)) Reset_Handler(void)
{
__asm__ volatile (
"bl stack_init\n\t"
"bl _ram_init\n\t"
"bl xosc_init\n\t"
"bl xosc_enable_peri_clk\n\t"
"bl reset_init_subsystem\n\t"
Binary file not shown.
+30
View File
@@ -50,6 +50,7 @@ MEMORY
PHDRS
{
text PT_LOAD FLAGS(5);
data PT_LOAD FLAGS(6);
}
/**
@@ -94,6 +95,35 @@ SECTIONS
KEEP(*(.embedded_block))
} > FLASH :text
/**
* Initialized data and RAM-resident code (LMA in flash, VMA in RAM).
* Startup copies from __data_lma to __data_start..__data_end.
*/
.data :
{
. = ALIGN(4);
__data_start = .;
*(.ram_func*)
*(.data*)
. = ALIGN(4);
__data_end = .;
} > RAM AT> FLASH :data
__data_lma = LOADADDR(.data);
/**
* Uninitialized data (BSS) in RAM.
*/
.bss (NOLOAD) :
{
. = ALIGN(4);
__bss_start = .;
*(.bss*)
*(COMMON)
. = ALIGN(4);
__bss_end = .;
} > RAM
/**
* Non-secure stack symbols.
*/
@@ -38,10 +38,38 @@
extern int main(void);
extern uint32_t __data_lma;
extern uint32_t __data_start;
extern uint32_t __data_end;
extern uint32_t __bss_start;
extern uint32_t __bss_end;
static void _data_copy_init(void)
{
uint32_t *src = &__data_lma;
uint32_t *dst = &__data_start;
while (dst < &__data_end)
*dst++ = *src++;
}
static void _bss_zero_init(void)
{
uint32_t *dst = &__bss_start;
while (dst < &__bss_end)
*dst++ = 0U;
}
void _ram_init(void)
{
stack_init();
_data_copy_init();
_bss_zero_init();
}
void __attribute__((naked, noreturn)) Reset_Handler(void)
{
__asm__ volatile (
"bl stack_init\n\t"
"bl _ram_init\n\t"
"bl xosc_init\n\t"
"bl xosc_enable_peri_clk\n\t"
"bl reset_init_subsystem\n\t"
Binary file not shown.
+30
View File
@@ -50,6 +50,7 @@ MEMORY
PHDRS
{
text PT_LOAD FLAGS(5);
data PT_LOAD FLAGS(6);
}
/**
@@ -94,6 +95,35 @@ SECTIONS
KEEP(*(.embedded_block))
} > FLASH :text
/**
* Initialized data and RAM-resident code (LMA in flash, VMA in RAM).
* Startup copies from __data_lma to __data_start..__data_end.
*/
.data :
{
. = ALIGN(4);
__data_start = .;
*(.ram_func*)
*(.data*)
. = ALIGN(4);
__data_end = .;
} > RAM AT> FLASH :data
__data_lma = LOADADDR(.data);
/**
* Uninitialized data (BSS) in RAM.
*/
.bss (NOLOAD) :
{
. = ALIGN(4);
__bss_start = .;
*(.bss*)
*(COMMON)
. = ALIGN(4);
__bss_end = .;
} > RAM
/**
* Non-secure stack symbols.
*/
@@ -38,10 +38,38 @@
extern int main(void);
extern uint32_t __data_lma;
extern uint32_t __data_start;
extern uint32_t __data_end;
extern uint32_t __bss_start;
extern uint32_t __bss_end;
static void _data_copy_init(void)
{
uint32_t *src = &__data_lma;
uint32_t *dst = &__data_start;
while (dst < &__data_end)
*dst++ = *src++;
}
static void _bss_zero_init(void)
{
uint32_t *dst = &__bss_start;
while (dst < &__bss_end)
*dst++ = 0U;
}
void _ram_init(void)
{
stack_init();
_data_copy_init();
_bss_zero_init();
}
void __attribute__((naked, noreturn)) Reset_Handler(void)
{
__asm__ volatile (
"bl stack_init\n\t"
"bl _ram_init\n\t"
"bl xosc_init\n\t"
"bl xosc_enable_peri_clk\n\t"
"bl reset_init_subsystem\n\t"
Binary file not shown.
+30
View File
@@ -50,6 +50,7 @@ MEMORY
PHDRS
{
text PT_LOAD FLAGS(5);
data PT_LOAD FLAGS(6);
}
/**
@@ -94,6 +95,35 @@ SECTIONS
KEEP(*(.embedded_block))
} > FLASH :text
/**
* Initialized data and RAM-resident code (LMA in flash, VMA in RAM).
* Startup copies from __data_lma to __data_start..__data_end.
*/
.data :
{
. = ALIGN(4);
__data_start = .;
*(.ram_func*)
*(.data*)
. = ALIGN(4);
__data_end = .;
} > RAM AT> FLASH :data
__data_lma = LOADADDR(.data);
/**
* Uninitialized data (BSS) in RAM.
*/
.bss (NOLOAD) :
{
. = ALIGN(4);
__bss_start = .;
*(.bss*)
*(COMMON)
. = ALIGN(4);
__bss_end = .;
} > RAM
/**
* Non-secure stack symbols.
*/
@@ -38,10 +38,38 @@
extern int main(void);
extern uint32_t __data_lma;
extern uint32_t __data_start;
extern uint32_t __data_end;
extern uint32_t __bss_start;
extern uint32_t __bss_end;
static void _data_copy_init(void)
{
uint32_t *src = &__data_lma;
uint32_t *dst = &__data_start;
while (dst < &__data_end)
*dst++ = *src++;
}
static void _bss_zero_init(void)
{
uint32_t *dst = &__bss_start;
while (dst < &__bss_end)
*dst++ = 0U;
}
void _ram_init(void)
{
stack_init();
_data_copy_init();
_bss_zero_init();
}
void __attribute__((naked, noreturn)) Reset_Handler(void)
{
__asm__ volatile (
"bl stack_init\n\t"
"bl _ram_init\n\t"
"bl xosc_init\n\t"
"bl xosc_enable_peri_clk\n\t"
"bl reset_init_subsystem\n\t"
Binary file not shown.
+30
View File
@@ -50,6 +50,7 @@ MEMORY
PHDRS
{
text PT_LOAD FLAGS(5);
data PT_LOAD FLAGS(6);
}
/**
@@ -94,6 +95,35 @@ SECTIONS
KEEP(*(.embedded_block))
} > FLASH :text
/**
* Initialized data and RAM-resident code (LMA in flash, VMA in RAM).
* Startup copies from __data_lma to __data_start..__data_end.
*/
.data :
{
. = ALIGN(4);
__data_start = .;
*(.ram_func*)
*(.data*)
. = ALIGN(4);
__data_end = .;
} > RAM AT> FLASH :data
__data_lma = LOADADDR(.data);
/**
* Uninitialized data (BSS) in RAM.
*/
.bss (NOLOAD) :
{
. = ALIGN(4);
__bss_start = .;
*(.bss*)
*(COMMON)
. = ALIGN(4);
__bss_end = .;
} > RAM
/**
* Non-secure stack symbols.
*/
+29 -1
View File
@@ -38,10 +38,38 @@
extern int main(void);
extern uint32_t __data_lma;
extern uint32_t __data_start;
extern uint32_t __data_end;
extern uint32_t __bss_start;
extern uint32_t __bss_end;
static void _data_copy_init(void)
{
uint32_t *src = &__data_lma;
uint32_t *dst = &__data_start;
while (dst < &__data_end)
*dst++ = *src++;
}
static void _bss_zero_init(void)
{
uint32_t *dst = &__bss_start;
while (dst < &__bss_end)
*dst++ = 0U;
}
void _ram_init(void)
{
stack_init();
_data_copy_init();
_bss_zero_init();
}
void __attribute__((naked, noreturn)) Reset_Handler(void)
{
__asm__ volatile (
"bl stack_init\n\t"
"bl _ram_init\n\t"
"bl xosc_init\n\t"
"bl xosc_enable_peri_clk\n\t"
"bl reset_init_subsystem\n\t"
Binary file not shown.
+30
View File
@@ -50,6 +50,7 @@ MEMORY
PHDRS
{
text PT_LOAD FLAGS(5);
data PT_LOAD FLAGS(6);
}
/**
@@ -94,6 +95,35 @@ SECTIONS
KEEP(*(.embedded_block))
} > FLASH :text
/**
* Initialized data and RAM-resident code (LMA in flash, VMA in RAM).
* Startup copies from __data_lma to __data_start..__data_end.
*/
.data :
{
. = ALIGN(4);
__data_start = .;
*(.ram_func*)
*(.data*)
. = ALIGN(4);
__data_end = .;
} > RAM AT> FLASH :data
__data_lma = LOADADDR(.data);
/**
* Uninitialized data (BSS) in RAM.
*/
.bss (NOLOAD) :
{
. = ALIGN(4);
__bss_start = .;
*(.bss*)
*(COMMON)
. = ALIGN(4);
__bss_end = .;
} > RAM
/**
* Non-secure stack symbols.
*/
@@ -39,10 +39,38 @@
extern int main(void);
extern uint32_t __data_lma;
extern uint32_t __data_start;
extern uint32_t __data_end;
extern uint32_t __bss_start;
extern uint32_t __bss_end;
static void _data_copy_init(void)
{
uint32_t *src = &__data_lma;
uint32_t *dst = &__data_start;
while (dst < &__data_end)
*dst++ = *src++;
}
static void _bss_zero_init(void)
{
uint32_t *dst = &__bss_start;
while (dst < &__bss_end)
*dst++ = 0U;
}
void _ram_init(void)
{
stack_init();
_data_copy_init();
_bss_zero_init();
}
void __attribute__((naked, noreturn)) Reset_Handler(void)
{
__asm__ volatile (
"bl stack_init\n\t"
"bl _ram_init\n\t"
"bl xosc_init\n\t"
"bl xosc_enable_peri_clk\n\t"
"bl reset_init_subsystem\n\t"
Binary file not shown.
+30
View File
@@ -50,6 +50,7 @@ MEMORY
PHDRS
{
text PT_LOAD FLAGS(5);
data PT_LOAD FLAGS(6);
}
/**
@@ -94,6 +95,35 @@ SECTIONS
KEEP(*(.embedded_block))
} > FLASH :text
/**
* Initialized data and RAM-resident code (LMA in flash, VMA in RAM).
* Startup copies from __data_lma to __data_start..__data_end.
*/
.data :
{
. = ALIGN(4);
__data_start = .;
*(.ram_func*)
*(.data*)
. = ALIGN(4);
__data_end = .;
} > RAM AT> FLASH :data
__data_lma = LOADADDR(.data);
/**
* Uninitialized data (BSS) in RAM.
*/
.bss (NOLOAD) :
{
. = ALIGN(4);
__bss_start = .;
*(.bss*)
*(COMMON)
. = ALIGN(4);
__bss_end = .;
} > RAM
/**
* Non-secure stack symbols.
*/
@@ -38,10 +38,38 @@
extern int main(void);
extern uint32_t __data_lma;
extern uint32_t __data_start;
extern uint32_t __data_end;
extern uint32_t __bss_start;
extern uint32_t __bss_end;
static void _data_copy_init(void)
{
uint32_t *src = &__data_lma;
uint32_t *dst = &__data_start;
while (dst < &__data_end)
*dst++ = *src++;
}
static void _bss_zero_init(void)
{
uint32_t *dst = &__bss_start;
while (dst < &__bss_end)
*dst++ = 0U;
}
void _ram_init(void)
{
stack_init();
_data_copy_init();
_bss_zero_init();
}
void __attribute__((naked, noreturn)) Reset_Handler(void)
{
__asm__ volatile (
"bl stack_init\n\t"
"bl _ram_init\n\t"
"bl xosc_init\n\t"
"bl xosc_enable_peri_clk\n\t"
"bl reset_init_subsystem\n\t"
Binary file not shown.
+19
View File
@@ -50,6 +50,7 @@ MEMORY
PHDRS
{
text PT_LOAD FLAGS(5);
data PT_LOAD FLAGS(6);
}
/**
@@ -100,11 +101,29 @@ SECTIONS
.bss (NOLOAD) :
{
. = ALIGN(4);
__bss_start = .;
*(.bss*)
*(COMMON)
. = ALIGN(4);
__bss_end = .;
} > RAM
/**
* Initialized data and RAM-resident code (LMA in flash, VMA in RAM).
* Startup copies from __data_lma to __data_start..__data_end.
*/
.data :
{
. = ALIGN(4);
__data_start = .;
*(.ram_func*)
*(.data*)
. = ALIGN(4);
__data_end = .;
} > RAM AT> FLASH :data
__data_lma = LOADADDR(.data);
/**
* Non-secure stack symbols.
*/
@@ -39,6 +39,34 @@
extern int main(void);
extern uint32_t __data_lma;
extern uint32_t __data_start;
extern uint32_t __data_end;
extern uint32_t __bss_start;
extern uint32_t __bss_end;
static void _data_copy_init(void)
{
uint32_t *src = &__data_lma;
uint32_t *dst = &__data_start;
while (dst < &__data_end)
*dst++ = *src++;
}
static void _bss_zero_init(void)
{
uint32_t *dst = &__bss_start;
while (dst < &__bss_end)
*dst++ = 0U;
}
void _ram_init(void)
{
stack_init();
_data_copy_init();
_bss_zero_init();
}
void _late_init(void)
{
timer_release_reset();
@@ -48,7 +76,7 @@ void _late_init(void)
void __attribute__((naked, noreturn)) Reset_Handler(void)
{
__asm__ volatile (
"bl stack_init\n\t"
"bl _ram_init\n\t"
"bl xosc_init\n\t"
"bl xosc_enable_peri_clk\n\t"
"bl reset_init_subsystem\n\t"
Binary file not shown.
+19
View File
@@ -50,6 +50,7 @@ MEMORY
PHDRS
{
text PT_LOAD FLAGS(5);
data PT_LOAD FLAGS(6);
}
/**
@@ -100,11 +101,29 @@ SECTIONS
.bss (NOLOAD) :
{
. = ALIGN(4);
__bss_start = .;
*(.bss*)
*(COMMON)
. = ALIGN(4);
__bss_end = .;
} > RAM
/**
* Initialized data and RAM-resident code (LMA in flash, VMA in RAM).
* Startup copies from __data_lma to __data_start..__data_end.
*/
.data :
{
. = ALIGN(4);
__data_start = .;
*(.ram_func*)
*(.data*)
. = ALIGN(4);
__data_end = .;
} > RAM AT> FLASH :data
__data_lma = LOADADDR(.data);
/**
* Non-secure stack symbols.
*/
@@ -39,10 +39,38 @@
extern int main(void);
extern uint32_t __data_lma;
extern uint32_t __data_start;
extern uint32_t __data_end;
extern uint32_t __bss_start;
extern uint32_t __bss_end;
static void _data_copy_init(void)
{
uint32_t *src = &__data_lma;
uint32_t *dst = &__data_start;
while (dst < &__data_end)
*dst++ = *src++;
}
static void _bss_zero_init(void)
{
uint32_t *dst = &__bss_start;
while (dst < &__bss_end)
*dst++ = 0U;
}
void _ram_init(void)
{
stack_init();
_data_copy_init();
_bss_zero_init();
}
void __attribute__((naked, noreturn)) Reset_Handler(void)
{
__asm__ volatile (
"bl stack_init\n\t"
"bl _ram_init\n\t"
"bl xosc_init\n\t"
"bl xosc_enable_peri_clk\n\t"
"bl reset_init_subsystem\n\t"
Binary file not shown.
+19
View File
@@ -50,6 +50,7 @@ MEMORY
PHDRS
{
text PT_LOAD FLAGS(5);
data PT_LOAD FLAGS(6);
}
/**
@@ -100,11 +101,29 @@ SECTIONS
.bss (NOLOAD) :
{
. = ALIGN(4);
__bss_start = .;
*(.bss*)
*(COMMON)
. = ALIGN(4);
__bss_end = .;
} > RAM
/**
* Initialized data and RAM-resident code (LMA in flash, VMA in RAM).
* Startup copies from __data_lma to __data_start..__data_end.
*/
.data :
{
. = ALIGN(4);
__data_start = .;
*(.ram_func*)
*(.data*)
. = ALIGN(4);
__data_end = .;
} > RAM AT> FLASH :data
__data_lma = LOADADDR(.data);
/**
* Non-secure stack symbols.
*/
@@ -38,26 +38,13 @@
extern int main(void);
/**
* @brief Linker-defined symbol: flash LMA of .data section.
*/
extern uint32_t __data_lma;
/**
* @brief Linker-defined symbol: RAM VMA start of .data section.
*/
extern uint32_t __data_start;
/**
* @brief Linker-defined symbol: RAM VMA end of .data section.
*/
extern uint32_t __data_end;
extern uint32_t __bss_start;
extern uint32_t __bss_end;
/**
* @brief Copy initialized data and RAM-resident code from flash to RAM.
* @retval None
*/
static void data_copy_init(void)
static void _data_copy_init(void)
{
uint32_t *src = &__data_lma;
uint32_t *dst = &__data_start;
@@ -65,16 +52,24 @@ static void data_copy_init(void)
*dst++ = *src++;
}
void ram_init(void)
static void _bss_zero_init(void)
{
uint32_t *dst = &__bss_start;
while (dst < &__bss_end)
*dst++ = 0U;
}
void _ram_init(void)
{
stack_init();
data_copy_init();
_data_copy_init();
_bss_zero_init();
}
void __attribute__((naked, noreturn)) Reset_Handler(void)
{
__asm__ volatile (
"bl ram_init\n\t"
"bl _ram_init\n\t"
"bl xosc_init\n\t"
"bl xosc_enable_peri_clk\n\t"
"bl reset_init_subsystem\n\t"
Binary file not shown.
+2
View File
@@ -117,9 +117,11 @@ SECTIONS
.bss (NOLOAD) :
{
. = ALIGN(4);
__bss_start = .;
*(.bss*)
*(COMMON)
. = ALIGN(4);
__bss_end = .;
} > RAM
/**