Worked examples — Startup code — vector table, reset handler, stack initialization
5.5.16 · D3· Coding › Embedded Systems & Real-Time Software › Startup code — vector table, reset handler, stack initializa
Yahan sab kuch the parent topic pe build karta hai. Jab hum touch karte hain ki linker humein addresses kaise deta hai, woh hai Linker scripts and memory sections (.text .data .bss); jab hum touch karte hain ki CPU registers kaise stack karta hai, woh hai ARM Cortex-M exception and interrupt model.
Shuru karne se pehle: teen symbols jo har example use karta hai
Hum teen families of names se baar baar milte hain. Chalein inhe ek picture se pin kar dete hain taaki koi bhi symbol kabhi mystery na rahe.

Scenario matrix
Har case class jo yeh topic tumpe throw kar sakta hai, aur kaun sa worked example use cover karta hai:
| # | Case class | Concrete stimulus | Example |
|---|---|---|---|
| A | Normal load — dono sections non-empty | .data mein 2 words, .bss mein 1 word |
Ex 1 |
| B | Empty .data (degenerate copy) |
koi initialized globals nahi → _sdata == _edata |
Ex 2 |
| C | Empty .bss (degenerate zero) |
har global initialized hai → _sbss == _ebss |
Ex 2 |
| D | Stack boundary / first push | entry ke baad aur first push ke baad MSP trace karo |
Ex 3 |
| E | Sign / direction of growth | full-descending SP, kya yeh upar overflow hota hai ya neeche? | Ex 3 |
| F | Collision limit — stack vs heap | stack kitna grow kar sakta hai .bss se pehle? |
Ex 4 |
| G | Relocated table (VTOR ≠ 0) — bootloader case | app ka table 0x0800_4000 pe, hardware kya read karta hai? |
Ex 5 |
| H | Real-world word problem | ek sensor buffer as a global — uska data kahan se aata hai? | Ex 6 |
| I | Exam twist — .bss-not-cleared heisenbug |
bug ka symptom predict karo | Ex 7 |
| J | Exam twist — misaligned _estack |
_estack odd/not word-aligned, kya fault hoga? |
Ex 8 |
Ab hum har cell ko hit karte hain.
Setup. 20 KB RAM: 0x2000_0000 … 0x2000_4FFF, toh _estack = 0x2000_5000. CPU full-descending hai (SP last used item ko point karta hai; ek push pehle 4 se decrement karta hai, phir likhta hai). Pehla pushed word kahan land karta hai?
Forecast: 0x2000_5000 pe? 0x2000_4FFC pe? kahin aur?
- Hardware MSP load karta hai. Word @
0x0000_0000=0x2000_5000→ MSP. Yeh step kyun? Cortex-M pe sabse pehli cheez jo hardware karta hai woh hai stack pointer set karna, koi bhi code run hone se pehle (figure dekho). - First push hota hai. SP SP , phir word wahan likha jaata hai. Pehle decrement kyun? "Full-descending" ka matlab hai SP hamesha valid data ko point karta hai; naya data add karne ke liye hume pehle neeche subtract karke jagah banana hota hai.
- Direction check. Har aage wala push 4 subtract karta hai → addresses
0x2000_0000ki taraf neeche jaate hain. Neeche kyun? Taaki stack aur ek heap jo low end se upar grow karta hai ek dusre ki taraf move karein, ek predictable collision point de.

