parent::[[221-Modern-Embedded]] next::[[C221-L14-Startup Code Part 2-Linker]] previous::[[C221-L12-Structures in C andCortex Microcontroller Software Interface Standard (CMSIS) ✅]] > [!TIP]- Outgoing Links > ```dataview > list > where contains(this.file.outlinks, file.link) and !contains(lower(file.name), "course") > ``` Summary:: Linker and map file; RAM sections bss, data, text, etc; Startup code and Vector table; ## Summary - RAM has a various sections that we can see from the linker created "map file" - `.bss` is space for uninitialized variables - `.data` is initialized or declared variables outside of `main` - ROM - `.text`,`.rodata`: e.g. the program code and the read only data - `Initializer Bytes` are the initial, out side of main variables that will be transferred to `RAM → .data` during the data initialization startup code - ① the processor loads the stack pointer (SP) and program counter (PC) from the vector table → ② `iar_program_start` is startup code provided by IAR → ③ `__iar_init_vfp()` initializes the hardware floating point unit → ④ `__low_level_init()` allows for early custom hardware initialization. → ⑤ `__iar_data_init3()` performs data initialization → ⑥ Finally, main() is called. - when initializing variables outside of main, space is allocated in ROM with the initial values, and subsequently copied to RAM→`.data` during the data initialization call. - `.bss` in RAM should contain all zeros for uninitialized variables, **but this is not always the case for all processors** and uninitialized (but declared) variables may need to be explicitly initialized to zero - in the `STR.W R3, [R2], #0x4` instruction, since the 0x4 is not in the brackets, this means that the address at R2 is incremented **after** the data at R3 is stored there (used for the loop when initializing the .data addresses) - the vector table contains the PC and SP values that are loaded on RESET, as well as exception handlers. Note that in the next lesson we will learn how to make sure that all the exception handlers are correctly loaded into this vector table, which has not been the case thus far (all exceptions have been resulting in `BusFault_Handler`) - beware of default interrupt handlers that result in a tight "BusFault" loop that is good for debugging/development but should not be used in a production environment (the device will be "bricked") - ## Notes ### Startup and Initialization #anki-todo startup flow "fill in the blanks" > [!ai]- Startup Flow → [[embedded machine startup code]] > Here is an overview of the standard C initialization startup sequence based on the transcript: > > - After reset, the processor loads the stack pointer (SP) and program counter (PC) from the vector table. > - First code executed is __iar_program_start provided by the IAR C startup library. > - __iar_init_vfp() initializes the hardware floating point unit. > - __low_level_init() allows for early custom hardware initialization. > - __iar_data_init3() performs data initialization: > - First it zeroes the .bss section for uninitialized variables. > - Then it copies initialized data from the "Initializer bytes" section to the .data section. > - Finally, main() is called. > > Key points: > > - Vector table initializes SP and PC. > - Startup code handles FPU, custom init, zeroing .bss, copying initialized data. > - By the time main() is called, all C variables are initialized properly. > - Map file shows how code and data sections are placed in memory. ### Map file and data sections The map file shows you the data sections created by the compiler. > [!NOTE] We need to set the option to generate linker map file in settings ### Adding Data Outside of Main Results in a `.data` Section in RAM When we add data outside of main, it will create an "initializer bytes" section in ROM, and a .data section in RAM. During the `__iar_data_init3` function the data will be copied from these initializer bytes in ROM to the `.data` section in RAM > [!CAUTION] The order of initialization of variables outside main does not mirror how they are stored in memory, the compiler will choose. This is so the copy can be done in a block move. ![[cpu initializer section.png]]_The initializers bytes are copied in a block to the .data_ > See specific machine instruction in the Appendix > [!ai]- BSS vs Data sections > The .bss and .data sections serve different purposes in a C program: > > - .bss holds uninitialized variables. These variables are declared without an explicit initializer in the code. > - The .bss section occupies space in RAM. > - During startup, the .bss section is zeroed out by the code. > - .data holds initialized variables. These variables have explicit initializers provided in the code. > - The .data section occupies space in RAM. > - During startup, the .data section is copied from the "Initializer bytes" section in ROM, which contains the initial values.k > [!CAUTION] Not all startup code clears the uninitialized `.bss` block > It's a good idea to check your startup code (16:03) since not all startup code clears the `.bss` block - if you find your `.bss` sections not cleared you may need to **explicitly** initialize to zero all of your previously uninitialized variables. (e.g. with TI DSPs) ### Before Startup Code - Vector Table and Reset On Reset the CPU will go to the vector table and does some specific instructions with these. How does the PC get pointed to the `__iar_program_start` and how is the SP set? ![[Screenshot 2023-08-30 at 9.31.58 PM.png]] > The ARM Cortex-M processor is hardwired such that after reset it copies the bits from address 0 to the SP register, and the all bits except the least-significant-bit from address 0x4 to the PC The value at 0x4 is 0x219 to signify 1 for the Thumb mode of the processor (it is dropped when it goes to the PC) > But the IAR table does not contain interrupt vectors that are specific to a given microcontroller, such as IRQ0, IRQ1, etc., so it cannot really handle any interrupts. This is why all the exceptions have been appearing as a `BusFault_Handler` - the IAR just chooses the alphabetically first one. The vector table shows the `BusFault_Handler` code will be at `0x1db`: ![[Screenshot 2023-08-30 at 9.44.45 PM.png]] _Showing the IAR defined exception handlers at `0x1da`, note that they are all at the same address, and they all result in a tight loop to itself (`B.N BusFault_Handler`- good for debugging but not for production ("Denial of Service")_ ## Appendix ### Low Level Init Is startup code defined by IAR, providing a way to run custom startup code early on (e.g. setup clock speed) It returns a value that is used to either go straight into `main` or go to data initialization ### Close Up View of `iar_zero_init` This is where the CPU is zeroing out the RAM data and copying initial values into it Zero'ing out the RAM data (see PC is at RAM location), `STR.W` command is used to loop through ![[Screenshot 2023-08-30 at 8.37.49 PM.png]] ![[Screenshot 2023-08-30 at 8.40.06 PM.png]] _Here the 0x4 value outside of the brackets means the R2 address is incremented **after** the 0 value is stored in R2_ ### Vector Table Layout The vector table in the datasheets shows that the 0x0 address is the initial SP value and the 0x04 address is the Reset (i.e. first PC address) → [[vector table]] ![[Screenshot 2023-08-30 at 9.37.07 PM.png]] ### Other Screens The first place we go is `iar program start` ![[Screenshot 2023-08-30 at 8.21.01 PM.png]] ![[Screenshot 2023-08-30 at 8.36.55 PM.png]]