main_f1.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. /*
  2. * STM32F1 board support for the bootloader.
  3. *
  4. */
  5. #include "hw_config.h"
  6. #include <stdlib.h>
  7. #include <libopencm3/stm32/rcc.h>
  8. #include <libopencm3/stm32/f1/bkp.h>
  9. #include <libopencm3/stm32/gpio.h>
  10. #include <libopencm3/stm32/flash.h>
  11. #include <libopencm3/stm32/usart.h>
  12. #include <libopencm3/stm32/pwr.h>
  13. #include <libopencm3/cm3/systick.h>
  14. #include "bl.h"
  15. #define UDID_START 0x1FFFF7E8
  16. // address of MCU IDCODE
  17. #define DBGMCU_IDCODE 0xE0042000
  18. #ifdef INTERFACE_USART
  19. # define BOARD_INTERFACE_CONFIG (void *)BOARD_USART
  20. #else
  21. # define BOARD_INTERFACE_CONFIG NULL
  22. #endif
  23. /* board definition */
  24. struct boardinfo board_info = {
  25. .board_type = BOARD_TYPE,
  26. .board_rev = 0,
  27. .fw_size = APP_SIZE_MAX,
  28. .systick_mhz = OSC_FREQ,
  29. };
  30. static void board_init(void);
  31. uint32_t
  32. board_get_devices(void)
  33. {
  34. return BOOT_DEVICES_SELECTION;
  35. }
  36. static void
  37. board_init(void)
  38. {
  39. /* initialise LEDs */
  40. rcc_peripheral_enable_clock(&BOARD_CLOCK_LEDS_REGISTER, BOARD_CLOCK_LEDS);
  41. gpio_set_mode(BOARD_PORT_LEDS,
  42. GPIO_MODE_OUTPUT_50_MHZ,
  43. GPIO_CNF_OUTPUT_PUSHPULL,
  44. BOARD_PIN_LED_BOOTLOADER | BOARD_PIN_LED_ACTIVITY);
  45. BOARD_LED_ON(
  46. BOARD_PORT_LEDS,
  47. BOARD_PIN_LED_BOOTLOADER | BOARD_PIN_LED_ACTIVITY);
  48. /* if we have one, enable the force-bootloader pin */
  49. #ifdef BOARD_FORCE_BL_PIN
  50. rcc_peripheral_enable_clock(&BOARD_FORCE_BL_CLOCK_REGISTER, BOARD_FORCE_BL_CLOCK_BIT);
  51. gpio_set(BOARD_FORCE_BL_PORT, BOARD_FORCE_BL_PIN);
  52. gpio_set_mode(BOARD_FORCE_BL_PORT,
  53. GPIO_MODE_INPUT,
  54. BOARD_FORCE_BL_PULL,
  55. BOARD_FORCE_BL_PIN);
  56. #endif
  57. /* enable the backup registers */
  58. rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_PWREN | RCC_APB1ENR_BKPEN);
  59. #ifdef INTERFACE_USART
  60. /* configure usart pins */
  61. rcc_peripheral_enable_clock(&BOARD_USART_PIN_CLOCK_REGISTER, BOARD_USART_PIN_CLOCK_BIT);
  62. gpio_set_mode(BOARD_PORT_USART,
  63. GPIO_MODE_OUTPUT_50_MHZ,
  64. GPIO_CNF_OUTPUT_ALTFN_PUSHPULL,
  65. BOARD_PIN_TX);
  66. /* configure USART clock */
  67. rcc_peripheral_enable_clock(&BOARD_USART_CLOCK_REGISTER, BOARD_USART_CLOCK_BIT);
  68. #endif
  69. #ifdef INTERFACE_I2C
  70. # error I2C GPIO config not handled yet
  71. #endif
  72. }
  73. void
  74. board_deinit(void)
  75. {
  76. /* deinitialise LEDs */
  77. gpio_set_mode(BOARD_PORT_LEDS,
  78. GPIO_MODE_INPUT,
  79. GPIO_CNF_INPUT_FLOAT,
  80. BOARD_PIN_LED_BOOTLOADER | BOARD_PIN_LED_ACTIVITY);
  81. /* if we have one, disable the force-bootloader pin */
  82. #ifdef BOARD_FORCE_BL_PIN
  83. gpio_set_mode(BOARD_FORCE_BL_PORT,
  84. GPIO_MODE_INPUT,
  85. GPIO_CNF_INPUT_FLOAT,
  86. BOARD_FORCE_BL_PIN);
  87. gpio_clear(BOARD_FORCE_BL_PORT, BOARD_FORCE_BL_PIN);
  88. #endif
  89. /* disable the backup registers */
  90. rcc_peripheral_disable_clock(&RCC_APB1ENR, RCC_APB1ENR_PWREN | RCC_APB1ENR_BKPEN);
  91. #ifdef INTERFACE_USART
  92. /* configure usart pins */
  93. gpio_set_mode(BOARD_PORT_USART,
  94. GPIO_MODE_INPUT,
  95. GPIO_CNF_INPUT_FLOAT,
  96. BOARD_PIN_TX);
  97. /* disable USART peripheral clock */
  98. rcc_peripheral_disable_clock(&BOARD_USART_CLOCK_REGISTER, BOARD_USART_CLOCK_BIT);
  99. #endif
  100. #ifdef INTERFACE_I2C
  101. # error I2C GPIO config not handled yet
  102. #endif
  103. /* reset the APB2 peripheral clocks */
  104. RCC_APB2ENR = 0x00000000; // XXX Magic reset number from STM32F1x reference manual
  105. }
  106. /**
  107. * @brief Initializes the RCC clock configuration.
  108. *
  109. * @param clock_setup : The clock configuration to set
  110. */
  111. static inline void
  112. clock_init(void)
  113. {
  114. #if defined(INTERFACE_USB)
  115. rcc_clock_setup_in_hsi_out_48mhz();
  116. #else
  117. rcc_clock_setup_in_hsi_out_24mhz();
  118. #endif
  119. }
  120. /**
  121. * @brief Resets the RCC clock configuration to the default reset state.
  122. * @note The default reset state of the clock configuration is given below:
  123. * - HSI ON and used as system clock source
  124. * - HSE, PLL and PLLI2S OFF
  125. * - AHB, APB1 and APB2 prescaler set to 1.
  126. * - CSS, MCO1 and MCO2 OFF
  127. * - All interrupts disabled
  128. * @note This function doesn't modify the configuration of the
  129. * - Peripheral clocks
  130. * - LSI, LSE and RTC clocks
  131. */
  132. void
  133. clock_deinit(void)
  134. {
  135. /* Enable internal high-speed oscillator. */
  136. rcc_osc_on(RCC_HSI);
  137. rcc_wait_for_osc_ready(RCC_HSI);
  138. /* Reset the RCC_CFGR register */
  139. RCC_CFGR = 0x000000;
  140. /* Stop the HSE, CSS, PLL, PLLI2S, PLLSAI */
  141. rcc_osc_off(RCC_HSE);
  142. rcc_osc_off(RCC_PLL);
  143. rcc_css_disable();
  144. /* Reset the HSEBYP bit */
  145. rcc_osc_bypass_disable(RCC_HSE);
  146. /* Reset the CIR register */
  147. RCC_CIR = 0x000000;
  148. }
  149. uint32_t
  150. flash_func_sector_size(unsigned sector)
  151. {
  152. if (sector < BOARD_FLASH_SECTORS) {
  153. return FLASH_SECTOR_SIZE;
  154. }
  155. return 0;
  156. }
  157. void
  158. flash_func_erase_sector(unsigned sector)
  159. {
  160. if (sector < BOARD_FLASH_SECTORS) {
  161. flash_erase_page(APP_LOAD_ADDRESS + (sector * FLASH_SECTOR_SIZE));
  162. }
  163. }
  164. void
  165. flash_func_write_word(uint32_t address, uint32_t word)
  166. {
  167. flash_program_word(address + APP_LOAD_ADDRESS, word);
  168. }
  169. uint32_t
  170. flash_func_read_word(uint32_t address)
  171. {
  172. return *(uint32_t *)(address + APP_LOAD_ADDRESS);
  173. }
  174. uint32_t
  175. flash_func_read_otp(uint32_t address)
  176. {
  177. return 0;
  178. }
  179. uint32_t get_mcu_id(void)
  180. {
  181. return *(uint32_t *)DBGMCU_IDCODE;
  182. }
  183. // See F4 version for future enhancement for full decoding
  184. int get_mcu_desc(int max, uint8_t *revstr)
  185. {
  186. const char none[] = "STM32F1xxx,?";
  187. int i;
  188. for (i = 0; none[i] && i < max - 1; i++) {
  189. revstr[i] = none[i];
  190. }
  191. return i;
  192. }
  193. int check_silicon(void)
  194. {
  195. return 0;
  196. }
  197. uint32_t
  198. flash_func_read_sn(uint32_t address)
  199. {
  200. // read a byte out from unique chip ID area
  201. // it's 12 bytes, or 3 words.
  202. return *(uint32_t *)(address + UDID_START);
  203. }
  204. void
  205. led_on(unsigned led)
  206. {
  207. switch (led) {
  208. case LED_ACTIVITY:
  209. BOARD_LED_ON(BOARD_PORT_LEDS, BOARD_PIN_LED_ACTIVITY);
  210. break;
  211. case LED_BOOTLOADER:
  212. BOARD_LED_ON(BOARD_PORT_LEDS, BOARD_PIN_LED_BOOTLOADER);
  213. break;
  214. }
  215. }
  216. void
  217. led_off(unsigned led)
  218. {
  219. switch (led) {
  220. case LED_ACTIVITY:
  221. BOARD_LED_OFF(BOARD_PORT_LEDS, BOARD_PIN_LED_ACTIVITY);
  222. break;
  223. case LED_BOOTLOADER:
  224. BOARD_LED_OFF(BOARD_PORT_LEDS, BOARD_PIN_LED_BOOTLOADER);
  225. break;
  226. }
  227. }
  228. void
  229. led_toggle(unsigned led)
  230. {
  231. switch (led) {
  232. case LED_ACTIVITY:
  233. gpio_toggle(BOARD_PORT_LEDS, BOARD_PIN_LED_ACTIVITY);
  234. break;
  235. case LED_BOOTLOADER:
  236. gpio_toggle(BOARD_PORT_LEDS, BOARD_PIN_LED_BOOTLOADER);
  237. break;
  238. }
  239. }
  240. static bool
  241. should_wait(void)
  242. {
  243. bool result = false;
  244. PWR_CR |= PWR_CR_DBP;
  245. if (BKP_DR1 == BL_WAIT_MAGIC) {
  246. result = true;
  247. BKP_DR1 = 0;
  248. }
  249. PWR_CR &= ~PWR_CR_DBP;
  250. return result;
  251. }
  252. int
  253. main(void)
  254. {
  255. unsigned timeout = 0;
  256. /* do board-specific initialisation */
  257. board_init();
  258. #if defined(INTERFACE_USART) || defined (INTERFACE_USB)
  259. /* XXX sniff for a USART connection to decide whether to wait in the bootloader? */
  260. timeout = BOOTLOADER_DELAY;
  261. #endif
  262. #ifdef INTERFACE_I2C
  263. # error I2C bootloader detection logic not implemented
  264. #endif
  265. /* if the app left a cookie saying we should wait, then wait */
  266. if (should_wait()) {
  267. timeout = BOOTLOADER_DELAY;
  268. }
  269. #ifdef BOARD_FORCE_BL_PIN
  270. /* if the force-BL pin state matches the state of the pin, wait in the bootloader forever */
  271. if (BOARD_FORCE_BL_VALUE == gpio_get(BOARD_FORCE_BL_PORT, BOARD_FORCE_BL_PIN)) {
  272. timeout = 0xffffffff;
  273. }
  274. #endif
  275. /* look for the magic wait-in-bootloader value in backup register zero */
  276. /* if we aren't expected to wait in the bootloader, try to boot immediately */
  277. if (timeout == 0) {
  278. /* try to boot immediately */
  279. jump_to_app();
  280. /* if we returned, there is no app; go to the bootloader and stay there */
  281. timeout = 0;
  282. }
  283. /* configure the clock for bootloader activity */
  284. clock_init();
  285. /* start the interface */
  286. cinit(BOARD_INTERFACE_CONFIG, USART);
  287. while (1) {
  288. /* run the bootloader, possibly coming back after the timeout */
  289. bootloader(timeout);
  290. /* look to see if we can boot the app */
  291. jump_to_app();
  292. /* boot failed; stay in the bootloader forever next time */
  293. timeout = 0;
  294. }
  295. }