5.5.17 · Coding › Embedded Systems & Real-Time Software
Tumhara compiler object files banata hai jo code aur data se bhare hote hain, lekin usse bilkul idea nahin ki chip ki physical memory mein yeh sab kahan rehna chahiye. Linker script ek map hai: yeh linker ko bolta hai "Flash yahan hai, RAM wahan hai , aur is tarah ka stuff us region mein jaata hai." PC pe OS yeh sab tere liye karta hai. Bare-metal microcontroller pe, tu hi OS hai — linker script woh tarika hai jisse tu silicon se baat karta hai.
Ek microcontroller mein kam se kam do bilkul alag memories hoti hain:
Flash (ROM) — non-volatile, power off hone ke baad bhi contents rakhta hai, lekin runtime pe isme sasta likhna possible nahin. → code aur constants ke liye accha.
RAM — volatile, power-off pe contents kho jaate hain, fast read/write. → variables ke liye accha jo change hote hain.
Ek text file (usually .ld) jo linker (ld) padhta hai, jisme memory regions define hote hain (physical memory kahan hai) aur output sections (code/data ko un regions mein kaise group aur place karein). Isme symbols bhi define hote hain jo startup code memory copy/zero karne ke liye use karta hai.
Iska core tension yeh hai:
Initialized variables (int x = 5;) ka value Flash mein stored rehna chahiye (power-off survive kare) lekin RAM se run karna chahiye (taaki change ho sake). Toh inke do addresses hote hain: ek load address (Flash) aur ek run address (RAM). Yahi famous LMA vs VMA distinction hai.
Section
Kya rakhta hai
Runtime mein kahan rehta hai
Initial value Flash mein stored hai?
.text
machine code + const data
Flash
haan (yeh khud hi data hai)
.rodata
read-only constants
Flash
haan
.data
initialized globals/statics (int x=5)
RAM
haan (boot pe copy hota hai)
.bss
zero-initialized globals (int y;)
RAM
nahin (boot pe sirf zero hota hai)
.stack/.heap
runtime stack & dynamic memory
RAM
nahin
.bss Flash kyun bachata hai
.bss = "Block Started by Symbol" (historical naam). Agar koi variable zero se start hota hai, toh Flash mein 10,000 zeros store karna wasteful hoga. Iske bajaye linker sirf kitna bada .bss hai yeh record karta hai, aur startup code RAM ke upar loop karta hai aur zeros likhta hai . Cost: kuch bytes size info + ek chhota sa loop, kilobytes stored zeros ki jagah.
Jab chip reset hoti hai, abhi tak koi C code nahi chala — RAM garbage hai. Reset_Handler (assembly/C startup) ko yeh karna hota hai:
.data copy karo uske Flash load address (LMA) se uske RAM run address (VMA) pe.
.bss zero karo RAM mein.
Stack pointer set karo.
main() call karo.
Linker script woh symbols export karta hai jo is code ko chahiye:
_sidata = LOADADDR(.data); /* .data init values Flash mein kahan hain */
_sdata = ADDR(.data); /* .data ko RAM mein kahan run karna hai */
_edata = _sdata + SIZEOF(.data);
_sbss = ADDR(.bss);
_ebss = _sbss + SIZEOF(.bss);
// startup.c — har line ka WHY:
for ( uint32_t * p =& _sidata, * q =& _sdata; q < & _edata; ) * q ++ = * p ++ ; // copy .data Flash→RAM
for ( uint32_t * q =& _sbss; q < & _ebss; ) * q ++ = 0 ; // zero .bss
Worked example Script ko first principles se banao
Step 1 — physical memory declare karo. Kyun? Linker ko address ranges aur sizes jaanna zaroori hai taaki overflow detect ho sake.
MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 256K
RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 64K
}
Yeh attrs kyun? r=read, w=write, x=execute. Flash rx hai (runtime pe tu isme nahi likhta); RAM rwx hai.
Step 2 — code ko Flash mein place karo. >FLASH kyun? Code non-volatile hai aur in-place execute hota hai.
SECTIONS {
.text : {
KEEP(*(.isr_vector)) /* vector table SABSE PEHLE — CPU address 0 yahan padhta hai */
*(.text*)
*(.rodata*)
} > FLASH
KEEP kyun? Vector table kabhi naam se call nahin hota, toh garbage collector use drop kar dega — KEEP yeh mana karta hai.
Step 3 — .data place karo: RAM mein run karo, Flash se load karo. AT> FLASH magic hai.
_sidata = LOADADDR(.data);
.data : {
_sdata = .;
*(.data*)
_edata = .;
} > RAM AT> FLASH
Do regions kyun? > RAM VMA (run address) set karta hai; AT> FLASH LMA (load address) set karta hai. Init values physically Flash mein baithi hain; startup unhe RAM mein copy karta hai.
Step 4 — .bss: sirf RAM, koi Flash backing nahin.
.bss : {
_sbss = .;
*(.bss*)
*(COMMON)
_ebss = .;
} > RAM
}
AT> kyun nahin? Load karne ko kuch hai hi nahin — yeh boot pe sirf zero hota hai.
.bss Flash binary mein space leta hai."
Kyun sahi lagta hai: .bss variables tere program mein exist karte hain, toh zaahir hai store hote honge. Fix: .bss uninitialized/zero hai, toh linker sirf uski size record karta hai; .bin file mein iske liye koi bytes nahin hote. RAM usage ≠ Flash usage.
Common mistake "Initialized globals khud kaam karte hain, startup code ki zaroorat nahin."
Kyun sahi lagta hai: PC pe int x=5; automatically kaam karta hai. Fix: Woh "automatic" copy OS loader karta hai. Bare-metal mein, agar tera startup code .data Flash→RAM copy nahin karta, tere initialized globals garbage honge (jo bhi RAM power-up pe tha). Copy loop bhoolna ek classic "debug mein kaam karta hai, release mein toot jaata hai" bug hai.
Common mistake "VMA aur LMA hamesha same hote hain."
Kyun sahi lagta hai: .text ke liye, yeh hote hi hain equal (code Flash se run karta hai). Fix: .data ke liye yeh alag hote hain — yahi poora reason hai AT> exist karta hai. Inhe confuse karne se variables Flash addresses se padhte hain ya kabhi copy hi nahin hote.
Common mistake "Main vector table ke aas-paas
KEEP drop kar sakta hoon space bachane ke liye."
Kyun sahi lagta hai: Linker garbage collection unused sections remove karta hai — size ke liye accha. Fix: Koi bhi vector table ko symbol se reference nahin karta, toh GC use delete karta hai → CPU address 0 pe jump karta hai aur kuch nahin milta → boot pe hard fault.
Recall Feynman: 12-saal ke bacche ko explain karo
Socho tum ek naye ghar (chip) mein move kar rahe ho. Tumhare paas do storage areas hain: ek attic (Flash) jo tumhara saman kabhi kho nahin deta chahe power off ho jaye, aur ek desk (RAM) jo use karna super easy hai lekin roz raat ko saaf ho jaati hai. Teri instructions (code) aur teri toys ki starting values ki list hamesha ke liye attic mein rehti hain. Jab bhi tum uthte ho (reset), ek chhota helper (startup code) starting values ko attic se neeche desk pe le jaata hai taaki tum unse khel sako, aur khali desk spots ko zero kar deta hai . Linker script ek floor plan hai jo sabko batata hai ki kaunsi cheez kaunse shelf pe jaayegi.
Mnemonic Section homes yaad rakho
"Text Reads, Data Doubles, BSS Blanks."
T ext/R odata → sirf Flash (read).
D ata → D ouble address (Flash LMA + RAM VMA).
B SS → RAM mein B lank/zeroed, koi Flash nahin.
Linker script ka MEMORY block kya define karta hai? Physical memory regions — ORIGIN (start address), LENGTH (size), aur attributes (rwx) jaise FLASH aur RAM ke liye.
.text kahan rehta hai aur kahan run karta hai?LMA aur VMA dono Flash mein — code non-volatile memory se in-place execute hota hai.
.data ke do alag addresses (LMA aur VMA) kyun hote hain?Initial values non-volatile Flash mein stored rehni chahiye (LMA), lekin variables runtime pe RAM mein writable hone chahiye (VMA); startup code Flash→RAM copy karta hai.
.bss kya hai aur yeh Flash space kyun bachata hai?Zero-initialized globals; sirf uski size record hoti hai, zeros nahin — startup code us RAM region ko ek loop mein zero karta hai.
SECTIONS entry mein AT> FLASH kya karta hai? Section ka load address (LMA) Flash pe set karta hai jabki > RAM run address (VMA) set karta hai.
Reset_Handler ko main() call karne se pehle do kaam kya karne chahiye? .data ko Flash se RAM mein copy karo, aur RAM mein .bss region ko zero karo.
Interrupt vector table ke aas-paas KEEP() kyun use karte hain? Koi ise symbol se reference nahin karta, toh linker garbage collection ise discard kar dega; KEEP ise force karta hai retain rehne ke liye.
LOADADDR(.data) vs ADDR(.data) kya return karta hai?LOADADDR = LMA (init values ka Flash address); ADDR = VMA (RAM run address).
Agar startup mein .data copy karna bhool jaao, kya hoga? Initialized globals apni declared values ki jagah power-on garbage contain karengi.
RAM (rwx) mein rwx attributes ka matlab kya hai?read, write, execute permissions jo linker us region ko assign kar sakta hai.
Startup code & Reset_Handler
Vector table & interrupt handling
Compilation pipeline — object files & relocation
Volatile keyword & memory-mapped IO
Stack vs Heap in embedded systems
Flash vs RAM tradeoffs
ELF file format & sections