2 ******************************************************************************
3 * @addtogroup RevolutionBL Revolution BootLoader
4 * @brief These files contain the code to the Revolution Bootloader.
8 * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
9 * @brief This is the file with the main function of the Revolution BootLoader
10 * @see The GNU Public License (GPL) Version 3
12 *****************************************************************************/
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 3 of the License, or
17 * (at your option) any later version.
19 * This program is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
21 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
24 * You should have received a copy of the GNU General Public License along
25 * with this program; if not, write to the Free Software Foundation, Inc.,
26 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 #include <pios_board_info.h>
33 #include <fifo_buffer.h>
34 #include <pios_com_msg.h>
35 #include <pios_usbhook.h> /* PIOS_USBHOOK_* */
37 #include <pios_board_init.h>
39 extern void FLASH_Download();
41 #define BSL_HOLD_STATE ((PIOS_USB_DETECT_GPIO_PORT->IDR & PIOS_USB_DETECT_GPIO_PIN) ? 0 : 1)
43 /* Private typedef -----------------------------------------------------------*/
44 typedef void (*pFunction
)(void);
45 /* Private define ------------------------------------------------------------*/
46 /* Private macro -------------------------------------------------------------*/
47 /* Private variables ---------------------------------------------------------*/
48 pFunction Jump_To_Application
;
52 uint32_t period1
= 5000; // 5 mS
53 uint32_t sweep_steps1
= 100; // * 5 mS -> 500 mS
54 uint32_t period2
= 5000; // 5 mS
55 uint32_t sweep_steps2
= 100; // * 5 mS -> 500 mS
58 ////////////////////////////////////////
59 uint8_t tempcount
= 0;
61 /* Extern variables ----------------------------------------------------------*/
62 DFUStates DeviceState
;
64 bool JumpToApp
= false;
66 bool USB_connected
= false;
67 bool User_DFU_request
= false;
68 static uint8_t mReceive_Buffer
[63];
69 /* Private function prototypes -----------------------------------------------*/
70 uint32_t LedPWM(uint32_t pwm_period
, uint32_t pwm_sweep_steps
, uint32_t count
);
80 // Make sure the brown out reset value for this chip
84 USB_connected
= PIOS_USB_CheckAvailable(0);
86 if (PIOS_IAP_CheckRequest() == true) {
87 PIOS_DELAY_WaitmS(1000);
88 User_DFU_request
= true;
89 PIOS_IAP_ClearRequest();
92 GO_dfu
= (USB_connected
== true) || (User_DFU_request
== true);
95 if (User_DFU_request
== true) {
96 DeviceState
= DFUidle
;
104 uint32_t stopwatch
= 0;
105 uint32_t prev_ticks
= PIOS_DELAY_GetuS();
107 /* Update the stopwatch */
108 uint32_t elapsed_ticks
= PIOS_DELAY_GetuSSince(prev_ticks
);
109 prev_ticks
+= elapsed_ticks
;
110 stopwatch
+= elapsed_ticks
;
112 if (JumpToApp
== true) {
116 switch (DeviceState
) {
117 case Last_operation_Success
:
118 case uploadingStarting
:
122 PIOS_LED_Off(PIOS_LED_HEARTBEAT
);
134 PIOS_LED_Off(PIOS_LED_HEARTBEAT
);
139 PIOS_LED_On(PIOS_LED_HEARTBEAT
);
150 if (LedPWM(period1
, sweep_steps1
, stopwatch
)) {
151 PIOS_LED_On(PIOS_LED_HEARTBEAT
);
153 PIOS_LED_Off(PIOS_LED_HEARTBEAT
);
156 PIOS_LED_On(PIOS_LED_HEARTBEAT
);
160 if (LedPWM(period2
, sweep_steps2
, stopwatch
)) {
161 PIOS_LED_On(PIOS_LED_HEARTBEAT
);
163 PIOS_LED_Off(PIOS_LED_HEARTBEAT
);
166 PIOS_LED_Off(PIOS_LED_HEARTBEAT
);
169 if (stopwatch
> 50 * 1000 * 1000) {
172 if ((stopwatch
> 6 * 1000 * 1000) && ((DeviceState
== BLidle
) || (DeviceState
== DFUidle
&& !USB_connected
))) {
183 const struct pios_board_info
*bdinfo
= &pios_board_info_blob
;
185 PIOS_LED_On(PIOS_LED_HEARTBEAT
);
186 // Look at cm3_vectors struct in startup. In a fw image the first uint32_t contains the address of the top of irqstack
187 uint32_t fwIrqStackBase
= (*(__IO
uint32_t *)bdinfo
->fw_base
) & 0xFFFE0000;
188 // Check for the two possible irqstack locations (sram or core coupled sram)
189 if (fwIrqStackBase
== 0x20000000 || fwIrqStackBase
== 0x10000000) {
190 /* Jump to user application */
192 RCC_APB2PeriphResetCmd(0xffffffff, ENABLE
);
193 RCC_APB1PeriphResetCmd(0xffffffff, ENABLE
);
194 RCC_APB2PeriphResetCmd(0xffffffff, DISABLE
);
195 RCC_APB1PeriphResetCmd(0xffffffff, DISABLE
);
197 PIOS_USBHOOK_Deactivate();
199 JumpAddress
= *(__IO
uint32_t *)(bdinfo
->fw_base
+ 4);
200 Jump_To_Application
= (pFunction
)JumpAddress
;
201 /* Initialize user application's Stack Pointer */
202 __set_MSP(*(__IO
uint32_t *)bdinfo
->fw_base
);
203 Jump_To_Application();
205 DeviceState
= failed_jump
;
209 uint32_t LedPWM(uint32_t pwm_period
, uint32_t pwm_sweep_steps
, uint32_t count
)
211 uint32_t curr_step
= (count
/ pwm_period
) % pwm_sweep_steps
; /* 0 - pwm_sweep_steps */
212 uint32_t pwm_duty
= pwm_period
* curr_step
/ pwm_sweep_steps
; /* fraction of pwm_period */
214 uint32_t curr_sweep
= (count
/ (pwm_period
* pwm_sweep_steps
)); /* ticks once per full sweep */
216 if (curr_sweep
& 1) {
217 pwm_duty
= pwm_period
- pwm_duty
; /* reverse direction in odd sweeps */
219 return ((count
% pwm_period
) > pwm_duty
) ? 1 : 0;
224 if (PIOS_COM_MSG_Receive(PIOS_COM_TELEM_USB
, mReceive_Buffer
, sizeof(mReceive_Buffer
))) {
225 processComand(mReceive_Buffer
);
231 * Check the brown out reset threshold is 2.7 volts and if not
232 * resets it. This solves an issue that can prevent boards
233 * powering up with some BEC
237 uint8_t bor
= FLASH_OB_GetBOR();
239 if (bor
!= OB_BOR_LEVEL3
) {
241 FLASH_OB_BORConfig(OB_BOR_LEVEL3
);
243 while (FLASH_WaitForLastOperation() == FLASH_BUSY
) {
247 while (FLASH_WaitForLastOperation() == FLASH_BUSY
) {
253 int32_t platform_senddata(const uint8_t *msg
, uint16_t msg_len
)
255 return PIOS_COM_MSG_Send(PIOS_COM_TELEM_USB
, msg
, msg_len
);