1 //***************************************************************************** 2 // 3 //! @file startup_gcc.c 4 //! 5 //! @brief Definitions for interrupt handlers, the vector table, and the stack. 6 // 7 //***************************************************************************** 8 9 //***************************************************************************** 10 // 11 // Copyright (c) 2017, Ambiq Micro 12 // All rights reserved. 13 // 14 // Redistribution and use in source and binary forms, with or without 15 // modification, are permitted provided that the following conditions are met: 16 // 17 // 1. Redistributions of source code must retain the above copyright notice, 18 // this list of conditions and the following disclaimer. 19 // 20 // 2. Redistributions in binary form must reproduce the above copyright 21 // notice, this list of conditions and the following disclaimer in the 22 // documentation and/or other materials provided with the distribution. 23 // 24 // 3. Neither the name of the copyright holder nor the names of its 25 // contributors may be used to endorse or promote products derived from this 26 // software without specific prior written permission. 27 // 28 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 29 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 32 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 33 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 34 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 35 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 36 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 37 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 38 // POSSIBILITY OF SUCH DAMAGE. 39 // 40 // This is part of revision v1.2.10-1-gc24dfba-hotfix of the AmbiqSuite Development Package. 41 // 42 //***************************************************************************** 43 44 #include <stdint.h> 45 46 //***************************************************************************** 47 // 48 // Forward declaration of interrupt handlers. 49 // 50 //***************************************************************************** 51 extern void am_reset_isr(void) __attribute ((naked)); 52 extern void am_nmi_isr(void) __attribute ((weak)); 53 extern void am_fault_isr(void) __attribute ((weak)); 54 extern void am_mpufault_isr(void) __attribute ((weak, alias ("am_fault_isr"))); 55 extern void am_busfault_isr(void) __attribute ((weak, alias ("am_fault_isr"))); 56 extern void am_usagefault_isr(void) __attribute ((weak, alias ("am_fault_isr"))); 57 extern void am_svcall_isr(void) __attribute ((weak, alias ("am_default_isr"))); 58 extern void am_debugmon_isr(void) __attribute ((weak, alias ("am_default_isr"))); 59 extern void am_pendsv_isr(void) __attribute ((weak, alias ("am_default_isr"))); 60 extern void am_systick_isr(void) __attribute ((weak, alias ("am_default_isr"))); 61 62 extern void am_brownout_isr(void) __attribute ((weak, alias ("am_default_isr"))); 63 extern void am_watchdog_isr(void) __attribute ((weak, alias ("am_default_isr"))); 64 extern void am_clkgen_isr(void) __attribute ((weak, alias ("am_default_isr"))); 65 extern void am_vcomp_isr(void) __attribute ((weak, alias ("am_default_isr"))); 66 extern void am_ioslave_ios_isr(void) __attribute ((weak, alias ("am_default_isr"))); 67 extern void am_ioslave_acc_isr(void) __attribute ((weak, alias ("am_default_isr"))); 68 extern void am_iomaster0_isr(void) __attribute ((weak, alias ("am_default_isr"))); 69 extern void am_iomaster1_isr(void) __attribute ((weak, alias ("am_default_isr"))); 70 extern void am_iomaster2_isr(void) __attribute ((weak, alias ("am_default_isr"))); 71 extern void am_iomaster3_isr(void) __attribute ((weak, alias ("am_default_isr"))); 72 extern void am_iomaster4_isr(void) __attribute ((weak, alias ("am_default_isr"))); 73 extern void am_iomaster5_isr(void) __attribute ((weak, alias ("am_default_isr"))); 74 extern void am_gpio_isr(void) __attribute ((weak, alias ("am_default_isr"))); 75 extern void am_ctimer_isr(void) __attribute ((weak, alias ("am_default_isr"))); 76 extern void am_uart_isr(void) __attribute ((weak, alias ("am_default_isr"))); 77 extern void am_uart1_isr(void) __attribute ((weak, alias ("am_default_isr"))); 78 extern void am_adc_isr(void) __attribute ((weak, alias ("am_default_isr"))); 79 extern void am_pdm_isr(void) __attribute ((weak, alias ("am_default_isr"))); 80 extern void am_stimer_isr(void) __attribute ((weak, alias ("am_default_isr"))); 81 extern void am_stimer_cmpr0_isr(void) __attribute ((weak, alias ("am_default_isr"))); 82 extern void am_stimer_cmpr1_isr(void) __attribute ((weak, alias ("am_default_isr"))); 83 extern void am_stimer_cmpr2_isr(void) __attribute ((weak, alias ("am_default_isr"))); 84 extern void am_stimer_cmpr3_isr(void) __attribute ((weak, alias ("am_default_isr"))); 85 extern void am_stimer_cmpr4_isr(void) __attribute ((weak, alias ("am_default_isr"))); 86 extern void am_stimer_cmpr5_isr(void) __attribute ((weak, alias ("am_default_isr"))); 87 extern void am_stimer_cmpr6_isr(void) __attribute ((weak, alias ("am_default_isr"))); 88 extern void am_stimer_cmpr7_isr(void) __attribute ((weak, alias ("am_default_isr"))); 89 extern void am_flash_isr(void) __attribute ((weak, alias ("am_default_isr"))); 90 extern void am_software0_isr(void) __attribute ((weak, alias ("am_default_isr"))); 91 extern void am_software1_isr(void) __attribute ((weak, alias ("am_default_isr"))); 92 extern void am_software2_isr(void) __attribute ((weak, alias ("am_default_isr"))); 93 extern void am_software3_isr(void) __attribute ((weak, alias ("am_default_isr"))); 94 95 extern void am_default_isr(void) __attribute ((weak)); 96 97 //***************************************************************************** 98 // 99 // The entry point for the application. 100 // 101 //***************************************************************************** 102 extern int main(void); 103 104 //***************************************************************************** 105 // 106 // Reserve space for the system stack. 107 // 108 //***************************************************************************** 109 __attribute__ ((section(".stack"))) 110 static uint32_t g_pui32Stack[1024]; 111 112 //***************************************************************************** 113 // 114 // The vector table. Note that the proper constructs must be placed on this to 115 // ensure that it ends up at physical address 0x0000.0000. 116 // 117 // Note: Aliasing and weakly exporting am_mpufault_isr, am_busfault_isr, and 118 // am_usagefault_isr does not work if am_fault_isr is defined externally. 119 // Therefore, we'll explicitly use am_fault_isr in the table for those vectors. 120 // 121 //***************************************************************************** 122 __attribute__ ((section(".isr_vector"))) 123 void (* const g_am_pfnVectors[])(void) = 124 { 125 (void (*)(void))((uint32_t)g_pui32Stack + sizeof(g_pui32Stack)), 126 // The initial stack pointer 127 am_reset_isr, // The reset handler 128 am_nmi_isr, // The NMI handler 129 am_fault_isr, // The hard fault handler 130 am_fault_isr, // The MPU fault handler 131 am_fault_isr, // The bus fault handler 132 am_fault_isr, // The usage fault handler 133 0, // Reserved 134 0, // Reserved 135 0, // Reserved 136 0, // Reserved 137 am_svcall_isr, // SVCall handle 138 am_debugmon_isr, // Debug monitor handler 139 0, // Reserved 140 am_pendsv_isr, // The PendSV handler 141 am_systick_isr, // The SysTick handler 142 143 // 144 // Peripheral Interrupts 145 // 146 am_brownout_isr, // 0: Brownout 147 am_watchdog_isr, // 1: Watchdog 148 am_clkgen_isr, // 2: CLKGEN 149 am_vcomp_isr, // 3: Voltage Comparator 150 am_ioslave_ios_isr, // 4: I/O Slave general 151 am_ioslave_acc_isr, // 5: I/O Slave access 152 am_iomaster0_isr, // 6: I/O Master 0 153 am_iomaster1_isr, // 7: I/O Master 1 154 am_iomaster2_isr, // 8: I/O Master 2 155 am_iomaster3_isr, // 9: I/O Master 3 156 am_iomaster4_isr, // 10: I/O Master 4 157 am_iomaster5_isr, // 11: I/O Master 5 158 am_gpio_isr, // 12: GPIO 159 am_ctimer_isr, // 13: CTIMER 160 am_uart_isr, // 14: UART 161 am_uart1_isr, // 15: UART 162 am_adc_isr, // 16: ADC 163 am_pdm_isr, // 17: ADC 164 am_stimer_isr, // 18: SYSTEM TIMER 165 am_stimer_cmpr0_isr, // 19: SYSTEM TIMER COMPARE0 166 am_stimer_cmpr1_isr, // 20: SYSTEM TIMER COMPARE1 167 am_stimer_cmpr2_isr, // 21: SYSTEM TIMER COMPARE2 168 am_stimer_cmpr3_isr, // 22: SYSTEM TIMER COMPARE3 169 am_stimer_cmpr4_isr, // 23: SYSTEM TIMER COMPARE4 170 am_stimer_cmpr5_isr, // 24: SYSTEM TIMER COMPARE5 171 am_stimer_cmpr6_isr, // 25: SYSTEM TIMER COMPARE6 172 am_stimer_cmpr7_isr, // 26: SYSTEM TIMER COMPARE7 173 am_flash_isr, // 27: FLASH 174 am_software0_isr, // 28: SOFTWARE0 175 am_software1_isr, // 29: SOFTWARE1 176 am_software2_isr, // 30: SOFTWARE2 177 am_software3_isr // 31: SOFTWARE3 178 }; 179 180 //***************************************************************************** 181 // 182 // The following are constructs created by the linker, indicating where the 183 // the "data" and "bss" segments reside in memory. The initializers for the 184 // "data" segment resides immediately following the "text" segment. 185 // 186 //***************************************************************************** 187 extern uint32_t _etext; 188 extern uint32_t _sdata; 189 extern uint32_t _edata; 190 extern uint32_t _sbss; 191 extern uint32_t _ebss; 192 193 //***************************************************************************** 194 // 195 // This is the code that gets called when the processor first starts execution 196 // following a reset event. Only the absolutely necessary set is performed, 197 // after which the application supplied entry() routine is called. 198 // 199 //***************************************************************************** 200 #if defined(__GNUC_STDC_INLINE__) 201 void 202 am_reset_isr(void) 203 { 204 // 205 // Set the vector table pointer. 206 // 207 __asm(" ldr r0, =0xE000ED08\n" 208 " ldr r1, =g_am_pfnVectors\n" 209 " str r1, [r0]"); 210 211 // 212 // Set the stack pointer. 213 // 214 __asm(" ldr sp, [r1]"); 215 #ifndef NOFPU 216 // 217 // Enable the FPU. 218 // 219 __asm("ldr r0, =0xE000ED88\n" 220 "ldr r1,[r0]\n" 221 "orr r1,#(0xF << 20)\n" 222 "str r1,[r0]\n" 223 "dsb\n" 224 "isb\n"); 225 #endif 226 // 227 // Copy the data segment initializers from flash to SRAM. 228 // 229 __asm(" ldr r0, =_init_data\n" 230 " ldr r1, =_sdata\n" 231 " ldr r2, =_edata\n" 232 "copy_loop:\n" 233 " ldr r3, [r0], #4\n" 234 " str r3, [r1], #4\n" 235 " cmp r1, r2\n" 236 " blt copy_loop\n"); 237 // 238 // Zero fill the bss segment. 239 // 240 __asm(" ldr r0, =_sbss\n" 241 " ldr r1, =_ebss\n" 242 " mov r2, #0\n" 243 "zero_loop:\n" 244 " cmp r0, r1\n" 245 " it lt\n" 246 " strlt r2, [r0], #4\n" 247 " blt zero_loop"); 248 249 // 250 // Call the application's entry point. 251 // 252 main(); 253 254 // 255 // If main returns then execute a break point instruction 256 // 257 __asm(" bkpt "); 258 } 259 #else 260 #error GNU STDC inline not supported. 261 #endif 262 263 //***************************************************************************** 264 // 265 // This is the code that gets called when the processor receives a NMI. This 266 // simply enters an infinite loop, preserving the system state for examination 267 // by a debugger. 268 // 269 //***************************************************************************** 270 void 271 am_nmi_isr(void) 272 { 273 // 274 // Go into an infinite loop. 275 // 276 while(1) 277 { 278 } 279 } 280 281 //***************************************************************************** 282 // 283 // This is the code that gets called when the processor receives a fault 284 // interrupt. This simply enters an infinite loop, preserving the system state 285 // for examination by a debugger. 286 // 287 //***************************************************************************** 288 void 289 am_fault_isr(void) 290 { 291 // 292 // Go into an infinite loop. 293 // 294 while(1) 295 { 296 } 297 } 298 299 //***************************************************************************** 300 // 301 // This is the code that gets called when the processor receives an unexpected 302 // interrupt. This simply enters an infinite loop, preserving the system state 303 // for examination by a debugger. 304 // 305 //***************************************************************************** 306 void 307 am_default_isr(void) 308 { 309 // 310 // Go into an infinite loop. 311 // 312 while(1) 313 { 314 } 315 } 316 317