stm32f10x.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. /*
  2. * stm32f10x.c
  3. *
  4. * Core and peripheral registers.
  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 clock_init(void)
  71. {
  72. /* Flash controller: reads require 2 wait states at 72MHz. */
  73. flash->acr = FLASH_ACR_PRFTBE | FLASH_ACR_LATENCY(2);
  74. /* Start up the external oscillator. */
  75. rcc->cr |= RCC_CR_HSEON;
  76. while (!(rcc->cr & RCC_CR_HSERDY))
  77. cpu_relax();
  78. /* PLLs, scalers, muxes. */
  79. rcc->cfgr = (RCC_CFGR_PLLMUL(9) | /* PLL = 9*8MHz = 72MHz */
  80. RCC_CFGR_PLLSRC_PREDIV1 |
  81. RCC_CFGR_ADCPRE_DIV8 |
  82. RCC_CFGR_PPRE1_DIV2);
  83. /* Enable and stabilise the PLL. */
  84. rcc->cr |= RCC_CR_PLLON;
  85. while (!(rcc->cr & RCC_CR_PLLRDY))
  86. cpu_relax();
  87. /* Switch to the externally-driven PLL for system clock. */
  88. rcc->cfgr |= RCC_CFGR_SW_PLL;
  89. while ((rcc->cfgr & RCC_CFGR_SWS_MASK) != RCC_CFGR_SWS_PLL)
  90. cpu_relax();
  91. /* Internal oscillator no longer needed. */
  92. rcc->cr &= ~RCC_CR_HSION;
  93. /* Enable SysTick counter at 72/8=9MHz. */
  94. stk->load = STK_MASK;
  95. stk->ctrl = STK_CTRL_ENABLE;
  96. }
  97. static void gpio_init(GPIO gpio)
  98. {
  99. /* Floating Input. Reference Manual states that JTAG pins are in PU/PD
  100. * mode at reset, so ensure all PU/PD are disabled. */
  101. gpio->crl = gpio->crh = 0x44444444u;
  102. }
  103. static void peripheral_init(void)
  104. {
  105. /* Enable basic GPIO and AFIO clocks, all timers, and DMA. */
  106. rcc->apb1enr = (RCC_APB1ENR_TIM2EN |
  107. RCC_APB1ENR_TIM3EN |
  108. RCC_APB1ENR_TIM4EN);
  109. rcc->apb2enr = (RCC_APB2ENR_IOPAEN |
  110. RCC_APB2ENR_IOPBEN |
  111. RCC_APB2ENR_IOPCEN |
  112. RCC_APB2ENR_AFIOEN |
  113. RCC_APB2ENR_TIM1EN);
  114. rcc->ahbenr = RCC_AHBENR_DMA1EN;
  115. /* Turn off serial-wire JTAG and reclaim the GPIOs. */
  116. afio->mapr = AFIO_MAPR_SWJ_CFG_DISABLED;
  117. /* All pins in a stable state. */
  118. gpio_init(gpioa);
  119. gpio_init(gpiob);
  120. gpio_init(gpioc);
  121. }
  122. void stm32_init(void)
  123. {
  124. exception_init();
  125. clock_init();
  126. peripheral_init();
  127. cpu_sync();
  128. }
  129. void delay_ticks(unsigned int ticks)
  130. {
  131. unsigned int diff, cur, prev = stk->val;
  132. for (;;) {
  133. cur = stk->val;
  134. diff = (prev - cur) & STK_MASK;
  135. if (ticks <= diff)
  136. break;
  137. ticks -= diff;
  138. prev = cur;
  139. }
  140. }
  141. void delay_ns(unsigned int ns)
  142. {
  143. delay_ticks((ns * STK_MHZ) / 1000u);
  144. }
  145. void delay_us(unsigned int us)
  146. {
  147. delay_ticks(us * STK_MHZ);
  148. }
  149. void delay_ms(unsigned int ms)
  150. {
  151. delay_ticks(ms * 1000u * STK_MHZ);
  152. }
  153. void gpio_configure_pin(GPIO gpio, unsigned int pin, unsigned int mode)
  154. {
  155. gpio_write_pin(gpio, pin, mode >> 4);
  156. mode &= 0xfu;
  157. if (pin >= 8) {
  158. pin -= 8;
  159. gpio->crh = (gpio->crh & ~(0xfu<<(pin<<2))) | (mode<<(pin<<2));
  160. } else {
  161. gpio->crl = (gpio->crl & ~(0xfu<<(pin<<2))) | (mode<<(pin<<2));
  162. }
  163. }
  164. void system_reset(void)
  165. {
  166. console_sync();
  167. printk("Resetting...\n");
  168. /* Wait for serial console TX to idle. */
  169. while (!(usart1->sr & USART_SR_TXE) || !(usart1->sr & USART_SR_TC))
  170. cpu_relax();
  171. /* Request reset and loop waiting for it to happen. */
  172. scb->aircr = SCB_AIRCR_VECTKEY | SCB_AIRCR_SYSRESETREQ;
  173. for (;;) ;
  174. }
  175. /*
  176. * Local variables:
  177. * mode: C
  178. * c-file-style: "Linux"
  179. * c-basic-offset: 4
  180. * tab-width: 4
  181. * indent-tabs-mode: nil
  182. * End:
  183. */