2 ******************************************************************************
3 * @addtogroup CopterControlBL CopterControl BootLoader
4 * @brief These files contain the code to the CopterControl 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 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
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
32 #include <pios_board_info.h>
35 #include <fifo_buffer.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
;
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
;
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
= {
90 .rxBufSize
= MAX_PACKET_DATA_LEN
,
92 .txBufSize
= MAX_PACKET_DATA_LEN
,
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
;
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();
124 /* Update the stopwatch */
125 stopwatch
= PIOS_DELAY_GetuSSince(start_time
);
129 switch (DeviceState
) {
130 case Last_operation_Success
:
131 case uploadingStarting
:
135 // PIOS_LED_Off(PIOS_LED_HEARTBEAT);
147 // PIOS_LED_Off(PIOS_LED_HEARTBEAT);
153 PIOS_LED_On(PIOS_LED_HEARTBEAT
);
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
));
167 if (JumpToApp
== true) {
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
);
179 PIOS_LED_Off(PIOS_LED_HEARTBEAT
);
183 PIOS_LED_On(PIOS_LED_HEARTBEAT
);
185 PIOS_LED_Off(PIOS_LED_HEARTBEAT
);
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 */
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();
206 DeviceState
= failed_jump
;
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;
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
);
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
)
247 fifoBuf_putData(&ssp_buffer
, buf
, len
);
250 int16_t SSP_SerialRead(void)
255 if (PIOS_COM_ReceiveBuffer(PIOS_COM_TELEM_USB
, &byte
, 1, 0) == 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
)
271 PIOS_COM_SendChar(PIOS_COM_TELEM_USB
, value
);