Merged in f5soh/librepilot/update_credits (pull request #529)
[librepilot.git] / flight / targets / boards / nucleof303re / bootloader / main.c
blob044608da540501bd366207d13ef27ac528722152
1 /**
2 ******************************************************************************
3 * @addtogroup BootLoader
5 * @{
6 * @file main.c
7 * @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2017.
8 * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
9 * @brief This is the file with the main function of the LibrePilot 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
22 * for more details.
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
29 #include <pios.h>
30 #include <pios_board_info.h>
31 #include <op_dfu.h>
32 #include <usb_lib.h>
33 #include <pios_iap.h>
34 #include <fifo_buffer.h>
35 #include <pios_com_msg.h>
36 #include <pios_board_init.h>
37 #include <pios_board_io.h>
39 extern void FLASH_Download();
40 #define BSL_HOLD_STATE ((PIOS_USB_DETECT_GPIO_PORT->IDR & PIOS_USB_DETECT_GPIO_PIN) ? 0 : 1)
42 /* Private typedef -----------------------------------------------------------*/
43 typedef void (*pFunction)(void);
44 /* Private define ------------------------------------------------------------*/
45 /* Private macro -------------------------------------------------------------*/
46 /* Private variables ---------------------------------------------------------*/
47 pFunction Jump_To_Application;
48 uint32_t JumpAddress;
50 /// LEDs PWM
51 uint32_t period1 = 5000; // 5 mS
52 uint32_t sweep_steps1 = 100; // * 5 mS -> 500 mS
53 uint32_t period2 = 5000; // 5 mS
54 uint32_t sweep_steps2 = 100; // * 5 mS -> 500 mS
57 ////////////////////////////////////////
58 uint8_t tempcount = 0;
60 /* Extern variables ----------------------------------------------------------*/
61 DFUStates DeviceState;
62 int16_t status = 0;
63 uint8_t JumpToApp = FALSE;
64 uint8_t GO_dfu = FALSE;
65 uint8_t USB_connected = FALSE;
66 uint8_t User_DFU_request = FALSE;
67 static uint8_t mReceive_Buffer[63];
68 /* Private function prototypes -----------------------------------------------*/
69 uint32_t LedPWM(uint32_t pwm_period, uint32_t pwm_sweep_steps, uint32_t count);
70 uint8_t processRX();
71 void jump_to_app();
73 int main()
75 PIOS_SYS_Init();
76 PIOS_Board_Init();
77 PIOS_IAP_Init();
79 USB_connected = PIOS_USB_CableConnected(0);
81 if (PIOS_IAP_CheckRequest() == TRUE) {
82 PIOS_DELAY_WaitmS(1000);
83 User_DFU_request = TRUE;
84 PIOS_IAP_ClearRequest();
87 GO_dfu = (USB_connected == TRUE) || (User_DFU_request == TRUE);
89 if (GO_dfu == TRUE) {
90 PIOS_Board_Init();
91 if (User_DFU_request == TRUE) {
92 DeviceState = DFUidle;
93 } else {
94 DeviceState = BLidle;
96 } else {
97 JumpToApp = TRUE;
100 uint32_t stopwatch = 0;
101 uint32_t prev_ticks = PIOS_DELAY_GetuS();
102 while (TRUE) {
103 /* Update the stopwatch */
104 uint32_t elapsed_ticks = PIOS_DELAY_GetuSSince(prev_ticks);
105 prev_ticks += elapsed_ticks;
106 stopwatch += elapsed_ticks;
108 if (JumpToApp == TRUE) {
109 jump_to_app();
112 switch (DeviceState) {
113 case Last_operation_Success:
114 case uploadingStarting:
115 case DFUidle:
116 period1 = 5000;
117 sweep_steps1 = 100;
118 PIOS_LED_Off(PIOS_LED_HEARTBEAT);
119 period2 = 0;
120 break;
121 case uploading:
122 period1 = 5000;
123 sweep_steps1 = 100;
124 period2 = 2500;
125 sweep_steps2 = 50;
126 break;
127 case downloading:
128 period1 = 2500;
129 sweep_steps1 = 50;
130 PIOS_LED_Off(PIOS_LED_HEARTBEAT);
131 period2 = 0;
132 break;
133 case BLidle:
134 period1 = 0;
135 PIOS_LED_On(PIOS_LED_HEARTBEAT);
136 period2 = 0;
137 break;
138 default: // error
139 period1 = 5000;
140 sweep_steps1 = 100;
141 period2 = 5000;
142 sweep_steps2 = 100;
145 if (period1 != 0) {
146 if (LedPWM(period1, sweep_steps1, stopwatch)) {
147 PIOS_LED_On(PIOS_LED_HEARTBEAT);
148 } else {
149 PIOS_LED_Off(PIOS_LED_HEARTBEAT);
151 } else {
152 PIOS_LED_On(PIOS_LED_HEARTBEAT);
155 if (period2 != 0) {
156 if (LedPWM(period2, sweep_steps2, stopwatch)) {
157 PIOS_LED_On(PIOS_LED_HEARTBEAT);
158 } else {
159 PIOS_LED_Off(PIOS_LED_HEARTBEAT);
161 } else {
162 PIOS_LED_Off(PIOS_LED_HEARTBEAT);
165 if (stopwatch > 50 * 1000 * 1000) {
166 stopwatch = 0;
168 if ((stopwatch > 6 * 1000 * 1000) && ((DeviceState == BLidle) /*|| (DeviceState == DFUidle && !USB_connected)*/)) {
169 JumpToApp = TRUE;
172 processRX();
173 DataDownload(start);
177 void jump_to_app()
179 const struct pios_board_info *bdinfo = &pios_board_info_blob;
181 uint32_t fwIrqStackBase = (*(__IO uint32_t *)bdinfo->fw_base) & 0xFFFE0000;
183 // Check for the two possible irqstack locations (sram or core coupled sram)
184 if (fwIrqStackBase == 0x20000000 || fwIrqStackBase == 0x10000000) {
185 /* Jump to user application */
186 FLASH_Lock();
187 RCC_APB2PeriphResetCmd(0xffffffff, ENABLE);
188 RCC_APB1PeriphResetCmd(0xffffffff, ENABLE);
189 RCC_APB2PeriphResetCmd(0xffffffff, DISABLE);
190 RCC_APB1PeriphResetCmd(0xffffffff, DISABLE);
192 _SetCNTR(0); // clear interrupt mask
193 _SetISTR(0); // clear all requests
195 JumpAddress = *(__IO uint32_t *)(bdinfo->fw_base + 4);
196 Jump_To_Application = (pFunction)JumpAddress;
197 /* Initialize user application's Stack Pointer */
198 __set_MSP(*(__IO uint32_t *)bdinfo->fw_base);
199 Jump_To_Application();
200 } else {
201 DeviceState = failed_jump;
202 JumpToApp = FALSE;
203 return;
206 uint32_t LedPWM(uint32_t pwm_period, uint32_t pwm_sweep_steps, uint32_t count)
208 uint32_t curr_step = (count / pwm_period) % pwm_sweep_steps; /* 0 - pwm_sweep_steps */
209 uint32_t pwm_duty = pwm_period * curr_step / pwm_sweep_steps; /* fraction of pwm_period */
211 uint32_t curr_sweep = (count / (pwm_period * pwm_sweep_steps)); /* ticks once per full sweep */
213 if (curr_sweep & 1) {
214 pwm_duty = pwm_period - pwm_duty; /* reverse direction in odd sweeps */
216 return ((count % pwm_period) > pwm_duty) ? 1 : 0;
219 uint8_t processRX()
221 if (PIOS_COM_MSG_Receive(PIOS_COM_TELEM_USB, mReceive_Buffer, sizeof(mReceive_Buffer))) {
222 processComand(mReceive_Buffer);
224 return TRUE;
227 int32_t platform_senddata(const uint8_t *msg, uint16_t msg_len)
229 return PIOS_COM_MSG_Send(PIOS_COM_TELEM_USB, msg, msg_len);