OP-1900 added deceleration check to autotakeoff failsafe
[librepilot.git] / flight / modules / FirmwareIAP / firmwareiap.c
blob0d8b1c9005892ec0c06887f8356843e61a37ba87
1 /**
2 ******************************************************************************
4 * @file firmwareiap.c
5 * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
6 * @brief In Application Programming module to support firmware upgrades by
7 * providing a means to enter the bootloader.
9 * @see The GNU Public License (GPL) Version 3
11 *****************************************************************************/
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 3 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 * for more details.
23 * You should have received a copy of the GNU General Public License along
24 * with this program; if not, write to the Free Software Foundation, Inc.,
25 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 #include <openpilot.h>
30 #include <pios_board_info.h>
32 #include "firmwareiap.h"
33 #include "firmwareiapobj.h"
34 #include "flightstatus.h"
36 // Private constants
37 #define IAP_CMD_STEP_1 1122
38 #define IAP_CMD_STEP_2 2233
39 #define IAP_CMD_STEP_3 3344
41 #define IAP_CMD_CRC 100
42 #define IAP_CMD_VERIFY 101
43 #define IAP_CMD_VERSION 102
45 #define IAP_STATE_READY 0
46 #define IAP_STATE_STEP_1 1
47 #define IAP_STATE_STEP_2 2
48 #define IAP_STATE_RESETTING 3
50 #define RESET_DELAY 500 /* delay between sending reset ot INS */
52 #define TICKS2MS(t) ((t) / portTICK_RATE_MS)
53 #define MS2TICKS(m) ((m) * portTICK_RATE_MS)
55 const uint32_t iap_time_2_low_end = 500;
56 const uint32_t iap_time_2_high_end = 5000;
57 const uint32_t iap_time_3_low_end = 500;
58 const uint32_t iap_time_3_high_end = 5000;
60 // Private types
62 // Private variables
63 static uint8_t reset_count = 0;
64 static portTickType lastResetSysTime;
66 // Private functions
67 static void FirmwareIAPCallback(UAVObjEvent *ev);
69 static uint32_t get_time(void);
71 // Private types
73 // Private functions
74 static void resetTask(UAVObjEvent *);
76 /**
77 * Initialise the module, called on startup.
78 * \returns 0 on success or -1 if initialisation failed
81 /*!
82 * \brief Performs object initialization functions.
83 * \param None.
84 * \return 0 - under all cases
86 * \note
89 MODULE_INITCALL(FirmwareIAPInitialize, 0);
90 int32_t FirmwareIAPInitialize()
92 FirmwareIAPObjInitialize();
94 const struct pios_board_info *bdinfo = &pios_board_info_blob;
96 FirmwareIAPObjData data;
97 FirmwareIAPObjGet(&data);
99 data.BoardType = bdinfo->board_type;
100 PIOS_BL_HELPER_FLASH_Read_Description(data.Description, FIRMWAREIAPOBJ_DESCRIPTION_NUMELEM);
101 PIOS_SYS_SerialNumberGetBinary(data.CPUSerial);
102 data.BoardRevision = bdinfo->board_rev;
103 data.BootloaderRevision = bdinfo->bl_rev;
104 data.ArmReset = 0;
105 data.crc = 0;
106 FirmwareIAPObjSet(&data);
107 if (bdinfo->magic == PIOS_BOARD_INFO_BLOB_MAGIC) {
108 FirmwareIAPObjConnectCallback(&FirmwareIAPCallback);
110 return 0;
113 int32_t FirmwareIAPStart()
115 return 0;
119 * \brief FirmwareIAPCallback - callback function for firmware IAP requests
120 * \param[in] ev - pointer objevent
121 * \retval None.
123 * \note
126 static uint8_t iap_state = IAP_STATE_READY;
127 static void FirmwareIAPCallback(UAVObjEvent *ev)
129 const struct pios_board_info *bdinfo = &pios_board_info_blob;
130 static uint32_t last_time = 0;
131 uint32_t this_time;
132 uint32_t delta;
134 if (iap_state == IAP_STATE_RESETTING) {
135 return;
138 FirmwareIAPObjData data;
139 FirmwareIAPObjGet(&data);
141 if (ev->obj == FirmwareIAPObjHandle()) {
142 // Get the input object data
143 FirmwareIAPObjGet(&data);
144 this_time = get_time();
145 delta = this_time - last_time;
146 last_time = this_time;
147 if ((data.BoardType == bdinfo->board_type) && (data.crc != PIOS_BL_HELPER_CRC_Memory_Calc())) {
148 PIOS_BL_HELPER_FLASH_Read_Description(data.Description, FIRMWAREIAPOBJ_DESCRIPTION_NUMELEM);
149 PIOS_SYS_SerialNumberGetBinary(data.CPUSerial);
150 data.BoardRevision = bdinfo->board_rev;
151 data.BootloaderRevision = bdinfo->bl_rev;
152 data.crc = PIOS_BL_HELPER_CRC_Memory_Calc();
153 FirmwareIAPObjSet(&data);
155 if ((data.ArmReset == 1) && (iap_state != IAP_STATE_RESETTING)) {
156 data.ArmReset = 0;
157 FirmwareIAPObjSet(&data);
159 switch (iap_state) {
160 case IAP_STATE_READY:
161 if (data.Command == IAP_CMD_STEP_1) {
162 iap_state = IAP_STATE_STEP_1;
164 break;
165 case IAP_STATE_STEP_1:
166 if (data.Command == IAP_CMD_STEP_2) {
167 if (delta > iap_time_2_low_end && delta < iap_time_2_high_end) {
168 iap_state = IAP_STATE_STEP_2;
169 } else {
170 iap_state = IAP_STATE_READY;
172 } else {
173 iap_state = IAP_STATE_READY;
175 break;
176 case IAP_STATE_STEP_2:
177 if (data.Command == IAP_CMD_STEP_3) {
178 if (delta > iap_time_3_low_end && delta < iap_time_3_high_end) {
179 #ifndef PIOS_APPS_MINIMAL
180 FlightStatusData flightStatus;
181 FlightStatusGet(&flightStatus);
183 if (flightStatus.Armed != FLIGHTSTATUS_ARMED_DISARMED) {
184 // Abort any attempts if not disarmed
185 iap_state = IAP_STATE_READY;
186 break;
188 #endif
189 // we've met the three sequence of command numbers
190 // we've met the time requirements.
191 PIOS_IAP_SetRequest1();
192 PIOS_IAP_SetRequest2();
194 /* Note: Cant just wait timeout value, because first time is randomized */
195 reset_count = 0;
196 lastResetSysTime = xTaskGetTickCount();
197 UAVObjEvent *event = pios_malloc(sizeof(UAVObjEvent));
198 memset(event, 0, sizeof(UAVObjEvent));
199 EventPeriodicCallbackCreate(event, resetTask, 100);
200 iap_state = IAP_STATE_RESETTING;
201 } else {
202 iap_state = IAP_STATE_READY;
204 } else {
205 iap_state = IAP_STATE_READY;
207 break;
208 case IAP_STATE_RESETTING:
209 // stay here permanentally, should reboot
210 break;
211 default:
212 iap_state = IAP_STATE_READY;
213 last_time = 0; // Reset the time counter, as we are not doing a IAP reset
214 break;
220 // Returns number of milliseconds from the start of the kernel.
223 * \brief Returns number of milliseconds from the start of the kernel
224 * \param None.
225 * \return number of milliseconds from the start of the kernel.
227 * \note
231 static uint32_t get_time(void)
233 portTickType ticks;
235 ticks = xTaskGetTickCount();
237 return TICKS2MS(ticks);
241 * Executed by event dispatcher callback to reset INS before resetting OP
243 static void resetTask(__attribute__((unused)) UAVObjEvent *ev)
245 #if defined(PIOS_LED_HEARTBEAT)
246 PIOS_LED_Toggle(PIOS_LED_HEARTBEAT);
247 #endif /* PIOS_LED_HEARTBEAT */
249 #if defined(PIOS_LED_ALARM)
250 PIOS_LED_Toggle(PIOS_LED_ALARM);
251 #endif /* PIOS_LED_ALARM */
253 FirmwareIAPObjData data;
254 FirmwareIAPObjGet(&data);
256 if ((portTickType)(xTaskGetTickCount() - lastResetSysTime) > RESET_DELAY / portTICK_RATE_MS) {
257 lastResetSysTime = xTaskGetTickCount();
258 data.BoardType = 0xFF;
259 data.ArmReset = 1;
260 data.crc = reset_count; /* Must change a value for this to get to INS */
261 FirmwareIAPObjSet(&data);
262 ++reset_count;
263 if (reset_count > 3) {
264 PIOS_SYS_Reset();