5.5.16 · D4 · HinglishEmbedded Systems & Real-Time Software

ExercisesStartup code — vector table, reset handler, stack initialization

2,735 words12 min read↑ Read in English

5.5.16 · D4 · Coding › Embedded Systems & Real-Time Software › Startup code — vector table, reset handler, stack initializa

Shuru karne se pehle, yahan woh memory picture hai jis par har problem tiki hui hai. Ise ek baar, dhyan se dekho.

Figure — Startup code — vector table, reset handler, stack initialization

Neeche use kiye gaye prerequisite links: Linker scripts and memory sections (.text .data .bss), ARM Cortex-M exception and interrupt model, Stack vs Heap memory layout, The C runtime and crt0, Bootloaders and VTOR relocation, Volatile, memory-mapped registers and hardware init.


L1 · Recognition

Exercise 1 (L1)

Reset par ek Cortex-M CPU vector table se do words padhta hai. Table 0x0000_0000 par shuru hoti hai. 0x0000_0000 par word = 0x2000_8000. 0x0000_0004 par word = 0x0000_0101. In do reads ke baad, MSP mein kya hai aur PC mein kya hai?

Recall Solution

Hardware rule fixed hai: word 0 → MSP, word 1 → PC.

  • MSP (stack-top address).
  • PC (Reset Handler ka address).

Word 0 stack kyun hai, code kyun nahi: CPU ko registers push karne ki jagah chahiye kisi bhi instruction ke chalne se pehle (interrupts cycle zero se registers stack kar sakte hain). Isliye designers ne sabse pehla word stack pointer banaya. Dekho ARM Cortex-M exception and interrupt model.

Exercise 2 (L1)

Neeche diya gaya vector table C mein likha hua hai. Kaun si entry actually ek function nahi hai, aur code phir bhi compile kyun hota hai?

void (* const vector_table[])(void) = {
    (void (*)(void)) &_estack,   // A
    Reset_Handler,               // B
    NMI_Handler,                 // C
};
Recall Solution

Entry A ek function nahi hai — yeh stack-top address _estack hai. Yeh compile hota hai kyunki array ka element type "pointer to function taking void returning void" hai, aur hum address &_estack ko us type mein cast karte hain sirf C ke type checker ko satisfy karne ke liye. Hardware word 0 ko kabhi call nahi karta; woh 32-bit number ko MSP mein copy karta hai. Ek number ko function-pointer type mein cast karna use code nahi banata.


L2 · Application

Exercise 3 (L2)

RAM 0x2000_0000 se 0x2000_4FFF tak hai (20 KB). Stack full-descending hai. Linker _estack ko kya value assign karta hai, aur pehla pushed word kahaan jaata hai?

Recall Solution

_estack = highest RAM address + 1 .

Full-descending matlab push pehle SP ko 4 se decrement karta hai, phir likhta hai. 0x2000_5000 se shuru karke: Toh pehla pushed word bytes 0x2000_4FFC..0x2000_4FFF occupy karta hai — bilkul top wala usable slot. Figure mein orange arrow dekho: stack neeche ki taraf RAM mein grow karta hai. Dekho Stack vs Heap memory layout.

Exercise 4 (L2)

.data RAM _sdata = 0x2000_0000 se _edata = 0x2000_0010 tak occupy karta hai (end exclusive). Har word 4 bytes ka hai. Copy loop kitne words ke liye run karta hai, aur (parent ke index formula ka use karke) RAM word at 0x2000_000C ko kaun sa Flash address feed karta hai agar _sidata = 0x0800_1000 ho?

Recall Solution

Word count: span in bytes bytes words.

RAM 0x2000_000C ke liye Flash source: parent ka rule hai Yahan , toh offset bytes. Kyun: RAM .data ka n-waan word Flash image ke n-waane word se copy hota hai; RAM mein offset Flash mein offset ke barabar hota hai. Dekho Linker scripts and memory sections (.text .data .bss).


L3 · Analysis

Exercise 5 (L3)

