cortex_init.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497
  1. /*
  2. * Copyright (C) 2010 by Ulrich Prinz (uprinz2@netscape.net)
  3. * Copyright (C) 2012 by Ole Reinhardt <ole.reinhardt@embedded-it.de>
  4. *
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. *
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * 2. Redistributions in binary form must reproduce the above copyright
  14. * notice, this list of conditions and the following disclaimer in the
  15. * documentation and/or other materials provided with the distribution.
  16. * 3. Neither the name of the copyright holders nor the names of
  17. * contributors may be used to endorse or promote products derived
  18. * from this software without specific prior written permission.
  19. *
  20. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  21. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  22. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  23. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  24. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  25. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  26. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  27. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  28. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  29. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  30. * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31. * SUCH DAMAGE.
  32. *
  33. * For additional information see http://www.ethernut.de/
  34. */
  35. /*
  36. * \verbatim
  37. * $Id: cortex_init.c 5684 2014-05-01 18:34:40Z olereinhardt $
  38. * \endverbatim
  39. */
  40. #include <string.h>
  41. #include <cfg/os.h>
  42. #include <cfg/clock.h>
  43. #include <cfg/arch.h>
  44. #include <cfg/memory.h>
  45. #include <cfg/cortex_debug.h>
  46. #include <arch/cm3.h>
  47. #include <arch/cm3/cortex_debug.h>
  48. #include <dev/rtc.h>
  49. #include <sys/heap.h>
  50. #include <sys/nutdebug.h>
  51. #include <sys/atom.h>
  52. #ifndef MSP_STACK_SIZE
  53. #define MSP_STACK_SIZE 128
  54. #endif
  55. #ifndef PSP_STACK_SIZE
  56. #define PSP_STACK_SIZE 32
  57. #endif
  58. #ifndef NUT_BOOT_FUNCTION
  59. #define NUT_BOOT_FUNCTION NutInit
  60. #endif
  61. extern void NUT_BOOT_FUNCTION(void *);
  62. /*!
  63. * \brief CortexM3 MSP processor stack.
  64. */
  65. __attribute__ ((section(".stack")))
  66. volatile static uint32_t mspStack[MSP_STACK_SIZE];
  67. /*!
  68. * \brief CortexM3 PSP processor stack.
  69. */
  70. __attribute__ ((section(".psp_stack")))
  71. volatile static uint32_t pspStack[PSP_STACK_SIZE];
  72. /*
  73. * Get the appropriate stack pointer, depending on our mode,
  74. * and use it as the parameter to the C handler. This function
  75. * will never return
  76. *
  77. * Pass reason to R1 */
  78. #define JUMP_REGDUMP(reason) \
  79. __asm__ __volatile__ ( \
  80. "@ JUMP_REGDUMP\n\t" \
  81. "MOV R1, #4 \n\t" \
  82. "MOV R0, LR \n\t" \
  83. "TST R0, R1 \n\t" \
  84. "BEQ 1f \n\t" \
  85. "MRS R0, PSP \n\t" \
  86. "B 2f \n\t" \
  87. "1: \n\t" \
  88. "MRS R0, MSP \n\t" \
  89. "2: \n\t" \
  90. "MOV R1, %0; \n\t" \
  91. "MOV R2, R7 \n\t" \
  92. "B CortexRegDump \n\t" \
  93. ::"g" (reason))
  94. static void IntDefaultHandler(void *arg) __attribute__ ((naked));
  95. static void IntNmiHandler(void *arg) __attribute__ ((naked));
  96. static void IntHardfaultHandler(void *arg) __attribute__ ((naked));
  97. static void IntMemfaultHandler(void *arg) __attribute__ ((naked));
  98. /*!
  99. * \brief CortexM3 memory pointers
  100. *
  101. * These pointers are provided by the linker, controlled by the
  102. * linker script. The list is shrinked to the two basic
  103. * entries of the initial stack pointer address and the
  104. * reset vector. All other interrupt vectors are set up dynamically
  105. * later after system start.
  106. */
  107. #if (__CORTEX_M >= 0x03)
  108. static void IntBusfaultHandler(void *arg) __attribute__ ((naked));
  109. static void IntUsagefaultHandler(void *arg) __attribute__ ((naked));
  110. __attribute__ ((section(".isr_vector")))
  111. #if defined(NUTDEBUG_RAM)
  112. void (* g_pfnVectors[NUM_INTERRUPTS])(void*) =
  113. #else
  114. void (* const g_pfnVectors[])(void *) =
  115. #endif
  116. {
  117. (void (*)(void *))((uint32_t)mspStack + sizeof(mspStack)), /* Initial Stack Pointer */
  118. NUT_BOOT_FUNCTION, /* Reset_Handler */
  119. IntNmiHandler, /* NMI_Handler */
  120. IntHardfaultHandler, /* HardFault_Handler */
  121. IntMemfaultHandler, /* MemManage_Handler */
  122. IntBusfaultHandler, /* BusFault_Handler */
  123. IntUsagefaultHandler,/* UsageFault_Handler */
  124. 0, /* Reserved */
  125. 0, /* Reserved */
  126. 0, /* Reserved */
  127. 0, /* Reserved */
  128. };
  129. #else
  130. static void IntRedirect(void *arg);
  131. __attribute__ ((section(".isr_vector")))
  132. void (* const g_pfnVectors[])(void *) =
  133. {
  134. (void (*)(void *))((uint32_t)mspStack + sizeof(mspStack)), /* Initial Stack Pointer */
  135. NUT_BOOT_FUNCTION, /* Reset_Handler */
  136. IntNmiHandler, /* NMI_Handler */
  137. IntHardfaultHandler, /* HardFault_Handler */
  138. IntMemfaultHandler, /* MemManage_Handler */
  139. 0, /* Reserved */
  140. 0, /* Reserved */
  141. 0, /* Reserved */
  142. 0, /* Reserved */
  143. 0, /* Reserved */
  144. 0, /* Reserved */
  145. 0, /* Reserved */
  146. IntRedirect, /* SVCAall*/
  147. 0, /* Reserved */
  148. 0, /* Reserved */
  149. IntRedirect, /* PendSV*/
  150. IntRedirect, /* SysTick*/
  151. IntRedirect, /* IRQn 0*/
  152. IntRedirect, /* IRQn 1*/
  153. IntRedirect, /* IRQn 2*/
  154. IntRedirect, /* IRQn 3*/
  155. IntRedirect, /* IRQn 4*/
  156. IntRedirect, /* IRQn 5*/
  157. IntRedirect, /* IRQn 6*/
  158. IntRedirect, /* IRQn 7*/
  159. IntRedirect, /* IRQn 8*/
  160. IntRedirect, /* IRQn 9*/
  161. IntRedirect, /* IRQn 10*/
  162. IntRedirect, /* IRQn 11*/
  163. IntRedirect, /* IRQn 12*/
  164. IntRedirect, /* IRQn 13*/
  165. IntRedirect, /* IRQn 14*/
  166. IntRedirect, /* IRQn 15*/
  167. IntRedirect, /* IRQn 16*/
  168. IntRedirect, /* IRQn 17*/
  169. IntRedirect, /* IRQn 18*/
  170. IntRedirect, /* IRQn 19*/
  171. IntRedirect, /* IRQn 20*/
  172. IntRedirect, /* IRQn 21*/
  173. IntRedirect, /* IRQn 22*/
  174. IntRedirect, /* IRQn 23*/
  175. IntRedirect, /* IRQn 24*/
  176. IntRedirect, /* IRQn 25*/
  177. IntRedirect, /* IRQn 26*/
  178. IntRedirect, /* IRQn 27*/
  179. IntRedirect, /* IRQn 28*/
  180. IntRedirect, /* IRQn 29*/
  181. IntRedirect, /* IRQn 30*/
  182. IntRedirect, /* IRQn 31*/
  183. };
  184. #endif
  185. /*!
  186. * \brief Dynamic interrupt vector table in RAM
  187. *
  188. * Copy of the interrupt vector table in RAM. The vector table layout is
  189. * defined by the hardware. The list CM3 CPUs can handle a maximum of 256
  190. * interrupt vectors. The maximum number of handlers used by a specific CPU
  191. * implementation is defined in NUM_INTERRUPTS which should be defined in each
  192. * CPU header as the last entry in IRQn_Type enum.
  193. */
  194. #if defined(NUTDEBUG_RAM)
  195. /* Code is just running in RAM, so re-use the g_pfnVectors */
  196. #define g_pfnRAMVectors g_pfnVectors
  197. #else
  198. static __attribute__((section(".vtable")))
  199. void (*g_pfnRAMVectors[NUM_INTERRUPTS])(void*);
  200. #endif
  201. /*!
  202. * \brief CortexM3 memory pointers
  203. *
  204. * These pointers are provided by the linker, controlled by the
  205. * linker script.
  206. */
  207. extern void * _etext; /* Start of constants in FLASH */
  208. extern void * _sidata; /* Start of variables in FLASH */
  209. extern void * _sdata; /* Start of variables in RAM */
  210. extern void * _edata; /* End of variables in RAM */
  211. extern void * _sbss; /* Start of unset variables in RAM */
  212. extern void * _ebss; /* End of unset variables in RAM */
  213. /* Remember: following stack grow from end address to start */
  214. extern void * _pspstack_start; /* Process stack start address */
  215. extern void * _pspstack_end; /* Process stack end address */
  216. extern void * _stack_start; /* Main stack start address */
  217. extern void * _stack_end; /* Main stack end address */
  218. /* Default interrupt handler */
  219. static void IntDefaultHandler(void *arg)
  220. {
  221. #ifdef DEBUG_MACRO
  222. /* 'DEFAULT_HANDLER' to R1.
  223. * Will be the second parameter (Exception type) to RegDump.
  224. */
  225. JUMP_REGDUMP(0);
  226. #else
  227. __asm("BKPT #0\n") ; // Break into the debugger
  228. while(1);
  229. #endif
  230. }
  231. /* Below the default exception handler follow */
  232. /*!
  233. * \brief Non mascable interrupt handler
  234. */
  235. static void IntNmiHandler(void *arg)
  236. {
  237. #ifdef DEBUG_MACRO
  238. /* Pass 'NMI_HANDLER' to R1.
  239. * Will be the second parameter (Exception type) to RegDump.
  240. */
  241. JUMP_REGDUMP(1);
  242. #else
  243. __asm("BKPT #0\n") ; // Break into the debugger
  244. while(1);
  245. #endif
  246. }
  247. /*!
  248. * \brief Hard fault handler
  249. */
  250. static void IntHardfaultHandler(void *arg)
  251. {
  252. #ifdef DEBUG_MACRO
  253. /* Pass 'HARDFAULLT_HANDLER' to R1.
  254. * Will be the second parameter (Exception type) to RegDump.
  255. */
  256. JUMP_REGDUMP(2);
  257. #else
  258. __asm("BKPT #0\n") ; // Break into the debugger
  259. while(1);
  260. #endif
  261. }
  262. /*!
  263. * \brief Mem fault handler
  264. */
  265. static void IntMemfaultHandler(void *arg)
  266. {
  267. #ifdef DEBUG_MACRO
  268. /*
  269. * Pass 'MEMFAULT_HANDLER' to R1.
  270. * Will be the second parameter (Exception type) to RegDumpGet.
  271. */
  272. JUMP_REGDUMP(3);
  273. #else
  274. __asm("BKPT #0\n") ; // Break into the debugger
  275. while(1);
  276. #endif
  277. }
  278. #if (__CORTEX_M >= 0x03)
  279. /*!
  280. * \brief Bus fault handler
  281. */
  282. void IntBusfaultHandler(void *arg)
  283. {
  284. #ifdef DEBUG_MACRO
  285. /*
  286. * Pass 'BUSFAULT_HANDLER' to R1.
  287. * Will be the second parameter (Exception type) to RegDump
  288. */
  289. JUMP_REGDUMP(4);
  290. #else
  291. __asm("BKPT #0\n") ; // Break into the debugger
  292. while(1);
  293. #endif
  294. }
  295. /*!
  296. * \brief Usage fault handler
  297. */
  298. static void IntUsagefaultHandler(void *arg)
  299. {
  300. #ifdef DEBUG_MACRO
  301. /*
  302. * Pass 'USAGEFAULT_HANDLER' to R1.
  303. * Will be the second parameter Exception type) to RegDump
  304. */
  305. JUMP_REGDUMP(5);
  306. #else
  307. __asm("BKPT #0\n") ; // Break into the debugger
  308. while(1);
  309. #endif
  310. }
  311. #endif
  312. /*!
  313. * \brief Register interrupt handler in RAM vector table
  314. *
  315. * \param int_id Specifies interrupt ID to register
  316. *
  317. * \param pfnHandler Interrupt handler function to be called
  318. */
  319. void Cortex_RegisterInt(IRQn_Type int_id, void (*pfnHandler)(void*))
  320. {
  321. uint16_t idx = int_id + 16;
  322. /* Check for valid interrupt number */
  323. NUTASSERT(idx < NUM_INTERRUPTS);
  324. #if (__CORTEX_M >= 0x03)
  325. /* Make sure that the RAM vector table is correctly aligned. */
  326. NUTASSERT(((uint32_t)g_pfnRAMVectors & 0x000003ff) == 0);
  327. #endif
  328. if (pfnHandler != NULL) {
  329. /* Save the interrupt handler. */
  330. g_pfnRAMVectors[idx] = pfnHandler;
  331. } else {
  332. /* Reset to default interrupt handler */
  333. g_pfnRAMVectors[idx] = &IntDefaultHandler;
  334. }
  335. }
  336. /*!
  337. * \brief CortexM3 Initialization.
  338. *
  339. * This function copies over the data segment from flash to ram
  340. * and fills the bss segment with 0.
  341. */
  342. static void Cortex_MemInit(void)
  343. {
  344. register uint32_t *src, *dst, *end;
  345. register uint32_t fill = 0;
  346. /*
  347. * Plain C-Code Cortex Init
  348. */
  349. /* Copy the data segment initializers from flash to SRAM. */
  350. src = (uint32_t*)&_etext;
  351. end = (uint32_t*)&_edata;
  352. for( dst = (uint32_t*)&_sdata; dst < end;)
  353. {
  354. *dst++ = *src++;
  355. }
  356. /* Fill the bss segment with 0x00 */
  357. end = (uint32_t*)&_ebss;
  358. for( dst = (uint32_t*)&_sbss; dst < end; )
  359. {
  360. *dst++ = fill;
  361. }
  362. __set_PSP((uint32_t)&_pspstack_end);
  363. }
  364. #if (__CORTEX_M >= 0x03)
  365. static void Cortex_IntInit(void)
  366. {
  367. int int_id;
  368. /* Disable exceptions */
  369. SCB->SHCSR &= ~(SCB_SHCSR_USGFAULTENA_Msk |
  370. SCB_SHCSR_BUSFAULTENA_Msk |
  371. SCB_SHCSR_MEMFAULTENA_Msk);
  372. /* Disable SysTick interrupt */
  373. SysTick->CTRL &= ~SysTick_CTRL_TICKINT_Msk;
  374. #ifndef NUTDEBUG_RAM
  375. /* Copy Reset vector to RAM vector table */
  376. g_pfnRAMVectors[0] = (void(*)(void*))g_pfnVectors[0];
  377. /* Copy Stackpointer to RAM vector table */
  378. g_pfnRAMVectors[1] = (void(*)(void*))g_pfnVectors[1];
  379. #endif
  380. /* Set the exception handler */
  381. g_pfnRAMVectors[2] = &IntNmiHandler;
  382. g_pfnRAMVectors[3] = &IntHardfaultHandler;
  383. g_pfnRAMVectors[4] = &IntMemfaultHandler;
  384. g_pfnRAMVectors[5] = &IntBusfaultHandler;
  385. g_pfnRAMVectors[6] = &IntUsagefaultHandler;
  386. /* Init reserved vectors with NULL */
  387. g_pfnRAMVectors[7] = NULL;
  388. g_pfnRAMVectors[8] = NULL;
  389. g_pfnRAMVectors[9] = NULL;
  390. g_pfnRAMVectors[10] = NULL;
  391. g_pfnRAMVectors[12] = NULL;
  392. g_pfnRAMVectors[13] = NULL;
  393. /* Init all other exception handler and system interrupts with the
  394. default handler
  395. */
  396. g_pfnRAMVectors[10] = &IntDefaultHandler;
  397. g_pfnRAMVectors[11] = &IntDefaultHandler;
  398. g_pfnRAMVectors[14] = &IntDefaultHandler;
  399. g_pfnRAMVectors[15] = &IntDefaultHandler;
  400. /* Enable exceptions again. The NMI and Hard-Fault handler are always enabled */
  401. SCB->SHCSR |= SCB_SHCSR_USGFAULTENA_Msk |
  402. SCB_SHCSR_BUSFAULTENA_Msk |
  403. SCB_SHCSR_MEMFAULTENA_Msk;
  404. for (int_id = 16; int_id < NUM_INTERRUPTS - 16; int_id ++) {
  405. /* Make sure the interrupt is disabled */
  406. NVIC_DisableIRQ(int_id);
  407. g_pfnRAMVectors[int_id] = &IntDefaultHandler;
  408. }
  409. /* Basic interrupt system setup */
  410. //SCB->AIRCR = (0x05fa0000|SCB_AIRCR_PRIGROUP0);
  411. /* Clear pending bits for SysTick interrupt, PendSV exception and ISRs */
  412. SCB->ICSR |= (SCB_ICSR_PENDSTCLR_Msk | SCB_ICSR_PENDSVCLR_Msk | SCB_ICSR_ISRPENDING_Msk);
  413. /* Point NVIC at the RAM vector table. */
  414. SCB->VTOR = (uint32_t)g_pfnRAMVectors;
  415. __enable_fault_irq();
  416. __enable_irq();
  417. }
  418. #else
  419. /*!
  420. * \brief Usage fault handler
  421. */
  422. static void IntRedirect(void *arg)
  423. {
  424. int int_id = SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk;
  425. if (g_pfnRAMVectors[int_id])
  426. g_pfnRAMVectors[int_id](NULL);
  427. }
  428. static void Cortex_IntInit(void)
  429. {
  430. __disable_irq();
  431. memset (g_pfnRAMVectors, 0, sizeof(g_pfnRAMVectors));
  432. /* Clear pending bits for SysTick interrupt, PendSV exception and ISRs */
  433. SCB->ICSR |= (SCB_ICSR_PENDSTCLR_Msk | SCB_ICSR_PENDSVCLR_Msk | SCB_ICSR_ISRPENDING_Msk);
  434. __enable_irq();
  435. }
  436. #endif
  437. /*!
  438. * \brief CortexM3 Startup.
  439. *
  440. * This function runs the basic cpu initialization.
  441. */
  442. void Cortex_Start(void)
  443. {
  444. Cortex_MemInit();
  445. Cortex_IntInit();
  446. }