Verify: highest byte jo ek full-descending stack kabhi likhta hai woh hai _estack - 1 = 0x2000_4FFF — last real RAM byte, kabhi nahi 0x2000_5000 (jo RAM se bahar hai). Off-by-one correct hai: initial value end+1 hai precisely taaki pehla subtract last valid word pe land kare. ✓
Setup. Same 20 KB RAM. .data + .bss milke 0x2000_0000 … 0x2000_07FF (2 KB) occupy karte hain. Heap theek uske baad 0x2000_0800 se start hota hai aur (is snapshot ke liye) empty hai. _estack = 0x2000_5000. .bss/heap corrupt karne se pehle maximum stack depth bytes mein kya hai?
Forecast: 18 KB? 20 KB? kam?
- Do frontiers identify karo. Stack ka top-of-growth
0x2000_5000se neeche pahunchta hai; neeche wala region jo safe rehna chahiye woh used low memory ke top0x2000_0800pe khatam hota hai. Yeh step kyun? Collision exactly tab hoti hai jab descending SP occupied low memory mein cross karta hai. - Gap compute karo. bytes KB. Subtract kyun? "Stack start" aur "pehle occupied byte neeche" ke beech free window maximum descent hai.
- Entries mein convert karo. words of 32-bit pushes. Kyun /4? Har push SP ko ek word = 4 bytes move karta hai.
Verify: (data/bss/heap) KB total RAM. Har byte account hota hai. Agar linker ka _Min_Stack_Size guard 18 KB set hota, yeh just fit hota; 18 KB + 1 byte link fail karta — ek silent overflow ki jagah ek clean compile-time catch. ✓
Setup. Ek bootloader 0x0800_0000 pe rehta hai. Yeh ek application ki taraf jump karta hai jiska vector table 0x0800_4000 pe hai. App ka table word 0 = 0x2000_5000, word 1 = 0x0800_4101 (Reset_Handler, LSB Thumb ke liye set hai). Bootloader VTOR = 0x0800_4000 set karta hai, phir app ka reset path trigger karta hai. VTOR set hone ke baad, app kaunsa stack pointer aur kaunsa entry point use karta hai?
Forecast: kya CPU abhi bhi 0x0000_0000 read karta hai, ya naya table?
- VTOR table ka base hai.
VTOR(Vector Table Offset Register) CPU ko batata hai ki entry 0 kahan hai.VTOR = 0x0800_4000ke baad, "word 0" ka matlab hai[0x0800_4000]. Yeh step kyun? VTOR ke bina table0x0000_0000pe fixed hota hai; VTOR do independent tables (boot + app) ko coexist karne deta hai. - App ka SP load karo. Bootloader manually karta hai
MSP = *(uint32_t*)0x0800_4000 = 0x2000_5000. Manually kyun? Ek software jump hardware reset sequence re-trigger nahi karta, toh bootloader ko word 0 khud MSP mein copy karna hota hai. - App ke reset handler pe jump karo.
PC = *(uint32_t*)0x0800_4004 = 0x0800_4101; CPU LSB mask karta hai real address0x0800_4100ke liye aur Thumb state mein rehta hai. Mask kyun? Cortex-M pe low bit Thumb flag hai, address ka part nahi; real entry0x0800_4100hai.
Verify: entry address = 0x0800_4101 & ~1 = 0x0800_4100; app ka SP = 0x2000_5000 Ex 3 ke _estack se match karta hai. +0x4000 offset entry 1 ki file location shift karta hai par SP value data hai, unchanged. ✓
Setup. Ek firmware mein ek global calibration array hai:
static const float k[3] = {1.0f, 0.5f, 0.25f}; read-only use hota hai, aur ek working buffer static float acc[3]; runtime pe accumulate hota hai. Kaun sa array reset handler copy karta hai, kaun sa zero hota hai, aur main ki pehli line mein acc[0] kya read karta hai?
Forecast: pehle har array ka section name karo.
kclassify karo. Yehconstaur initialized hai → Flash mein.rodata. Yeh RAM mein copy nahi hota (Flash se directly read hota hai). Kyun? Const data kabhi change nahi hota, toh ise Flash mein rakhne se RAM bachti hai; reset handler.rodatako touch nahi karta.accclassify karo. Uninitialized (koi= {...}nahi) →.bss. Kyun? Koi initial values nahi matlab Flash mein zeros store karna wasteful hoga;.bsszero-cleared region hai.mainmeinacc[0]predict karo..bssloop neaccke sabko0x0000_0000likha →acc[0] == 0.0f. Kyun? Bit pattern0x00000000exactly IEEE-754+0.0hai, toh ek zeroed float0.0read karta hai.
Verify: k Flash mein rehta hai (uske liye 0 RAM copies); acc bytes of .bss occupy karta hai, sab 0 set; acc[0] == 0.0f. Agar acc initializer {9,9,9} ke saath .data hota, toh yeh _sidata se copy hota. ✓
Setup. Startup code .data sahi copy karta hai par .bss loop missing hai. Ek global static int errors; (.bss mein) if (errors > 0) reboot(); ke roop mein use hota hai. Author ke board pe yeh kabhi reboot nahi karta; ek colleague ke identical board pe yeh randomly reboot karta hai. Explain karo aur predict karo.
Forecast: kaunsi line "randomly" trigger karti hai?
errorsgarbage se start hota hai. Koi zeroing nahi, toherrorsmein woh hoga jo RAM cell mein power-up pe tha — undefined. Yeh step kyun? SRAM power-up state 0 guaranteed nahi hoti; yeh silicon aur last power state pe depend karti hai.- Author ki kismat. Woh cell unke board pe
0tha, toherrors > 0false hai → koi reboot nahi. Kyun? Undefined ≠ har baar random; ek given chip reliably 0 se power up ho sakta hai, bug ko hide karte hue. - Colleague ka failure. Ek alag die
errors = 0x0000_0004(maan lo) ke saath power up hota hai →errors > 0true → spurious reboot. Kyun? Same source code, alag physical garbage → classic non-reproducible heisenbug.
Verify: fix ke saath, .bss zeroing har board pe errors = 0 force karta hai → errors > 0 start pe deterministically false. Symptom gayab hota hai kyunki "undefined" C-guaranteed 0 ban gaya. ✓
_estack
Setup. Ek student linker script edit karta hai aur _estack = 0x2000_4FFE (4 se divisible nahi) set karta hai. RAM 0x2000_4FFF pe khatam hoti hai. Pehle exception pe kya hoga?
Forecast: kaam karta hai? HardFault? silent?
- Alignment rule state karo. Cortex-M require karta hai ki SP ek exception boundary pe 8-byte aligned ho (aur hamesha word-aligned);
0x2000_4FFEword-aligned bhi nahi hai (). Yeh step kyun? Hardware SP use karke registers auto-stack karta hai; misaligned SP matlab unaligned 32-bit writes. - Fault predict karo. Ek misaligned address pe pehla push/auto-stack ek UsageFault raise karta hai (ya HardFault escalate hota hai agar UsageFault disabled ho). Kyun? Exception model ek misaligned stack ko error treat karta hai, wraparound nahi.
- Fix.
_estackko ek word boundary tak round down karo:0x2000_5000(ya nearest ). Kyun? , word aur 8-byte rule dono satisfy karta hai.
Verify: → misaligned, faults. → aligned, safe. Corrected value exactly "end+1 rounded to 8" convention hai. ✓
Recall Kya har matrix cell hit hua?
Normal load (A) ::: Ex 1 Empty .data / empty .bss (B, C) ::: Ex 2 First push & growth direction (D, E) ::: Ex 3 Stack↔heap collision limit (F) ::: Ex 4 Relocated table via VTOR (G) ::: Ex 5 Real-world const-vs-bss (H) ::: Ex 6 .bss heisenbug symptom (I) ::: Ex 7 Misaligned _estack fault (J) ::: Ex 8
Copy Zero Call, top-down stack"
Copy .data → Zero .bss → Call main; aur stack top pe rehta hai, neeche grow karta hai.
Yahan use ki gayi connections
- Linker scripts and memory sections (.text .data .bss) — har
_s…/_e…symbol ka source. - ARM Cortex-M exception and interrupt model — Ex 3 & Ex 8 mein auto-stacking aur alignment rules.
- Stack vs Heap memory layout — Ex 4 mein collision geometry.
- Bootloaders and VTOR relocation — Ex 5 mein relocated table.
- Volatile, memory-mapped registers and hardware init —
VTORkhud kaise write hota hai. - The C runtime and crt0 — woh bigger picture jisme reset handler fit hota hai.