Ek student ka reset handler .data sahi se copy karta hai lekin .bss-zeroing loop delete kar di gayi hai. Program mein int counter; ... counter++; hai jo loop bound ki tarah use hota hai. Unke board par kaam karta hai lekin factory-fresh board par hang ho jaata hai. Bilkul precisely explain karo kyun, .bss kya guarantee karta hai us baat ke terms mein.

Recall Solution

.bss mein zero-initialized globals rehte hain. C guarantee karta hai ki int counter; 0 se start hoga. Reset handler woh guarantee manufacture karta hai .bss RAM region ko clear karke.

Loop delete hone par, counter mein power-up par RAM mein jo bhi tha woh hoga — jo undefined hai. Student ke board par woh RAM pehle se 0 padh raha tha (warm reset ke baad common), toh counter luck se 0 se shuru hua. Fresh board par, RAM garbage se power up hua (jaise 0xDEAD_BEEF), toh counter++ ek bade number se start hota hai aur loop bound galat hai → hang.

Fix: zeroing loop for (dst=&_sbss; dst<&_ebss;) *dst++ = 0; restore karo. Yeh "undefined" ko promised 0 mein convert karta hai. Dekho The C runtime and crt0.

Exercise 6 (L3)

.bss _sbss = 0x2000_0100 se _ebss = 0x2000_0300 tak hai. Zeroing loop har iteration mein ek 32-bit word likhta hai. Kitne iterations run hote hain, aur kitne bytes zero hote hain?

Recall Solution

Span bytes.

  • Bytes zeroed .
  • Iterations words.

4 se kyun divide: loop ek uint32_t* pointer increment karta hai, aur uint32_t* par dst++ sizeof(uint32_t) = 4 bytes aage badhta hai. Har iteration ek word likhti hai.

Exercise 7 (L3)

Vector table offset 0x40 se IRQ handlers rakhti hai. Har entry ek word (4 bytes) ki hai. IRQ5 ke handler ka byte offset kya hai, aur agar VTOR = 0x0800_0000 ho toh woh memory address kya hai?

Recall Solution

IRQ0 offset 0x40 par hai. Entry IRQn bytes par hai. Table relocate hoke VTOR = 0x0800_0000 par: VTOR kyun matter karta hai: ek bootloader table ko 0x0000_0000 se hata kar application ki table ki taraf VTOR point kar sakta hai, toh CPU naye base se index karta hai. Dekho Bootloaders and VTOR relocation.


L4 · Synthesis

Exercise 8 (L4)

Ordering design karo. Tumhe ek reset handler likhna hai jo (a) .data copy kare, (b) .bss zero kare, (c) ek memory-mapped clock register initialize kare jo RAM-based code ko chahiye, (d) C++ constructors run kare, (e) main call kare. Inme se do ka ek strict ordering constraint hai ek doosre ke saath obvious se aage. Ek sahi full order do aur ek non-obvious constraint justify karo.

Recall Solution

Ek sahi order:

  1. (c) clock/hardware init — often pehle, taki baaki sab full speed par run kare aur koi bhi wait-states configure ho jaayein. (Uses Volatile, memory-mapped registers and hardware init.)
  2. (a) .data copy karo
  3. (b) .bss zero karo
  4. (d) C++ constructors (__libc_init_array)
  5. (e) main call karo

Non-obvious constraint: (d) constructors (a) aur (b) dono ke baad aane chahiye. Ek C++ constructor ek global object read ya write kar sakta hai — ek initialized global .data mein rehta hai, ek default wala .bss mein. Agar constructors copy/zero se pehle run karein, toh woh garbage RAM ko touch karenge, aur phir step (a)/(b) jo constructor ne likha use overwrite kar dega. Toh .data/.bss setup kisi bhi user code (constructors included) ke execute hone se pehle finish hona chahiye.

(c) pehle kyun ja sakta hai: clock register ek hardware register hai, C global nahi — yeh .data/.bss par depend nahi karta, toh yeh early mein safe (aur often required) hai.

Exercise 9 (L4)

3 words ke .data ke liye copy-.data loop ko formula sequence ke roop mein likho, _sdata = 0x2000_0000, _sidata = 0x0800_2000 ke saath. Har (destination, source) pair list karo jo loop produce karta hai.

