Visual walkthrough — Startup code — vector table, reset handler, stack initialization
5.5.16 · D2· Coding › Embedded Systems & Real-Time Software › Startup code — vector table, reset handler, stack initializa
Step 1 se pehle, teen plain-word anchors jo hum har jagah reuse karenge:
Related building blocks yahan milenge: Linker scripts and memory sections (.text .data .bss), ARM Cortex-M exception and interrupt model, aur Stack vs Heap memory layout.
Step 1 — Power-on pe machine: do memories, ek confused CPU
KYA HAI. Jis pal power stable hoti hai, hamare paas do alag memories hain aur ek CPU jo abhi tak kuch nahi kiya.
- Flash (non-volatile, power off hone pe bhi contents rakhti hai): tumhara program image rakhti hai — machine code, aur tumhare variables ki initial values. Yeh typically address
0x0800_0000se shuru hoti hai (ya0x0000_0000pe aliased hoti hai). - RAM (volatile, power-up pe contents undefined hoti hain): jahan variables rahenge aur badlenge.
0x2000_0000se shuru hoti hai.
YEH PICTURE PEHLE KYUN. Baad ke har step mein ya toh in do boxes ke beech data copy ho raha hai ya clear ho raha hai, ya koi pointer unme se kisi ek ke andar aim kar raha hai. Agar tumhare dimaag mein yeh two-box picture hai, toh iske baad kuch bhi surprising nahi lagega.
PICTURE. Left pe Flash bhari aur orderly hai; right pe RAM question marks se bhari hai — genuinely unknown values.

Step 2 — Vector table: sirf woh do words jo hardware khud padhta hai
KYA HAI. Program image ke bilkul bottom mein ek chhoti si array hoti hai jise vector table kehte hain. CPU, purely hardware mein, exactly apne pehle do words padhta hai:
Term by term padhte hain:
- — offset
0x00pe stored 32-bit number. Hardware ise SP mein copy karta hai. Yeh code nahi hai; yeh ek address hai — stack ka intended top. - — offset
0x04pe number. Hardware ise PC mein copy karta hai. Yeh ek code ka address hai — Reset Handler ka.
YEH DO HI, IS ORDER MEIN KYUN. Stack kisi bhi instruction ke run hone se pehle valid hona chahiye, kyunki interrupts ko respond karne wali machinery stack pe push karti hai. Toh chip designers SP pehle load karte hain, pehle word se — koi code abhi chala nahi hai, isliye yeh pure hardware hona chahiye. Phir PC, taaki execution ke paas jaane ki jagah ho.
PICTURE. Do amber arrows table ke pehle do rungs se nikal ke CPU ke SP aur PC boxes mein jaati hain.

Step 3 — SP load karna: stack-top, aur yeh RAM ki ceiling ki taraf kyun point karta hai
KYA HAI. Word 0 mein number _estack hai — linker ne ise (highest RAM address) + 1 ke roop mein diya hai. 0x2000_0000 pe 20 KB RAM ke liye:
- — pehla RAM address (floor).
- — hex mein 20 KB ().
- — last valid rung se ek aage: ceiling+1.
TOP SE KYUN, BOTTOM SE NAHI? Stack full-descending hai: SP last likhے gaye item ki taraf point karta hai, aur push pehle SP se 4 subtract karta hai, phir write karta hai. Isliye SP ko high shuru karna hota hai aur neeche jaata hai. Wahi heap (agar koi ho) low end se upar badhta hai. Dono ko opposite ends pe shuru karne ka matlab hai ki woh sirf ek predictable tarike se collide karte hain. (Zyada detail Stack vs Heap memory layout mein.)
PICTURE. RAM ek vertical bar ke roop mein; SP top edge pe hai; ek dashed amber arrow future growth ki direction neeche ki taraf dikhata hai.

Step 4 — PC load karna aur Reset Handler mein jump karna
KYA HAI. Word 1 PC mein jaata hai, toh CPU ka next fetched instruction Reset_Handler ka pehla instruction hota hai. Execution yahan se shuru hoti hai. Abhi tak koi main() nahi, koi globals nahi — bas SP set hai aur PC aimed hai.
DIRECTLY main ki jagah handler KYUN. main assume karta hai ki globals apni values rakhte hain aur .bss zero hai. Yeh kuch bhi abhi true nahi hai. Reset Handler woh minimum glue hai jo un facts ko manufacture karta hai (Steps 5–6) main ko control dene se pehle. Seedha main mein jump karne se manufacturing skip ho jaati hai — initialised globals Flash-time garbage read karte. (Compare The C runtime and crt0.)
PICTURE. PC arrow ab Flash ke andar Reset Handler ke code ke pehle rung pe land karta hai; ek caption uski to-do list list karta hai.

Step 5 — .data copy karna: initialised globals ko unki values dena
KYA HAI. Har initialised global (int g = 42;) ke liye, value 42 build time pe Flash mein bake ki gayi thi, lekin variable writable RAM mein rehna chahiye. Toh handler ek block Flash→RAM copy karta hai. Linker hamare paas teen markers deta hai:
_sidata— jahan init image Flash mein hai (source start)._sdata,_edata— RAM mein.dataka start aur end (destination).
RAM offset pe word ke liye copy:
- — hum RAM
.datablock mein kitne andar hain (pehle word ke liye 0, agle ke liye 4…). - — Flash image mein wahi door. n-th RAM word ← n-th Flash word.
Code mein yeh do-pointer march hai: while (dst < &_edata) *dst++ = *src++;
KYUN. Flash ko normal stores se runtime par write nahi kiya ja sakta, aur uski values power cycles ke baad survive karni chahiye. RAM change ho sakti hai (ek global jise tum assign karte ho) lekin garbage se shuru hoti hai. Copy karna dono reconcile karta hai: sahi initial value aur writability.
PICTURE. Do cursors lockstep mein chalte hain — src Flash image ke through, dst RAM ke through — arrows 42 ko across carry karte hain.

