startup_rp2040.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. // SPDX-License-Identifier: BSD-3-Clause
  2. // Copyright (c) 2021, Alex Taradov <alex@taradov.com>. All rights reserved.
  3. //-----------------------------------------------------------------------------
  4. #include <stdint.h>
  5. #include "rp2040.h"
  6. //-----------------------------------------------------------------------------
  7. #define DUMMY __attribute__ ((weak, alias ("irq_handler_dummy")))
  8. //-----------------------------------------------------------------------------
  9. DUMMY void irq_handler_nmi(void);
  10. DUMMY void irq_handler_hard_fault(void);
  11. DUMMY void irq_handler_sv_call(void);
  12. DUMMY void irq_handler_pend_sv(void);
  13. DUMMY void irq_handler_sys_tick(void);
  14. DUMMY void irq_handler_timer_0(void);
  15. DUMMY void irq_handler_timer_1(void);
  16. DUMMY void irq_handler_timer_2(void);
  17. DUMMY void irq_handler_timer_3(void);
  18. DUMMY void irq_handler_pwm(void);
  19. DUMMY void irq_handler_usbctrl(void);
  20. DUMMY void irq_handler_xip(void);
  21. DUMMY void irq_handler_pio0_0(void);
  22. DUMMY void irq_handler_pio0_1(void);
  23. DUMMY void irq_handler_pio1_0(void);
  24. DUMMY void irq_handler_pio1_1(void);
  25. DUMMY void irq_handler_dma_0(void);
  26. DUMMY void irq_handler_dma_1(void);
  27. DUMMY void irq_handler_io_bank0(void);
  28. DUMMY void irq_handler_io_qspi(void);
  29. DUMMY void irq_handler_sio_proc0(void);
  30. DUMMY void irq_handler_sio_proc1(void);
  31. DUMMY void irq_handler_clocks(void);
  32. DUMMY void irq_handler_spi0(void);
  33. DUMMY void irq_handler_spi1(void);
  34. DUMMY void irq_handler_uart0(void);
  35. DUMMY void irq_handler_uart1(void);
  36. DUMMY void irq_handler_adc_fifo(void);
  37. DUMMY void irq_handler_i2c0(void);
  38. DUMMY void irq_handler_i2c1(void);
  39. DUMMY void irq_handler_rtc(void);
  40. extern int main(void);
  41. extern uint32_t _text_start;
  42. extern uint32_t _stack_top;
  43. extern uint32_t _text;
  44. extern uint32_t _etext;
  45. extern uint32_t _data;
  46. extern uint32_t _edata;
  47. extern uint32_t _bss;
  48. extern uint32_t _ebss;
  49. //-----------------------------------------------------------------------------
  50. // Note: Vector table does not need to be placed in a separate section on this MCU,
  51. // but we do so anyway to ensure alignment at 128 byte boundary without
  52. // potentially wasting space with automatic alignment.
  53. __attribute__ ((used, section(".vectors")))
  54. void (* const vectors[])(void) =
  55. {
  56. 0, // 0 - Initial Stack Pointer Value (unused)
  57. // Cortex-M0+ handlers
  58. 0, // 1 - Reset (unused)
  59. irq_handler_nmi, // 2 - NMI
  60. irq_handler_hard_fault, // 3 - Hard Fault
  61. 0, // 4 - Reserved
  62. 0, // 5 - Reserved
  63. 0, // 6 - Reserved
  64. 0, // 7 - Reserved
  65. 0, // 8 - Reserved
  66. 0, // 9 - Reserved
  67. 0, // 10 - Reserved
  68. irq_handler_sv_call, // 11 - SVCall
  69. 0, // 12 - Reserved
  70. 0, // 13 - Reserved
  71. irq_handler_pend_sv, // 14 - PendSV
  72. irq_handler_sys_tick, // 15 - SysTick
  73. // Peripheral handlers
  74. irq_handler_timer_0, // 0 - timer_irq_0
  75. irq_handler_timer_1, // 1 - timer_irq_1
  76. irq_handler_timer_2, // 2 - timer_irq_2
  77. irq_handler_timer_3, // 3 - timer_irq_3
  78. irq_handler_pwm, // 4 - pwm_irq_wrap
  79. irq_handler_usbctrl, // 5 - usbctrl_irq
  80. irq_handler_xip, // 6 - xip_irq
  81. irq_handler_pio0_0, // 7 - pio0_irq_0
  82. irq_handler_pio0_1, // 8 - pio0_irq_1
  83. irq_handler_pio1_0, // 9 - pio1_irq_0
  84. irq_handler_pio1_1, // 10 - pio1_irq_1
  85. irq_handler_dma_0, // 11 - dma_irq_0
  86. irq_handler_dma_1, // 12 - dma_irq_1
  87. irq_handler_io_bank0, // 13 - io_irq_bank0
  88. irq_handler_io_qspi, // 14 - io_irq_qspi
  89. irq_handler_sio_proc0, // 15 - sio_irq_proc0
  90. irq_handler_sio_proc1, // 16 - sio_irq_proc1
  91. irq_handler_clocks, // 17 - clocks_irq
  92. irq_handler_spi0, // 18 - spi0_irq
  93. irq_handler_spi1, // 19 - spi1_irq
  94. irq_handler_uart0, // 20 - uart0_irq
  95. irq_handler_uart1, // 21 - uart1_irq
  96. irq_handler_adc_fifo, // 22 - adc_irq_fifo
  97. irq_handler_i2c0, // 23 - i2c0_irq
  98. irq_handler_i2c1, // 24 - i2c1_irq
  99. irq_handler_rtc, // 25 - rtc_irq
  100. };
  101. //-----------------------------------------------------------------------------
  102. void irq_handler_dummy(void)
  103. {
  104. while (1);
  105. }
  106. //-----------------------------------------------------------------------------
  107. __attribute__((naked, used, noreturn, section(".boot.entry"))) void boot_entry(void)
  108. {
  109. // Note: This code must be position independent, it is linked at 0x10000000, but
  110. // loaded at 0x20041f00.
  111. XIP_SSI->SSIENR = 0;
  112. XIP_SSI->BAUDR = 2; // Must be even
  113. // Read unique ID
  114. XIP_SSI->RX_SAMPLE_DLY = (1 << XIP_SSI_RX_SAMPLE_DLY_RSD_Pos);
  115. XIP_SSI->CTRLR0 = (XIP_SSI_CTRLR0_SPI_FRF_STD << XIP_SSI_CTRLR0_SPI_FRF_Pos) |
  116. (XIP_SSI_CTRLR0_TMOD_TX_AND_RX << XIP_SSI_CTRLR0_TMOD_Pos) |
  117. ((32-1) << XIP_SSI_CTRLR0_DFS_32_Pos);
  118. XIP_SSI->SSIENR = XIP_SSI_SSIENR_SSI_EN_Msk;
  119. XIP_SSI->DR0 = 0x4b000000/*RUID*/;
  120. XIP_SSI->DR0 = 0;
  121. XIP_SSI->DR0 = 0;
  122. XIP_SSI->DR0 = 0;
  123. XIP_SSI->DR0 = 0;
  124. XIP_SSI->DR0 = 0;
  125. while (1)
  126. {
  127. int sr = XIP_SSI->SR;
  128. if ((sr & XIP_SSI_SR_TFE_Msk) && (0 == (sr & XIP_SSI_SR_BUSY_Msk)))
  129. break;
  130. }
  131. (void)XIP_SSI->DR0;
  132. // UID is placed at the same address as this boot sector
  133. volatile uint32_t *uid = (volatile uint32_t *)0x20041f00;
  134. uid[0] = XIP_SSI->DR0;
  135. uid[1] = XIP_SSI->DR0;
  136. uid[2] = XIP_SSI->DR0;
  137. uid[3] = XIP_SSI->DR0;
  138. uid[4] = XIP_SSI->DR0;
  139. XIP_SSI->SSIENR = 0;
  140. // Setup for XIP
  141. XIP_SSI->CTRLR0 = (XIP_SSI_CTRLR0_SPI_FRF_STD << XIP_SSI_CTRLR0_SPI_FRF_Pos) |
  142. (XIP_SSI_CTRLR0_TMOD_EEPROM_READ << XIP_SSI_CTRLR0_TMOD_Pos) |
  143. ((32-1) << XIP_SSI_CTRLR0_DFS_32_Pos);
  144. XIP_SSI->CTRLR1 = (0 << XIP_SSI_CTRLR1_NDF_Pos);
  145. XIP_SSI->SPI_CTRLR0 = (0x03/*READ_DATA*/ << XIP_SSI_SPI_CTRLR0_XIP_CMD_Pos) |
  146. ((24 / 4) << XIP_SSI_SPI_CTRLR0_ADDR_L_Pos) |
  147. (XIP_SSI_SPI_CTRLR0_INST_L_8B << XIP_SSI_SPI_CTRLR0_INST_L_Pos) |
  148. (XIP_SSI_SPI_CTRLR0_TRANS_TYPE_1C1A << XIP_SSI_SPI_CTRLR0_TRANS_TYPE_Pos);
  149. XIP_SSI->SSIENR = XIP_SSI_SSIENR_SSI_EN_Msk;
  150. uint32_t *src = &_text_start;
  151. uint32_t *dst = &_text;
  152. while (dst < &_edata)
  153. *dst++ = *src++;
  154. dst = &_bss;
  155. while (dst < &_ebss)
  156. *dst++ = 0;
  157. SCB->VTOR = (uint32_t)vectors;
  158. asm (R"asm(
  159. msr msp, %[sp]
  160. bx %[reset]
  161. )asm"
  162. :: [sp] "r" (&_stack_top), [reset] "r" (main)
  163. );
  164. __builtin_unreachable();
  165. }