dRonin  adbada4
dRonin firmware
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
startup.c
Go to the documentation of this file.
1 
13 /*
14  * This program is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU General Public License as published by
16  * the Free Software Foundation; either version 3 of the License, or
17  * (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful, but
20  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
21  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  * for more details.
23  *
24  * You should have received a copy of the GNU General Public License along
25  * with this program; if not, see <http://www.gnu.org/licenses/>
26  */
27 
28 
29 #include <string.h>
30 #include <stm32f4xx.h>
31 
32 /* prototype for main() that tells us not to worry about it possibly returning */
33 extern int main(void) __attribute__((noreturn));
34 
35 /* prototype our _main() to avoid prolog/epilog insertion and other related junk */
36 void _main(void) __attribute__((noreturn, naked, no_instrument_function));
37 
39 static void default_cpu_handler(void) __attribute__((noreturn, naked, no_instrument_function));
40 
42 extern char _sbss, _ebss;
43 
45 extern char _sidata, _sdata, _edata, _sfast, _efast;
46 
48 char irq_stack[1024] __attribute__((section(".irqstack")));
49 
51 typedef const void (vector)(void);
52 
54 struct cm3_vectors {
55  void *initial_stack;
56  vector *entry;
57  vector *vectors[14];
58 };
59 
63 void
64 _main(void)
65 {
66  /* At least some bootloaders increment the MSP off the top of the stack
67  * before jumping to here. Let's set it ourselves to make sure it's good */
68  asm volatile ("msr msp, %0" : : "r" (&irq_stack[sizeof(irq_stack)]) : );
69  /* load the stack base for the current stack before we attempt to branch to
70  * any function that might bounds-check the stack */
71  asm volatile ("mov r10, %0" : : "r" (&irq_stack[0]) : );
72 
73  /* Disable all interrupts, until proper table etc is installed. */
74  __disable_irq();
75 
76  /* enable usage, bus and memory faults */
77  SCB->SHCSR |= SCB_SHCSR_USGFAULTENA_Msk | SCB_SHCSR_BUSFAULTENA_Msk | SCB_SHCSR_MEMFAULTENA_Msk;
78 
79  /* configure FP state save behaviour - automatic, lazy save */
80  FPU->FPCCR |= FPU_FPCCR_ASPEN_Msk | FPU_FPCCR_LSPEN_Msk;
81 
82  /* configure default FPU state */
83  FPU->FPDSCR |= FPU_FPDSCR_DN_Msk; /* enable Default NaN */
84  FPU->FPDSCR |= FPU_FPDSCR_FZ_Msk; /* Use flush to zero for very
85  * small values. */
86 
87  /* enable the FPU */
88  SCB->CPACR |= (0xf << 20); // turn on CP10/11 for FP support on cores that implement it
89 
90  /* copy initialised data from flash to RAM */
91  memcpy(&_sdata, &_sidata, &_edata - &_sdata);
92 
93  /* zero the BSS */
94  memset(&_sbss, 0, &_ebss - &_sbss);
95 
96  /* zero any 'fast' RAM that's been used */
97 #if defined(STM32F40_41xxx)
98  memset(&_sfast, 0, &_efast - &_sfast);
99 #endif /* defined(STM32F40_41xxx) */
100  /* fill most of the IRQ/bootstrap stack with a watermark pattern so we can measure how much is used */
101  /* leave a little space at the top in case memset() isn't a leaf with no locals */
102  memset(&irq_stack, 0xa5, sizeof(irq_stack) - 64);
103 
104  /* call main */
105  (void)main();
106 }
107 
112 register void *stack_pointer asm("sp");
113 
114 
115 static void
117 {
118  // Hijack the process stack pointer to make backtrace work
119  asm("mrs %0, psp" : "=r"(HARDFAULT_PSP) : :);
120  stack_pointer = HARDFAULT_PSP;
121  while(1);
122 }
123 
125 #define HANDLER(_name) extern vector _name __attribute__((weak, alias("default_cpu_handler")))
126 
127 /* standard CMSIS vector names */
128 HANDLER(NMI_Handler);
129 HANDLER(HardFault_Handler);
130 HANDLER(MemManage_Handler);
131 HANDLER(BusFault_Handler);
132 HANDLER(UsageFault_Handler);
133 HANDLER(DebugMon_Handler);
134 
136 struct cm3_vectors cpu_vectors __attribute((section(".cpu_vectors"))) = {
137  .initial_stack = &irq_stack[sizeof(irq_stack)],
138  .entry = (vector *)_main,
139  .vectors = {
140  NMI_Handler,
141  HardFault_Handler,
142  MemManage_Handler,
143  BusFault_Handler,
144  UsageFault_Handler,
145  0,
146  0,
147  0,
148  0,
149  0,
150  DebugMon_Handler,
151  0,
152  0,
153  0,
154  }
155 };
156 
void _main(void)
Definition: startup.c:64
char _ebss
const void( vector)(void)
Definition: startup.c:32
char _sidata
char _sbss
#define HANDLER(_name)
Definition: startup.c:125
char _sdata
const void *_vectors[] __attribute((section(".vectors")))
int main(void)
Definition: chibi_main.c:69
char _edata
static void default_cpu_handler(void)
Definition: startup.c:116
void ** HARDFAULT_PSP
Definition: startup.c:111
static void entry()
Definition: loadabletest.c:40