Step 6 — .bss zero karna: undefined RAM ko guaranteed zero mein badalna
KYA HAI. Uninitialised globals (int z;, int counter;) .bss region banate hain. C guarantee karta hai ki woh 0 read karein, lekin Flash mein koi zeros stored nahi hain (zeros store karne mein space kyun waste karein?). Handler simply range ke across 0 write karta hai:
_sbss,_ebss— RAM mein.bssblock ka start aur end (linker se).- Loop power-on garbage ko clean zeros se overwrite karta hai, ek word at a time.
KYUN. Step 1 ne dikhaya ki RAM noise se shuru hoti hai. Is loop ke bina, int counter; kisi random value se shuru ho sakta hai; counter++ nonsense produce karta hai. Zeroing undefined ko C-promised 0 mein convert karta hai.
PICTURE. RAM ka .bss slice question marks se solid run of 0s mein flip hota hai, ek broom-cursor sweep karta hua.

Step 7 — Constructors, phir main() mein jump
KYA HAI. .data correct aur .bss zeroed hone ke saath, C environment exist karta hai. Do last acts:
__libc_init_array()C++ static/global constructors run karta hai (pure C mein harmless no-op).main()mein branch-with-link. Yeh ek normal function call hai: return address push hota hai — stack ka pehla real use.
main ke baad loop-forever KYUN. Bare metal pe return karne ke liye koi operating system nahi hai. Agar main kabhi return kare, toh while(1){} CPU ko deliberately trap karta hai bajaye call ke baad jo garbage sit karta ho woh execute karne ke.
PICTURE. main ka return address 0x2000_4FFC pe land karta hai — exactly _estack - 4 — Step 3 ka off-by-one confirm karta hua.

Step 8 — Degenerate cases (reader ko kabhi stranded mat chhodho)
KYA / KYUN, case by case:
- Empty
.data(koi initialised globals nahi):_sdata == _edata.while (dst < &_edata)test immediately false hota hai — zero iterations, correctly kuch copy nahi. Koi special-casing zaroorat nahi. - Empty
.bss(koi uninitialised globals nahi):_sbss == _ebss, loop zero times run hota hai. Correct. - RAM ready hone se pehle zero-size stack usage: avoid karna impossible hai — isliye SP Step 2 mein hardware se load hota hai, kisi bhi code se pehle. Ordering hi safeguard hai.
- VTOR relocation (bootloader present): table
0x0000_0000pe nahi hona chahiye;VTORnaam ka ek register hardware ko batata hai ki table actually kahan hai. Upar ki sab baatein phir bhi hold karti hain — sirf woh offset badalta hai jahan se hardware padhta hai. Dekho Bootloaders and VTOR relocation. - Stack overflow: koi MMU guard page nahi hone ke saath, stack silently apni region ke past
.bss/heap mein grow karta hai aur unhe corrupt kar deta hai. Detection ke liye linker_Min_Stack_Sizegap,MSPLIMregister (Cortex-M33), ya fill-pattern watermark chahiye — hardware tumhe warn nahi karega.
PICTURE. Left panel: ek empty range jahan start == end (loop skip ho jaata hai). Right panel: stack arrow .bss ke floor se crash karta hua andar, collision hone ki jagah ek amber warning.

Ek picture mein poora summary
Sab kuch ek canvas pe: hardware table ke do words se SP aur PC load karta hai → Reset Handler .data Flash→RAM copy karta hai → .bss zero karta hai → constructors run karta hai → main ko working full-descending stack ke saath call karta hai.

Recall Feynman Retelling — ek dost ko batao
Chip dumb hokar jaagta hai. Do memories exist karti hain: Flash (tumhara program, sab kuch yaad rakhti hai, runtime pe read-only) aur RAM (scratch space, pure garbage se shuru hoti hai). CPU ka pehla kaam, silicon mein zero code ke saath, yeh hai ki woh tumhare program ke front se do numbers padhta hai: pehla stack pointer ban jaata hai (scratch space ke top ka bookmark), doosra program counter ban jaata hai (yah code run karo). Woh code Reset Handler hai. Woh teen kaam karta hai: tumhare int x = 42; globals ki starting values Flash se RAM mein copy karta hai; "should-be-zero" globals ko scrub karta hai taaki woh actually zero ho jaayein (luck-of-the-draw noise nahi); constructors run karta hai. Tab hi woh main call karta hai. Stack RAM ki ceiling pe rehta hai aur neeche badhta hai, toh pehla function call bilkul top se ek word neeche bookmark karta hai. Agar main kabhi finish ho, toh code forever spin karta hai, kyunki bare metal pe ghar jaane ki koi jagah nahi hai.
Recall
Vector table ke pehle do words kahan jaate hain? ::: Word 0 → SP (initial stack top), Word 1 → PC (Reset Handler address).
Flash se RAM mein .data copy kyun karte hain? ::: Initial values read-only Flash mein baked hain; variable writable RAM mein rehna chahiye, isliye hum value copy karte hain aur writability paate hain.
.bss explicitly zero kyun karte hain? ::: RAM power-up pe undefined hoti hai; loop garbage ko C-guaranteed 0 mein convert karta hai.
_estack = 0x2000_5000 ke liye pehla push kahan land karta hai? ::: 0x2000_4FFC pe = _estack - 4 (full-descending stack).
Parent: Back to 5.5.16 · Prereqs: Volatile, memory-mapped registers and hardware init, The C runtime and crt0.