Merged in f5soh/librepilot/update_credits (pull request #529)
[librepilot.git] / flight / targets / boards / gpsplatinum / bootloader / main.c
blob8f49d55c3faf31eac2b6b735ec592eeeb5c999d7
1 /**
2 ******************************************************************************
3 * @addtogroup CopterControlBL CopterControl BootLoader
4 * @brief These files contain the code to the CopterControl Bootloader.
6 * @{
7 * @file main.c
8 * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
9 * @brief This is the file with the main function of the OpenPilot 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 <stdbool.h>
31 #include <stdint.h>
32 #include <pios_board_info.h>
33 #include <op_dfu.h>
34 #include <pios_iap.h>
35 #include <fifo_buffer.h>
36 #include <pios_com.h>
37 #include <ssp.h>
38 #include <pios_delay.h>
39 #include <pios_board_init.h>
41 extern void FLASH_Download();
42 int32_t platform_senddata(const uint8_t *msg, uint16_t msg_len);
43 /* Private typedef -----------------------------------------------------------*/
44 typedef void (*pFunction)(void);
45 /* Private define ------------------------------------------------------------*/
46 #define MAX_PACKET_DATA_LEN 255
47 #define MAX_PACKET_BUF_SIZE (1 + 1 + MAX_PACKET_DATA_LEN + 2)
48 #define UART_BUFFER_SIZE 256
49 #define BL_WAIT_TIME 6 * 1000 * 1000
50 #define DFU_BUFFER_SIZE 63
52 /* Private macro -------------------------------------------------------------*/
53 /* Private variables ---------------------------------------------------------*/
54 pFunction Jump_To_Application;
55 static uint32_t JumpAddress;
57 /// LEDs PWM
58 uint32_t period1 = 5000; // 5 mS
59 uint32_t sweep_steps1 = 100; // * 5 mS -> 500 mS
60 uint32_t period2 = 5000; // 5 mS
61 uint32_t sweep_steps2 = 100; // * 5 mS -> 500 mS
63 static uint8_t process_buffer[DFU_BUFFER_SIZE];
64 static uint8_t rx_buffer[UART_BUFFER_SIZE];
65 static uint8_t txBuf[MAX_PACKET_BUF_SIZE];
66 static uint8_t rxBuf[MAX_PACKET_BUF_SIZE];
68 /* Extern variables ----------------------------------------------------------*/
69 DFUStates DeviceState = DFUidle;
70 int16_t status = 0;
71 bool JumpToApp = false;
72 bool ssp_dfu = false; // signal that ssp data has been received
73 bool User_DFU_request = true;
76 /* Private function prototypes -----------------------------------------------*/
77 static void led_pwm_step(uint16_t pwm_period, uint16_t pwm_sweep_steps, uint32_t stopwatch, bool default_state);
78 static uint32_t LedPWM(uint16_t pwm_period, uint16_t pwm_sweep_steps, uint32_t count);
79 static void processRX();
80 static void jump_to_app();
83 static void SSP_CallBack(uint8_t *buf, uint16_t len);
84 static int16_t SSP_SerialRead(void);
85 static void SSP_SerialWrite(uint8_t);
88 static const PortConfig_t ssp_portConfig = {
89 .rxBuf = rxBuf,
90 .rxBufSize = MAX_PACKET_DATA_LEN,
91 .txBuf = txBuf,
92 .txBufSize = MAX_PACKET_DATA_LEN,
93 .max_retry = 1,
94 .timeoutLen = 5000,
95 .pfCallBack = SSP_CallBack,
96 .pfSerialRead = SSP_SerialRead,
97 .pfSerialWrite = SSP_SerialWrite,
98 .pfGetTime = PIOS_DELAY_GetuS,
101 static Port_t ssp_port;
102 static t_fifo_buffer ssp_buffer;
104 int main()
106 PIOS_SYS_Init();
107 PIOS_Board_Init();
108 PIOS_IAP_Init();
110 if (PIOS_IAP_CheckRequest() == false) {
111 PIOS_DELAY_WaitmS(500);
112 User_DFU_request = false;
113 DeviceState = BLidle;
114 PIOS_IAP_ClearRequest();
117 // Initialize the SSP layer between serial port and DFU
118 fifoBuf_init(&ssp_buffer, rx_buffer, UART_BUFFER_SIZE);
119 ssp_Init(&ssp_port, &ssp_portConfig);
121 uint32_t stopwatch = 0;
122 const uint32_t start_time = PIOS_DELAY_GetuS();
123 while (true) {
124 /* Update the stopwatch */
125 stopwatch = PIOS_DELAY_GetuSSince(start_time);
127 processRX();
129 switch (DeviceState) {
130 case Last_operation_Success:
131 case uploadingStarting:
132 case DFUidle:
133 period1 = 5000;
134 sweep_steps1 = 100;
135 // PIOS_LED_Off(PIOS_LED_HEARTBEAT);
136 period2 = 0;
137 break;
138 case uploading:
139 period1 = 5000;
140 sweep_steps1 = 100;
141 period2 = 2500;
142 sweep_steps2 = 50;
143 break;
144 case downloading:
145 period1 = 2500;
146 sweep_steps1 = 50;
147 // PIOS_LED_Off(PIOS_LED_HEARTBEAT);
148 period2 = 0;
149 break;
150 case BLidle:
151 period1 = 0;
152 sweep_steps1 = 100;
153 PIOS_LED_On(PIOS_LED_HEARTBEAT);
154 period2 = 0;
155 break;
156 default: // error
157 period1 = 5000;
158 sweep_steps1 = 100;
159 period2 = 5000;
160 sweep_steps2 = 100;
162 led_pwm_step(period1, sweep_steps1, stopwatch, false);
163 led_pwm_step(period2, sweep_steps2, stopwatch, true);
164 JumpToApp |= !ssp_dfu && (stopwatch > BL_WAIT_TIME) && ((DeviceState == BLidle) || (DeviceState == DFUidle));
165 DataDownload(start);
167 if (JumpToApp == true) {
168 jump_to_app();
173 void led_pwm_step(uint16_t pwm_period, uint16_t pwm_sweep_steps, uint32_t stopwatch, bool default_state)
175 if (pwm_period != 0) {
176 if (LedPWM(pwm_period, pwm_sweep_steps, stopwatch)) {
177 PIOS_LED_On(PIOS_LED_HEARTBEAT);
178 } else {
179 PIOS_LED_Off(PIOS_LED_HEARTBEAT);
181 } else {
182 if (default_state) {
183 PIOS_LED_On(PIOS_LED_HEARTBEAT);
184 } else {
185 PIOS_LED_Off(PIOS_LED_HEARTBEAT);
189 void jump_to_app()
191 const struct pios_board_info *bdinfo = &pios_board_info_blob;
193 if (((*(__IO uint32_t *)bdinfo->fw_base) & 0x2FFE0000) == 0x20000000) { /* Jump to user application */
194 FLASH_Lock();
195 RCC_APB2PeriphResetCmd(0xffffffff, ENABLE);
196 RCC_APB1PeriphResetCmd(0xffffffff, ENABLE);
197 RCC_APB2PeriphResetCmd(0xffffffff, DISABLE);
198 RCC_APB1PeriphResetCmd(0xffffffff, DISABLE);
200 JumpAddress = *(__IO uint32_t *)(bdinfo->fw_base + 4);
201 Jump_To_Application = (pFunction)JumpAddress;
202 /* Initialize user application's Stack Pointer */
203 __set_MSP(*(__IO uint32_t *)bdinfo->fw_base);
204 Jump_To_Application();
205 } else {
206 DeviceState = failed_jump;
207 return;
211 uint32_t LedPWM(uint16_t pwm_period, uint16_t pwm_sweep_steps, uint32_t count)
213 const uint32_t curr_step = (count / pwm_period) % pwm_sweep_steps; /* 0 - pwm_sweep_steps */
214 uint32_t pwm_duty = pwm_period * curr_step / pwm_sweep_steps; /* fraction of pwm_period */
216 const uint32_t curr_sweep = (count / (pwm_period * pwm_sweep_steps)); /* ticks once per full sweep */
218 if (curr_sweep & 1) {
219 pwm_duty = pwm_period - pwm_duty; /* reverse direction in odd sweeps */
221 return ((count % pwm_period) > pwm_duty) ? 1 : 0;
223 uint32_t process_count = 0;
224 void processRX()
226 do {
227 ssp_ReceiveProcess(&ssp_port);
228 status = ssp_SendProcess(&ssp_port);
229 } while ((status != SSP_TX_IDLE) && (status != SSP_TX_ACKED));
231 if (fifoBuf_getUsed(&ssp_buffer) >= DFU_BUFFER_SIZE) {
232 for (int32_t x = 0; x < DFU_BUFFER_SIZE; ++x) {
233 process_buffer[x] = fifoBuf_getByte(&ssp_buffer);
235 process_count++;
236 processComand(process_buffer);
239 uint32_t callback_cnt = 0;
240 uint32_t read_cnt = 0;
241 uint32_t write_cnt = 0;
242 uint32_t rx_check_cnt = 0;
243 void SSP_CallBack(uint8_t *buf, uint16_t len)
245 ssp_dfu = true;
246 callback_cnt++;
247 fifoBuf_putData(&ssp_buffer, buf, len);
250 int16_t SSP_SerialRead(void)
252 uint8_t byte;
254 rx_check_cnt++;
255 if (PIOS_COM_ReceiveBuffer(PIOS_COM_TELEM_USB, &byte, 1, 0) == 1) {
256 read_cnt++;
257 return byte;
258 } else {
259 return -1;
263 int32_t platform_senddata(const uint8_t *msg, uint16_t msg_len)
265 return ssp_SendData(&ssp_port, msg, msg_len);
268 void SSP_SerialWrite(uint8_t value)
270 write_cnt++;
271 PIOS_COM_SendChar(PIOS_COM_TELEM_USB, value);