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 file contains the DFU commands handling code
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
29 /* Includes ------------------------------------------------------------------*/
33 #include "pios_bl_helper.h"
34 #include "pios_com_msg.h"
35 #include <pios_board_info.h>
36 // programmable devices
37 Device devicesTable
[10];
38 uint8_t numberOfDevices
= 0;
40 DFUProgType currentProgrammingDestination
; // flash, flash_trough spi
41 uint8_t currentDeviceCanRead
;
42 uint8_t currentDeviceCanWrite
;
46 uint8_t echoBuffer
[64];
47 uint8_t SendBuffer
[64];
49 uint8_t EchoReqFlag
= 0;
50 uint8_t EchoAnsFlag
= 0;
51 uint8_t StartFlag
= 0;
52 uint32_t Aditionals
= 0;
53 uint32_t SizeOfTransfer
= 0;
54 uint32_t Expected_CRC
= 0;
55 uint8_t SizeOfLastPacket
= 0;
56 uint32_t Next_Packet
= 0;
67 uint32_t downSizeOfLastPacket
= 0;
68 uint32_t downPacketTotal
= 0;
69 uint32_t downPacketCurrent
= 0;
70 DFUTransfer downType
= 0;
71 /* Extern variables ----------------------------------------------------------*/
72 extern DFUStates DeviceState
;
73 extern uint8_t JumpToApp
;
74 /* Private function prototypes -----------------------------------------------*/
75 /* Private functions ---------------------------------------------------------*/
76 void sendData(uint8_t *buf
, uint16_t size
);
77 uint32_t CalcFirmCRC(void);
79 void DataDownload(__attribute__((unused
)) DownloadAction action
)
81 if ((DeviceState
== downloading
)) {
86 SendBuffer
[1] = Download
;
87 SendBuffer
[2] = downPacketCurrent
>> 24;
88 SendBuffer
[3] = downPacketCurrent
>> 16;
89 SendBuffer
[4] = downPacketCurrent
>> 8;
90 SendBuffer
[5] = downPacketCurrent
;
91 if (downPacketCurrent
== downPacketTotal
- 1) {
92 packetSize
= downSizeOfLastPacket
;
96 for (uint8_t x
= 0; x
< packetSize
; ++x
) {
97 partoffset
= (downPacketCurrent
* 14 * 4) + (x
* 4);
98 offset
= baseOfAdressType(downType
) + partoffset
;
99 if (!flash_read(SendBuffer
+ (6 + x
* 4), offset
,
100 currentProgrammingDestination
)) {
101 DeviceState
= Last_operation_failed
;
104 downPacketCurrent
= downPacketCurrent
+ 1;
105 if (downPacketCurrent
> downPacketTotal
- 1) {
106 DeviceState
= Last_operation_Success
;
107 Aditionals
= (uint32_t)Download
;
109 sendData(SendBuffer
+ 1, 63);
112 void processComand(uint8_t *xReceive_Buffer
)
114 Command
= xReceive_Buffer
[COMMAND
];
116 char str
[63] = { 0 };
117 sprintf(str
, "Received COMMAND:%d|", Command
);
118 PIOS_COM_SendString(PIOS_COM_TELEM_USB
, str
);
120 EchoReqFlag
= (Command
>> 7);
121 EchoAnsFlag
= (Command
>> 6) & 0x01;
122 StartFlag
= (Command
>> 5) & 0x01;
123 Count
= xReceive_Buffer
[COUNT
] << 24;
124 Count
+= xReceive_Buffer
[COUNT
+ 1] << 16;
125 Count
+= xReceive_Buffer
[COUNT
+ 2] << 8;
126 Count
+= xReceive_Buffer
[COUNT
+ 3];
128 Data
= xReceive_Buffer
[DATA
] << 24;
129 Data
+= xReceive_Buffer
[DATA
+ 1] << 16;
130 Data
+= xReceive_Buffer
[DATA
+ 2] << 8;
131 Data
+= xReceive_Buffer
[DATA
+ 3];
132 Data0
= xReceive_Buffer
[DATA
];
133 Data1
= xReceive_Buffer
[DATA
+ 1];
134 Data2
= xReceive_Buffer
[DATA
+ 2];
135 Data3
= xReceive_Buffer
[DATA
+ 3];
136 for (uint32_t i
= 0; i
< 3; i
++) {
137 Opt
[i
] = xReceive_Buffer
[DATA
+ 4 * (i
+ 1)] << 24 |
138 xReceive_Buffer
[DATA
+ 4 * (i
+ 1) + 1] << 16 |
139 xReceive_Buffer
[DATA
+ 4 * (i
+ 1) + 2] << 8 |
140 xReceive_Buffer
[DATA
+ 4 * (i
+ 1) + 3];
143 Command
= Command
& 0b00011111;
145 if (EchoReqFlag
== 1) {
146 memcpy(echoBuffer
, xReceive_Buffer
, 64);
150 if (((DeviceState
== BLidle
) && (Data0
< numberOfDevices
))
151 || (DeviceState
== DFUidle
)) {
155 DeviceState
= DFUidle
;
156 currentProgrammingDestination
= devicesTable
[Data0
].programmingType
;
157 currentDeviceCanRead
= devicesTable
[Data0
].readWriteFlags
& 0x01;
158 currentDeviceCanWrite
= devicesTable
[Data0
].readWriteFlags
>> 1
160 currentDevice
= devicesTable
[Data0
];
162 switch (currentProgrammingDestination
) {
164 result
= PIOS_BL_HELPER_FLASH_Ini();
166 case Remote_flash_via_spi
:
170 DeviceState
= Last_operation_failed
;
171 Aditionals
= (uint16_t)Command
;
174 DeviceState
= Last_operation_failed
;
175 Aditionals
= (uint32_t)Command
;
180 if ((DeviceState
== DFUidle
) || (DeviceState
== uploading
)) {
181 if ((StartFlag
== 1) && (Next_Packet
== 0)) {
182 TransferType
= Data0
;
183 SizeOfTransfer
= Count
;
185 Expected_CRC
= Data2
<< 24;
186 Expected_CRC
+= Data3
<< 16;
187 Expected_CRC
+= xReceive_Buffer
[DATA
+ 4] << 8;
188 Expected_CRC
+= xReceive_Buffer
[DATA
+ 5];
189 SizeOfLastPacket
= Data1
;
191 if (isBiggerThanAvailable(TransferType
, (SizeOfTransfer
- 1)
192 * 14 * 4 + SizeOfLastPacket
* 4) == true) {
193 DeviceState
= outsideDevCapabilities
;
194 Aditionals
= (uint32_t)Command
;
197 if (TransferType
== FW
) {
198 switch (currentProgrammingDestination
) {
200 result
= PIOS_BL_HELPER_FLASH_Start();
202 case Remote_flash_via_spi
:
210 DeviceState
= Last_operation_failed
;
211 Aditionals
= (uint32_t)Command
;
213 DeviceState
= uploading
;
216 } else if ((StartFlag
!= 1) && (Next_Packet
!= 0)) {
217 if (Count
> SizeOfTransfer
) {
218 DeviceState
= too_many_packets
;
220 } else if (Count
== Next_Packet
- 1) {
221 uint8_t numberOfWords
= 14;
222 if (Count
== SizeOfTransfer
- 1) { // is this the last packet?
223 numberOfWords
= SizeOfLastPacket
;
228 switch (currentProgrammingDestination
) {
230 for (uint8_t x
= 0; x
< numberOfWords
; ++x
) {
232 Data
= xReceive_Buffer
[DATA
+ offset
] << 24;
233 Data
+= xReceive_Buffer
[DATA
+ 1 + offset
] << 16;
234 Data
+= xReceive_Buffer
[DATA
+ 2 + offset
] << 8;
235 Data
+= xReceive_Buffer
[DATA
+ 3 + offset
];
236 aux
= baseOfAdressType(TransferType
) + (uint32_t)(
237 Count
* 14 * 4 + x
* 4);
239 for (int retry
= 0; retry
< MAX_WRI_RETRYS
; ++retry
) {
241 result
= (FLASH_ProgramWord(aux
, Data
)
242 == FLASH_COMPLETE
) ? 1 : 0;
247 case Remote_flash_via_spi
:
248 result
= false; // No support for this for the OPLink Mini
255 DeviceState
= Last_operation_failed
;
256 Aditionals
= (uint32_t)Command
;
261 DeviceState
= wrong_packet_received
;
265 DeviceState
= Last_operation_failed
;
266 Aditionals
= (uint32_t)Command
;
270 case Req_Capabilities
:
273 Buffer
[1] = Rep_Capabilities
;
280 Buffer
[7] = numberOfDevices
;
281 uint16_t WRFlags
= 0;
282 for (int x
= 0; x
< numberOfDevices
; ++x
) {
283 WRFlags
= ((devicesTable
[x
].readWriteFlags
<< (x
* 2))
286 Buffer
[8] = WRFlags
>> 8;
289 Buffer
[2] = devicesTable
[Data0
- 1].sizeOfCode
>> 24;
290 Buffer
[3] = devicesTable
[Data0
- 1].sizeOfCode
>> 16;
291 Buffer
[4] = devicesTable
[Data0
- 1].sizeOfCode
>> 8;
292 Buffer
[5] = devicesTable
[Data0
- 1].sizeOfCode
;
294 Buffer
[7] = devicesTable
[Data0
- 1].BL_Version
;
295 Buffer
[8] = devicesTable
[Data0
- 1].sizeOfDescription
;
296 Buffer
[9] = devicesTable
[Data0
- 1].devID
;
297 Buffer
[10] = devicesTable
[Data0
- 1].FW_Crc
>> 24;
298 Buffer
[11] = devicesTable
[Data0
- 1].FW_Crc
>> 16;
299 Buffer
[12] = devicesTable
[Data0
- 1].FW_Crc
>> 8;
300 Buffer
[13] = devicesTable
[Data0
- 1].FW_Crc
;
301 Buffer
[14] = devicesTable
[Data0
- 1].devID
>> 8;
302 Buffer
[15] = devicesTable
[Data0
- 1].devID
;
304 sendData(Buffer
+ 1, 63);
307 if (Data
== 0x5AFE) {
308 /* Force board into safe mode */
309 PIOS_IAP_WriteBootCount(0xFFFF);
311 // pass any Opt value to the firmware
312 PIOS_IAP_WriteBootCmd(0, Opt
[0]);
313 PIOS_IAP_WriteBootCmd(1, Opt
[1]);
314 PIOS_IAP_WriteBootCmd(2, Opt
[2]);
322 case Abort_Operation
:
324 DeviceState
= DFUidle
;
328 if (DeviceState
== uploading
) {
329 if (Next_Packet
- 1 == SizeOfTransfer
) {
331 if ((TransferType
!= FW
) || (Expected_CRC
== CalcFirmCRC())) {
332 DeviceState
= Last_operation_Success
;
334 DeviceState
= CRC_Fail
;
337 if (Next_Packet
- 1 < SizeOfTransfer
) {
339 DeviceState
= too_few_packets
;
345 sprintf(str
, "COMMAND:DOWNLOAD_REQ 1 Status=%d|", DeviceState
);
346 PIOS_COM_SendString(PIOS_COM_TELEM_USB
, str
);
348 if (DeviceState
== DFUidle
) {
350 PIOS_COM_SendString(PIOS_COM_TELEM_USB
, "COMMAND:DOWNLOAD_REQ 1|");
353 downPacketTotal
= Count
;
354 downSizeOfLastPacket
= Data1
;
355 if (isBiggerThanAvailable(downType
, (downPacketTotal
- 1) * 14
356 + downSizeOfLastPacket
) == 1) {
357 DeviceState
= outsideDevCapabilities
;
358 Aditionals
= (uint32_t)Command
;
360 downPacketCurrent
= 0;
361 DeviceState
= downloading
;
364 DeviceState
= Last_operation_failed
;
365 Aditionals
= (uint32_t)Command
;
371 Buffer
[1] = Status_Rep
;
372 if (DeviceState
== wrong_packet_received
) {
373 Buffer
[2] = Aditionals
>> 24;
374 Buffer
[3] = Aditionals
>> 16;
375 Buffer
[4] = Aditionals
>> 8;
376 Buffer
[5] = Aditionals
;
379 Buffer
[3] = ((uint16_t)Aditionals
) >> 8;
380 Buffer
[4] = ((uint16_t)Aditionals
);
383 Buffer
[6] = DeviceState
;
387 sendData(Buffer
+ 1, 63);
388 if (DeviceState
== Last_operation_Success
) {
389 DeviceState
= DFUidle
;
396 if (EchoReqFlag
== 1) {
397 echoBuffer
[1] = echoBuffer
[1] | EchoAnsFlag
;
398 sendData(echoBuffer
+ 1, 63);
401 void OPDfuIni(uint8_t discover
)
403 const struct pios_board_info
*bdinfo
= &pios_board_info_blob
;
406 dev
.programmingType
= Self_flash
;
407 dev
.readWriteFlags
= (BOARD_READABLE
| (BOARD_WRITABLE
<< 1));
408 dev
.startOfUserCode
= bdinfo
->fw_base
;
409 dev
.sizeOfCode
= bdinfo
->fw_size
;
410 dev
.sizeOfDescription
= bdinfo
->desc_size
;
411 dev
.BL_Version
= bdinfo
->bl_rev
;
412 dev
.FW_Crc
= CalcFirmCRC();
413 dev
.devID
= (bdinfo
->board_type
<< 8) | (bdinfo
->board_rev
);
414 dev
.devType
= bdinfo
->hw_type
;
416 devicesTable
[0] = dev
;
418 // TODO check other devices trough spi or whatever
421 uint32_t baseOfAdressType(DFUTransfer type
)
425 return currentDevice
.startOfUserCode
;
429 return currentDevice
.startOfUserCode
+ currentDevice
.sizeOfCode
;
437 uint8_t isBiggerThanAvailable(DFUTransfer type
, uint32_t size
)
441 return (size
> currentDevice
.sizeOfCode
) ? 1 : 0;
445 return (size
> currentDevice
.sizeOfDescription
) ? 1 : 0;
453 uint32_t CalcFirmCRC()
455 switch (currentProgrammingDestination
) {
457 return PIOS_BL_HELPER_CRC_Memory_Calc();
460 case Remote_flash_via_spi
:
470 void sendData(uint8_t *buf
, uint16_t size
)
472 PIOS_COM_MSG_Send(PIOS_COM_TELEM_USB
, buf
, size
);
475 bool flash_read(uint8_t *buffer
, uint32_t adr
, DFUProgType type
)
478 case Remote_flash_via_spi
:
479 return false; // We should not get this for the OPLink Mini
483 for (uint8_t x
= 0; x
< 4; ++x
) {
484 buffer
[x
] = *PIOS_BL_HELPER_FLASH_If_Read(adr
+ x
);