cortex.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. /*
  2. * cortex.c
  3. *
  4. * STM32 ARM Cortex management.
  5. *
  6. * Written & released by Keir Fraser <keir.xen@gmail.com>
  7. *
  8. * This is free and unencumbered software released into the public domain.
  9. * See the file COPYING for more details, or visit <http://unlicense.org>.
  10. */
  11. struct extra_exception_frame {
  12. uint32_t r4, r5, r6, r7, r8, r9, r10, r11, lr;
  13. };
  14. void EXC_unexpected(struct extra_exception_frame *extra)
  15. {
  16. struct exception_frame *frame;
  17. uint8_t exc = (uint8_t)read_special(psr);
  18. uint32_t msp, psp;
  19. if (extra->lr & 4) {
  20. frame = (struct exception_frame *)read_special(psp);
  21. psp = (uint32_t)(frame + 1);
  22. msp = (uint32_t)(extra + 1);
  23. } else {
  24. frame = (struct exception_frame *)(extra + 1);
  25. psp = read_special(psp);
  26. msp = (uint32_t)(frame + 1);
  27. }
  28. printk("Unexpected %s #%u at PC=%08x (%s):\n",
  29. (exc < 16) ? "Exception" : "IRQ",
  30. (exc < 16) ? exc : exc - 16,
  31. frame->pc, (extra->lr & 8) ? "Thread" : "Handler");
  32. printk(" r0: %08x r1: %08x r2: %08x r3: %08x\n",
  33. frame->r0, frame->r1, frame->r2, frame->r3);
  34. printk(" r4: %08x r5: %08x r6: %08x r7: %08x\n",
  35. extra->r4, extra->r5, extra->r6, extra->r7);
  36. printk(" r8: %08x r9: %08x r10: %08x r11: %08x\n",
  37. extra->r8, extra->r9, extra->r10, extra->r11);
  38. printk(" r12: %08x sp: %08x lr: %08x pc: %08x\n",
  39. frame->r12, (extra->lr & 4) ? psp : msp, frame->lr, frame->pc);
  40. printk(" msp: %08x psp: %08x psr: %08x\n",
  41. msp, psp, frame->psr);
  42. system_reset();
  43. }
  44. static void exception_init(void)
  45. {
  46. /* Initialise and switch to Process SP. Explicit asm as must be
  47. * atomic wrt updates to SP. We can't guarantee that in C. */
  48. asm volatile (
  49. " mrs r1,msp \n"
  50. " msr psp,r1 \n" /* Set up Process SP */
  51. " movs r1,%0 \n"
  52. " msr control,r1 \n" /* Switch to Process SP */
  53. " isb \n" /* Flush the pipeline */
  54. :: "i" (CONTROL_SPSEL) : "r1" );
  55. /* Set up Main SP for IRQ/Exception context. */
  56. write_special(msp, _irq_stacktop);
  57. /* Initialise interrupts and exceptions. */
  58. scb->vtor = (uint32_t)(unsigned long)vector_table;
  59. scb->ccr |= SCB_CCR_STKALIGN | SCB_CCR_DIV_0_TRP;
  60. /* GCC inlines memcpy() using full-word load/store regardless of buffer
  61. * alignment. Hence it is unsafe to trap on unaligned accesses. */
  62. /*scb->ccr |= SCB_CCR_UNALIGN_TRP;*/
  63. scb->shcsr |= (SCB_SHCSR_USGFAULTENA |
  64. SCB_SHCSR_BUSFAULTENA |
  65. SCB_SHCSR_MEMFAULTENA);
  66. /* SVCall/PendSV exceptions have lowest priority. */
  67. scb->shpr2 = 0xff<<24;
  68. scb->shpr3 = 0xff<<16;
  69. }
  70. static void sysclk_init(void)
  71. {
  72. /* Enable SysTick counter. */
  73. stk->load = STK_MASK;
  74. stk->ctrl = STK_CTRL_ENABLE;
  75. }
  76. void cortex_init(void)
  77. {
  78. exception_init();
  79. cpu_sync();
  80. sysclk_init();
  81. }
  82. void delay_ticks(unsigned int ticks)
  83. {
  84. unsigned int diff, cur, prev = stk->val;
  85. for (;;) {
  86. cur = stk->val;
  87. diff = (prev - cur) & STK_MASK;
  88. if (ticks <= diff)
  89. break;
  90. ticks -= diff;
  91. prev = cur;
  92. }
  93. }
  94. void delay_ns(unsigned int ns)
  95. {
  96. delay_ticks((ns * STK_MHZ) / 1000u);
  97. }
  98. void delay_us(unsigned int us)
  99. {
  100. delay_ticks(us * STK_MHZ);
  101. }
  102. void delay_ms(unsigned int ms)
  103. {
  104. delay_ticks(ms * 1000u * STK_MHZ);
  105. }
  106. void system_reset(void)
  107. {
  108. IRQ_global_disable();
  109. printk("Resetting...\n");
  110. /* Request reset and loop waiting for it to happen. */
  111. cpu_sync();
  112. scb->aircr = SCB_AIRCR_VECTKEY | SCB_AIRCR_SYSRESETREQ;
  113. for (;;) ;
  114. }
  115. #if defined(CORTEX_M7)
  116. void icache_invalidate_all(void)
  117. {
  118. cpu_sync();
  119. cache->iciallu = 0;
  120. cpu_sync();
  121. }
  122. void icache_enable(void)
  123. {
  124. icache_invalidate_all();
  125. scb->ccr |= SCB_CCR_IC;
  126. cpu_sync();
  127. }
  128. static void _dcache_op_all(volatile uint32_t *opreg)
  129. {
  130. uint32_t ccsidr;
  131. unsigned int sets, ways;
  132. cpufeat->csselr = 0; /* L1 DCache */
  133. cpu_sync();
  134. ccsidr = cpufeat->ccsidr;
  135. sets = CCSIDR_SETS(ccsidr);
  136. do {
  137. ways = CCSIDR_WAYS(ccsidr);
  138. do {
  139. *opreg = DCISW_SET(sets) | DCISW_WAY(ways);
  140. } while (ways--);
  141. } while (sets--);
  142. cpu_sync();
  143. }
  144. void dcache_invalidate_all(void)
  145. {
  146. _dcache_op_all(&cache->dcisw);
  147. }
  148. void dcache_clear_and_invalidate_all(void)
  149. {
  150. _dcache_op_all(&cache->dccisw);
  151. }
  152. void dcache_enable(void)
  153. {
  154. dcache_invalidate_all();
  155. scb->ccr |= SCB_CCR_DC;
  156. cpu_sync();
  157. }
  158. void dcache_disable(void)
  159. {
  160. scb->ccr &= ~SCB_CCR_DC;
  161. cpu_sync();
  162. dcache_clear_and_invalidate_all();
  163. }
  164. #endif
  165. /*
  166. * Local variables:
  167. * mode: C
  168. * c-file-style: "Linux"
  169. * c-basic-offset: 4
  170. * tab-width: 4
  171. * indent-tabs-mode: nil
  172. * End:
  173. */