Recall Solution

use karte hue, source ke saath, har word ke liye 4 bytes step karte hue:

word RAM dest () offset Flash source
0 0x2000_0000 0x0 0x0800_2000
1 0x2000_0004 0x4 0x0800_2004
2 0x2000_0008 0x8 0x0800_2008

Parallel step kyun: dono pointers har iteration mein same 4 bytes aage badhte hain (*dst++ = *src++), toh RAM offset aur Flash offset saath locked rehte hain — yahi formula express karta hai.


L5 · Mastery

Exercise 10 (L5)

Ek device mein RAM 0x2000_00000x2000_1FFF (8 KB) hai. Low end se upar layout: .data = 256 bytes, .bss = 512 bytes, phir heap, phir ek gap, phir stack jo _estack se neeche grow karta hai. Designer _Min_Stack_Size = 1 KB aur _Min_Heap_Size = 1 KB guaranteed chahta hai. _estack compute karo, woh byte offset jahan .bss khatam hoti hai, aur reserved heap ke top aur reserved stack ke bottom ke beech kitne free bytes hain. Agar woh free region exhaust ho jaaye toh failure mode batao.

Recall Solution

Constants: 8 KB bytes; 1 KB bytes.

  • .data 0x2000_0000 .. 0x2000_00FF occupy karta hai (256 bytes). Offset 0x100 par khatam hota hai.
  • .bss agle 512 bytes occupy karta hai: 0x2000_0100 .. 0x2000_02FF. .bss offset par khatam hota hai , yaani address 0x2000_0300.
  • Reserved heap = .bss ke upar 1024 bytes: 0x2000_0300 .. 0x2000_06FF, offset par khatam.
  • _estack = top of RAM + 1 .
  • Reserved stack = _estack ke neeche 1024 bytes: 0x2000_1C00 .. 0x2000_1FFF, uska bottom offset par.
  • Free gap reserved-heap end aur reserved-stack bottom ke beech:

Failure mode agar gap exhaust ho: bina MMU guard page ke, badhta stack silently _estack - 1024 se neeche heap/.bss mein utarta hai aur memory corrupt karta hai — symptoms door ke variables mein dikhte hain, overflow site par nahi. Mitigations: linker _Min_Stack_Size check (jo 1 KB reserve karta hai), Cortex-M33 par MSPLIM register, ya fill-pattern watermark jo detect kare ki stack kitni door tak pahuncha. Dekho Stack vs Heap memory layout.

Exercise 11 (L5)

Numerically prove karo ki main ko directly vector-table offset 0x04 par rakhna (reset handler skip karke) ek initialized global ko galat chhod deta hai. int g = 42; lo jo RAM 0x2000_0000 par hai, 42 Flash mein _sidata par stored hai, aur assume karo ki power-up RAM 0x2000_0000 par 0x0000_0000 padhta hai. Har case mein main mein g ki value kya hai (copy loop ke saath vs bina)?

Recall Solution
  • Reset handler ke saath (copy loop chalta hai): loop Flash ka 42 0x2000_0000 mein likhta hai. Toh g == 42. Sahi.
  • Bina iske (main at 0x04): copy kabhi nahi hoti; g mein power-up RAM jo tha woh hai = 0x0000_0000 = 0. Toh g == 0, 42 nahi. Galat.

Agar power-up RAM ne 0 ki jagah garbage rakha hota, toh g woh garbage hota — aur bhi bura. Yahi reason hai ki reset handler minimum required glue hai: sirf wahi .data copy karta hai aur .bss zero karta hai. Dekho The C runtime and crt0.


Recall

Vector table ka Word 0 kaun se register mein jaata hai? ::: MSP (Main Stack Pointer). Full-descending stack ke liye _estack = 0x2000_5000, pehla push kahaan land karta hai? ::: 0x2000_4FFC. _sdata se offset d par RAM .data word ke liye Flash source? ::: _sidata + d. C++ constructors .data/.bss setup ke baad kyun run karne chahiye? ::: Woh user code hain jo globals touch kar sakte hain; pehle run karna undefined RAM hit karta hai aur kaam clobber ho jaata hai.