board_init.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. // The code is this file allows the user to enter DFU mode when the board
  2. // starts up, by connecting POS10 on the external connector to GND.
  3. // The code itself is taken from the LimiFrog software repository found at
  4. // https://github.com/LimiFrog/LimiFrog-SW, and the original license header
  5. // is copied below.
  6. #include STM32_HAL_H
  7. static void LBF_DFU_If_Needed(void);
  8. void LIMIFROG_board_early_init(void) {
  9. LBF_DFU_If_Needed();
  10. }
  11. /*******************************************************************************
  12. * LBF_DFU_If_Needed.c
  13. *
  14. * (c)2015 LimiFrog / CYMEYA
  15. * This program is licensed under the terms of the MIT License.
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND.
  17. * Please refer to the License File LICENSE.txt located at the root of this
  18. * project for full licensing conditions,
  19. * or visit https://opensource.org/licenses/MIT.
  20. ******************************************************************************/
  21. #define __LIMIFROG_02
  22. /* ==== BTLE (excl UART) ======================================== */
  23. // PC9 = BT_RST (active high)
  24. #define BT_RST_PIN GPIO_PIN_9
  25. #define BT_RST_PORT GPIOC
  26. // Position 10
  27. #ifdef __LIMIFROG_01
  28. #define CONN_POS10_PIN GPIO_PIN_9
  29. #define CONN_POS10_PORT GPIOB
  30. #else
  31. #define CONN_POS10_PIN GPIO_PIN_8
  32. #define CONN_POS10_PORT GPIOB
  33. #endif
  34. static inline void GPIO_HIGH(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
  35. {
  36. GPIOx->BSRR = (uint32_t)GPIO_Pin;
  37. }
  38. static inline int IS_GPIO_RESET(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
  39. {
  40. GPIO_PinState bitstatus;
  41. if((GPIOx->IDR & GPIO_Pin) != (uint32_t)GPIO_PIN_RESET)
  42. {
  43. bitstatus = GPIO_PIN_SET;
  44. }
  45. else
  46. {
  47. bitstatus = GPIO_PIN_RESET;
  48. }
  49. return (bitstatus==GPIO_PIN_RESET);
  50. }
  51. /**************************************************************
  52. RATIONALE FOR THIS FUNCTION :
  53. - The STM32 embeds in ROM a bootloader that allows to
  54. obtain code and boot from a number of different interfaces,
  55. including USB in a mode called "DFU" (Device Frimware Update)
  56. [see AN3606 from ST for full details]
  57. This bootloader code is executed instead of the regular
  58. application code when pin BOOT0 is pulled-up (which on
  59. LimiFrog0.2 is achieved by pressing the general-purpose
  60. pushbutton switch on the side.
  61. - The bootloader monitors a number of IOs of the STM32 to decide
  62. from which interface it should boot.
  63. - Problem in LimiFrog (up to versions 0.2a at least): upon
  64. power-up the BLE modules generates some activity on UART3,
  65. which is part of the pins monitored by the STM32.
  66. This misleads the bootloader in trying to boot from UART3
  67. and, as a result, not continuing with booting from USB.
  68. - This code implements an alternative solution to launch the
  69. bootloader while making sure UART3 remains stable.
  70. - The idea it to start application code with a check, prior to any
  71. other applicative code, of whether USB bootload is required (as
  72. flagged by a GPIO pulled low at reset, in the same way as BOOT0).
  73. The hadware reset pin of BLE is asserted (so that now it won't
  74. generate any acitivity on UART3), and if USB bootload is required :
  75. bootload ROM is remapped at address 0x0, stack pointer is
  76. updated and the code is branched to the start of the bootloader.
  77. - This code is run prior to any applicative configuration of clocks,
  78. IRQs etc. -- the STM32 is therefore still running from MSI
  79. THIS FUNCTION MAY BE SUPPRESSED IF YOU NEVER NEED TO BOOT DFU MODE
  80. ********************************************************************/
  81. static void LBF_DFU_If_Needed(void)
  82. {
  83. GPIO_InitTypeDef GPIO_InitStruct;
  84. // Initialize and assert pin BTLE_RST
  85. // (hw reset to BLE module, so it won't drive UART3)
  86. __HAL_RCC_GPIOC_CLK_ENABLE();
  87. GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  88. GPIO_InitStruct.Pull = GPIO_NOPULL;
  89. GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  90. GPIO_InitStruct.Pin = BT_RST_PIN;
  91. HAL_GPIO_Init(BT_RST_PORT, &GPIO_InitStruct);
  92. GPIO_HIGH(BT_RST_PORT, BT_RST_PIN); // assert BTLE reset
  93. /* -- Bootloader will be called if position 10 on the extension port
  94. is actively pulled low -- */
  95. // Note - this is an arbitrary choice, code could be modified to
  96. // monitor another GPIO of the STM32 and/or decide that active level
  97. // is high rather than low
  98. // Initialize Extension Port Position 10 = PB8 (bears I2C1_SCL)
  99. // Use weak pull-up to detect if pin is externally pulled low
  100. __HAL_RCC_GPIOB_CLK_ENABLE();
  101. GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  102. GPIO_InitStruct.Pull = GPIO_PULLUP;
  103. GPIO_InitStruct.Pin = CONN_POS10_PIN;
  104. HAL_GPIO_Init(CONN_POS10_PORT, &GPIO_InitStruct);
  105. // If selection pin pulled low...
  106. if ( IS_GPIO_RESET(CONN_POS10_PORT, CONN_POS10_PIN ))
  107. {
  108. // Remap bootloader ROM (ie System Flash) to address 0x0
  109. SYSCFG->MEMRMP = 0x00000001;
  110. // Init stack pointer with value residing at ROM base
  111. asm (
  112. "LDR R0, =0x00000000\n\t" // load ROM base address"
  113. "LDR SP,[R0, #0]\n\t" // assign main stack pointer"
  114. );
  115. // Jump to address pointed by 0x00000004 -- */
  116. asm (
  117. "LDR R0,[R0, #4]\n\t" // load bootloader address
  118. "BX R0\n\t"
  119. );
  120. }
  121. }