Home | Projects | Notes > ARM Cortex-M3/M4 Processor > Startup File
A startup file is responsible for setting up the proper environment for the main user code to run.
Code written in startup file runs before main()
and main()
gets called by the startup code.
Some part of the startup file is target (i.e., processor) dependent. (e.g., Vector table, initializing the stack, turning on/off the processor-specific peripherals such as FPU, etc.)
Startup code takes care of the vector table placement in code memory as required by the ARM Cortex-M processor.
Startup code may also take care stack reinitialization. (You can alter the stack placement.)
Startup code is responsible for .data
and .bss
sections initialization in main memory. It needs to properly copy the .data
section from FLASH to SRAM, and properly initialize the .bss
section to SRAM.
Only after the initial environment is properly setup, the startup code can call the main()
.
Create a vector table for your microcontroller. Vector tables are MCU-specific.
Write a startup code which initializes .data
and .bss
section in SRAM. (Reset_Handler()
)
Call main()
Startup file can be a C file (.c) or an assembly file (.s).
[!] Note: Vector table information can be found in the MCU Reference Manual. Different exceptions for different microcontrollers. Check the documentation!
A vector table is essentially an array of addresses. Create an array to hold MSP and the addresses of handlers for system exceptions and IRQs.
xxxxxxxxxx
51uint32_t vectors[] = {
2 MSP address,
3 System exception handler addresses,
4 IRQ handler addresses
5};
This array is an "Initialized data" from the program's point of view so, by default, the compiler will try to placed it in the .data
section. We don't want that! Vector table must be located in the starting address of the code memory!
.data
section!)
Normally, the compiler places the objects it generates in sections like
data
andbss
. Sometimes, however, you need additional sections, or you need certain particular variables to appear in special sections, for example to map to special hardware. Thesection
attribute specifies that a variable (or function) lives in a particular section.Syntax:
xxxxxxxxxx
191struct duart a __attribute__ ((section ("DUART_A"))) = { 0 };
2// place object 'a' in 'DUART_A' section
3struct duart b __attribute__ ((section ("DUART_B"))) = { 0 };
4char stack[10000] __attribute__ ((section ("STACK"))) = { 0 };
5int init_data __attribute__ ((section ("INITDATA")));
6void func(void) __attribute__ ((section (".random section")));
7
8main()
9{
10/* Initialize stack pointer */
11init_sp (stack + sizeof (stack));
12
13/* Initialize initialized data */
14memcpy (&init_data, &data, &edata - &data);
15
16/* Turn on the serial ports */
17init_duart (&a);
18init_duart (&b);
19}
You can test these by inspecting the object file using the objdump tool.
Updated vector table with the section to be placed specified:
xxxxxxxxxx
51uint32_t vectors[] __attribute__((section(".isr_vector")))= { // leading '.' not mandatory
2 MSP address,
3 System exception handler addresses,
4 IRQ handler addresses
5};
Or,
xxxxxxxxxx
51uint32_t vectors[] = { // leading '.' not mandatory
2 MSP address,
3 System exception handler addresses,
4 IRQ handler addresses
5}; __attribute__((section(".isr_vector")))
Then you can check with the following command that .isr_vector
section has been created:
xxxxxxxxxx
181$ arm-none-eabi-objdump -h stm32_startup.o
2
3stm32_startup.o: file format elf32-littlearm
4
5Sections:
6Idx Name Size VMA LMA File off Algn
7 0 .text 00000000 00000000 00000000 00000034 2**1
8 CONTENTS, ALLOC, LOAD, READONLY, CODE
9 1 .data 00000008 00000000 00000000 00000034 2**2
10 CONTENTS, ALLOC, LOAD, RELOC, DATA
11 2 .bss 00000000 00000000 00000000 0000003c 2**0
12 ALLOC
13 3 .isr_vector 0000000c 00000000 00000000 0000003c 2**1
14 CONTENTS, ALLOC, LOAD, READONLY, CODE
15 4 .comment 00000034 00000000 00000000 00000048 2**0
16 CONTENTS, READONLY
17 5 .ARM.attributes 0000002e 00000000 00000000 0000007c 2**0
18 CONTENTS, READONLY
Now, we've got 97 exceptions (15 system exceptions + 82 interrupts). Do we need to write the handlers for all these at this point?
Not required! You can create a single default handler for all the exceptions and allow the programmer to implement the required handlers as per the application requirements. (Not all applications require all 97 exceptions to be implemented.)
We'll create a Default_Handler()
for this reason!
GCC attributes for functions: weak
and alias
weak
Lets programmer to override already defined weak function (dummy) with the same function name
alias
Lets programmer to give alias for a function
Check GCC documentation for more info!
xxxxxxxxxx
21void NMI_Handler(void) __attribute__((weak, alias("Default_Handler")));
2void HardFault_Handler(void) __attribute__((weak, alias("Default_Handler")));
Here,
Default_Handler()
is an alias forNMI_Handler()
.In the vector table array, address of
Default_Handler()
function will be stored in place of the address of an unimplemented handler. So, when NMI exception (which is not yet defined at this point) triggers,Default_Handler()
will be executed. (Redirected!)Thanks to the
weak
attribute, a programmer can simply override the handler function (with the same function name without__attribute__...
attached when necessary. Then the control will not be directed to theDefault_Handler()
but to the overridden function.
Except for the first entry, which must contain a valid SP value, every Reserved entry must be set to 0!
Reset_Handler()
Initializing .data
and .bss
section in SRAM is taken care of by the Reset_Handler()
.
Copying .data
section from FLASH to SRAM requires some boundary addresses; _edata
, _sdata
, etext
, etc. These information are to be exported from the linker script. So, these are declared with extern
keyword in the startup file.
main()
Newlib is a C standard library implementation intended for use on embedded systems, and it is introduced by Cygnus Solutions (now Reg Hat).
Newlib is written as a Glibc(CNU libc) replacement for embedded systems. It can be used with no OS ("bare-metal") or with a lightweight RTOS.
Newlib ships with GNU ARM toolchain installation as the default C standard library.
GNU libc (glibc) includes ISO C, POSIX, System V, and XPG interfaces.
Due to the increased feature set in Newlib, it has become too bloated to use on the systems where the amount of memory is very much limited.
To provide a C library with a minimal memory footprint, suited for use with microcontrollers, ARM introduced Newlib-Nano based on Newlib. (e.g., Newlib Nano does not support float
data type, by default. To use float
compiler argument must be set.)
Locating Newlib and Newlib-Nano library files on Windows:
Linker flag to specify the specs file for your project: --specs=nano.specs
This flag should not be used with -nostdlib
so, if you have it in your LDFLAGS variable in your makefile, remove it.
When standard library is linked to your project, you will be able to see (by objdumping final ELF file) that a lot of sections are newly added. If there are any duplicate sections, you can merge them into one section by introducing a simple teak to your linker script.
xxxxxxxxxx
151/* linker script */
2
3SECTIONS
4{
5 .text :
6 {
7 ...
8 *(.text) /* merge .text sections from all(*) input files */
9 *(.text.*) /* merge if anything like '.text.<function_name>' gets generated */
10 *(.rodata)
11 *(.rodata.*)
12 ...
13 }> FLASH
14 ...
15}
Check out L9 and L11. To this for all the sections.
Although not mandatory, to merge standard library specific sections (.init
, .fini
) to .text
section:
xxxxxxxxxx
181/* objdump of final ELF */
2
3final.elf: file format elf32-littlearm
4
5Sections:
6Idx Name Size VMA LMA File off Algn
7 0 .text 00002744 08000000 08000000 00010000 2**2
8 CONTENTS, ALLOC, LOAD, READONLY, CODE
9 1 .init 00000018 08002744 08002744 00012744 2**2
10 CONTENTS, ALLOC, LOAD, READONLY, CODE
11 2 .fini 00000018 0800275c 0800275c 0001275c 2**2
12 CONTENTS, ALLOC, LOAD, READONLY, CODE
13 3 .eh_frame 00000004 08002774 08002774 00012774 2**2
14 CONTENTS, ALLOC, LOAD, READONLY, DATA
15 4 .ARM.exidx 00000008 08002778 08002778 00012778 2**2
16 CONTENTS, ALLOC, LOAD, READONLY, DATA
17 5 .data 00000074 20000000 08002780 00020000 2**2
18 CONTENTS, ALLOC, LOAD, DATA
Do as following in your linker script:
xxxxxxxxxx
171/* linker script */
2
3SECTIONS
4{
5.text :
6{
7...
8*(.text)
9*(.text.*)
10*(.init) /* merge c standard library specific section into .text */
11*(fini) /* merge c standard library specific section into .text */
12*(.rodata)
13*(.rodata.*)
14...
15}> FLASH
16...
17}
Recap the flow of the Reset_Handler()
: Initialize .data
section .bss
section main()
.
Now, to initialize the C standard library, we need to call __libc_init_array()
.
The idea of Newlib is to implement the hardware-independent parts of the standard C library and rely on a few low-level system calls that must be implemented with the target hardware in mind.
Newlib does not provide low-level system calls which are going to operate on some of the hardware components of a microcontroller. You, as a programmer, have to provide those low-level system calls.
When you are using Newlib, you must implement the system calls appropriately to support devices, file-systems, and memory management.
Example of a low-level system call:
Inside the system call _write()
you need to write a code depending on which hardware component of the microcontroller you want to associate the printf()
functionality with.
Likewise, you have to provide the implementation for many different low-level system calls such as _read()
, _sbrk()
, etc.
Write a syscalls.c
file which includes hardware-specific function definitions of the system calls, and place it in your project folder.
Sometimes, during the build process, you may encounter some errors like the following:
xxxxxxxxxx
181$ make
2
3arm-none-eabi-gcc -c -mcpu=cortex-m4 -mthumb -std=gnu11 -O0 -o main.o main.c # recipie: command to generate the target
4# arm-none-eabi-gcc -c -mcpu=cortex-m4 -mthumb -std=gnu11 -O0 main.c -o main.o
5# arm-none-eabi-gcc -c -mcpu=cortex-m4 -mthumb -std=gnu11 -O0 main.c -o main.o
6# 'main.c' represents dependency, 'main.o' represents target (@ does look like a target :))
7arm-none-eabi-gcc -c -mcpu=cortex-m4 -mthumb -std=gnu11 -O0 -o led.o led.c
8arm-none-eabi-gcc -c -mcpu=cortex-m4 -mthumb -std=gnu11 -O0 -o stm32_startup.o stm32_startup.c
9arm-none-eabi-gcc -c -mcpu=cortex-m4 -mthumb -std=gnu11 -O0 -o syscalls.o syscalls.c
10arm-none-eabi-gcc --specs=nano.specs -T stm32_ls.ld -Wl,-Map=final.map -o final.elf main.o led.o stm32_startup.o syscalls.o
11/usr/lib/gcc/arm-none-eabi/10.3.1/../../../arm-none-eabi/bin/ld: /usr/lib/gcc/arm-none-eabi/10.3.1/../../../arm-none-eabi/lib/crt0.o: in function `_mainCRTStartup':
12/build/newlib-pB30de/newlib-3.3.0/build/arm-none-eabi/libgloss/arm/semihv2m/../../../../../libgloss/arm/crt0.S:547: undefined reference to `__bss_start__'
13/usr/lib/gcc/arm-none-eabi/10.3.1/../../../arm-none-eabi/bin/ld: /build/newlib-pB30de/newlib-3.3.0/build/arm-none-eabi/libgloss/arm/semihv2m/../../../../../libgloss/arm/crt0.S:547: undefined reference to `__bss_end__'
14/usr/lib/gcc/arm-none-eabi/10.3.1/../../../arm-none-eabi/bin/ld: syscalls.o: in function `_sbrk':
15syscalls.c:(.text+0x258): undefined reference to `end'
16collect2: error: ld returned 1 exit status
17make: *** [makefile:28: final.elf] Error 1
18
This simply means that the system call
_mainCRTStartup()
wants symbols__bss_start__
,__bss_end__
and the system call_sbrk()
wants a symbolend
but, the linker cannot find (locate) them.These type of error can be resolved by simply defining these symbols in your linker script so that the linker can resolve all the references without problem.
WARNING!
When there is any section change introduced over the course, make sure if the symbols that are used in the .data
section transfer code in the Reset_Handler()
since the boundary may have been changed due to the newly introduced section around .data
section in FLASH.
If your application requires floating-point arithmetic, there are a couple of decisions you need to make. You can use,
The hardware Floating-Point Unit (FPU) if supported by the processor
e.g., STM32Fx (ARM Coretex-M4) supports FPU
Attempting to use FPU without initializing it will cause the HardFault exception! Make sure to enable it.
The library functions if FPU not supported by the processor (or even if supported by the processor)
Checkout mfloat-abi=
flag to see how you make the choice!
Startup file written on bare-metal board from scratch.
xxxxxxxxxx
2551/* stm32_startup.c */
2
3
4
5
6// 128 KB (SRAM1 + SRAM2)
7
8
9
10
11/* linker symbols */
12extern uint32_t _etext;
13extern uint32_t _sdata;
14extern uint32_t _edata;
15extern uint32_t _la_data;
16extern uint32_t _sbss;
17extern uint32_t _ebss;
18
19int main(void);
20void __libc_init_array(void);
21
22
23/* function prototypes of STM32F407x systems exception and IRQ handlers */
24/* vector table entries */
25
26void Reset_Handler(void);
27
28void NMI_Handler (void) __attribute__ ((weak, alias("Default_Handler")));
29void HardFault_Handler (void) __attribute__ ((weak, alias("Default_Handler")));
30void MemManage_Handler (void) __attribute__ ((weak, alias("Default_Handler")));
31void BusFault_Handler (void) __attribute__ ((weak, alias("Default_Handler")));
32void UsageFault_Handler (void) __attribute__ ((weak, alias("Default_Handler")));
33void SVC_Handler (void) __attribute__ ((weak, alias("Default_Handler")));
34void DebugMon_Handler (void) __attribute__ ((weak, alias("Default_Handler")));
35void PendSV_Handler (void) __attribute__ ((weak, alias("Default_Handler")));
36void SysTick_Handler (void) __attribute__ ((weak, alias("Default_Handler")));
37void WWDG_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
38void PVD_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
39void TAMP_STAMP_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
40void RTC_WKUP_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
41void RCC_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
42void EXTI0_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
43void EXTI1_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
44void EXTI2_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
45void EXTI3_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
46void EXTI4_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
47void DMA1_Stream0_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
48void DMA1_Stream1_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
49void DMA1_Stream2_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
50void DMA1_Stream3_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
51void DMA1_Stream4_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
52void DMA1_Stream5_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
53void DMA1_Stream6_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
54void ADC_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
55void CAN1_TX_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
56void CAN1_RX0_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
57void CAN1_RX1_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
58void CAN1_SCE_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
59void EXTI9_5_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
60void TIM1_BRK_TIM9_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
61void TIM1_UP_TIM10_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
62void TIM1_TRG_COM_TIM11_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
63void TIM1_CC_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
64void TIM2_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
65void TIM3_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
66void TIM4_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
67void I2C1_EV_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
68void I2C1_ER_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
69void I2C2_EV_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
70void I2C2_ER_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
71void SPI1_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
72void SPI2_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
73void USART1_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
74void USART2_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
75void USART3_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
76void EXTI15_10_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
77void RTC_Alarm_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
78void OTG_FS_WKUP_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
79void TIM8_BRK_TIM12_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
80void TIM8_UP_TIM13_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
81void TIM8_TRG_COM_TIM14_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
82void TIM8_CC_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
83void DMA1_Stream7_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
84void FSMC_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
85void SDIO_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
86void TIM5_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
87void SPI3_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
88void UART4_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
89void UART5_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
90void TIM6_DAC_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
91void TIM7_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
92void DMA2_Stream0_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
93void DMA2_Stream1_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
94void DMA2_Stream2_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
95void DMA2_Stream3_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
96void DMA2_Stream4_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
97void ETH_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
98void ETH_WKUP_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
99void CAN2_TX_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
100void CAN2_RX0_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
101void CAN2_RX1_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
102void CAN2_SCE_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
103void OTG_FS_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
104void DMA2_Stream5_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
105void DMA2_Stream6_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
106void DMA2_Stream7_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
107void USART6_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
108void I2C3_EV_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
109void I2C3_ER_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
110void OTG_HS_EP1_OUT_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
111void OTG_HS_EP1_IN_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
112void OTG_HS_WKUP_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
113void OTG_HS_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
114void DCMI_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
115void CRYP_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
116void HASH_RNG_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
117void FPU_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));
118
119/* vector table */
120uint32_t vectors[] __attribute__((section(".isr_vector"))) = {
121 STACK_START, // first entry of VT is a valid stack pointer
122 (uint32_t)&Reset_Handler,
123 (uint32_t)&NMI_Handler,
124 (uint32_t)HardFault_Handler,
125 (uint32_t)MemManage_Handler,
126 (uint32_t)BusFault_Handler,
127 (uint32_t)UsageFault_Handler,
128 0,
129 0,
130 0,
131 0,
132 (uint32_t)SVC_Handler,
133 (uint32_t)DebugMon_Handler,
134 0,
135 (uint32_t)PendSV_Handler,
136 (uint32_t)SysTick_Handler,
137 (uint32_t)WWDG_IRQHandler,
138 (uint32_t)PVD_IRQHandler,
139 (uint32_t)TAMP_STAMP_IRQHandler,
140 (uint32_t)RTC_WKUP_IRQHandler,
141 0,
142 (uint32_t)RCC_IRQHandler,
143 (uint32_t)EXTI0_IRQHandler,
144 (uint32_t)EXTI1_IRQHandler,
145 (uint32_t)EXTI2_IRQHandler,
146 (uint32_t)EXTI3_IRQHandler,
147 (uint32_t)EXTI4_IRQHandler,
148 (uint32_t)DMA1_Stream0_IRQHandler,
149 (uint32_t)DMA1_Stream1_IRQHandler,
150 (uint32_t)DMA1_Stream2_IRQHandler,
151 (uint32_t)DMA1_Stream3_IRQHandler,
152 (uint32_t)DMA1_Stream4_IRQHandler,
153 (uint32_t)DMA1_Stream5_IRQHandler,
154 (uint32_t)DMA1_Stream6_IRQHandler,
155 (uint32_t)ADC_IRQHandler,
156 (uint32_t)CAN1_TX_IRQHandler,
157 (uint32_t)CAN1_RX0_IRQHandler,
158 (uint32_t)CAN1_RX1_IRQHandler,
159 (uint32_t)CAN1_SCE_IRQHandler,
160 (uint32_t)EXTI9_5_IRQHandler,
161 (uint32_t)TIM1_BRK_TIM9_IRQHandler,
162 (uint32_t)TIM1_UP_TIM10_IRQHandler,
163 (uint32_t)TIM1_TRG_COM_TIM11_IRQHandler,
164 (uint32_t)TIM1_CC_IRQHandler,
165 (uint32_t)TIM2_IRQHandler,
166 (uint32_t)TIM3_IRQHandler,
167 (uint32_t)TIM4_IRQHandler,
168 (uint32_t)I2C1_EV_IRQHandler,
169 (uint32_t)I2C1_ER_IRQHandler,
170 (uint32_t)I2C2_EV_IRQHandler,
171 (uint32_t)I2C2_ER_IRQHandler,
172 (uint32_t)SPI1_IRQHandler,
173 (uint32_t)SPI2_IRQHandler,
174 (uint32_t)USART1_IRQHandler,
175 (uint32_t)USART2_IRQHandler,
176 (uint32_t)USART3_IRQHandler,
177 (uint32_t)EXTI15_10_IRQHandler,
178 (uint32_t)RTC_Alarm_IRQHandler,
179 (uint32_t)OTG_FS_WKUP_IRQHandler,
180 (uint32_t)TIM8_BRK_TIM12_IRQHandler,
181 (uint32_t)TIM8_UP_TIM13_IRQHandler,
182 (uint32_t)TIM8_TRG_COM_TIM14_IRQHandler,
183 (uint32_t)TIM8_CC_IRQHandler,
184 (uint32_t)DMA1_Stream7_IRQHandler,
185 (uint32_t)FSMC_IRQHandler,
186 (uint32_t)SDIO_IRQHandler,
187 (uint32_t)TIM5_IRQHandler,
188 (uint32_t)SPI3_IRQHandler,
189 (uint32_t)UART4_IRQHandler,
190 (uint32_t)UART5_IRQHandler,
191 (uint32_t)TIM6_DAC_IRQHandler,
192 (uint32_t)TIM7_IRQHandler,
193 (uint32_t)DMA2_Stream0_IRQHandler,
194 (uint32_t)DMA2_Stream1_IRQHandler,
195 (uint32_t)DMA2_Stream2_IRQHandler,
196 (uint32_t)DMA2_Stream3_IRQHandler,
197 (uint32_t)DMA2_Stream4_IRQHandler,
198 (uint32_t)ETH_IRQHandler,
199 (uint32_t)ETH_WKUP_IRQHandler,
200 (uint32_t)CAN2_TX_IRQHandler,
201 (uint32_t)CAN2_RX0_IRQHandler,
202 (uint32_t)CAN2_RX1_IRQHandler,
203 (uint32_t)CAN2_SCE_IRQHandler,
204 (uint32_t)OTG_FS_IRQHandler,
205 (uint32_t)DMA2_Stream5_IRQHandler,
206 (uint32_t)DMA2_Stream6_IRQHandler,
207 (uint32_t)DMA2_Stream7_IRQHandler,
208 (uint32_t)USART6_IRQHandler,
209 (uint32_t)I2C3_EV_IRQHandler,
210 (uint32_t)I2C3_ER_IRQHandler,
211 (uint32_t)OTG_HS_EP1_OUT_IRQHandler,
212 (uint32_t)OTG_HS_EP1_IN_IRQHandler,
213 (uint32_t)OTG_HS_WKUP_IRQHandler,
214 (uint32_t)OTG_HS_IRQHandler,
215 (uint32_t)DCMI_IRQHandler,
216 (uint32_t)CRYP_IRQHandler,
217 (uint32_t)HASH_RNG_IRQHandler,
218 (uint32_t)FPU_IRQHandler,
219};
220
221/* dummy function (unimplemented handlers will be directed to this function) */
222void Default_Handler(void)
223{
224 while (1);
225}
226
227void Reset_Handler(void)
228{
229 /* copy .data section from FLASH to SRAM */
230 uint32_t size = (uint32_t)&_edata - (uint32_t)&_sdata;
231
232 uint8_t *pDst = (uint8_t*)&_sdata; //sram
233 //uint8_t *pSrc = (uint8_t*)&_etext; //flash
234 uint8_t *pSrc = (uint8_t*)&_la_data; //flash
235
236 for(uint32_t i =0 ; i < size ; i++)
237 {
238 *pDst++ = *pSrc++;
239 }
240
241 /* initialize the .bss section to zero in SRAM */
242 size = (uint32_t)&_ebss - (uint32_t)&_sbss;
243 pDst = (uint8_t*)&_sbss;
244
245 for(uint32_t i =0 ; i < size ; i++)
246 {
247 *pDst++ = 0;
248 }
249
250 /* call init function for standard library (this is required only if your main()
251 program contains any standard library functions e.g., printf(), scanf(), etc.) */
252 __libc_init_array();
253
254 main();
255}
Nayak, K. (2022). Embedded Systems Programming on ARM Cortex-M3/M4 Processor [Video file]. Retrieved from https://www.udemy.com/course/embedded-system-programming-on-arm-cortex-m3m4/