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_board_info.h>
35 // programmable devices
36 Device devicesTable
[10];
37 uint8_t numberOfDevices
= 0;
39 DFUProgType currentProgrammingDestination
; // flash, flash_trough spi
40 uint8_t currentDeviceCanRead
;
41 uint8_t currentDeviceCanWrite
;
45 uint8_t echoBuffer
[64];
46 uint8_t SendBuffer
[64];
48 uint8_t EchoReqFlag
= 0;
49 uint8_t EchoAnsFlag
= 0;
50 uint8_t StartFlag
= 0;
51 uint32_t Aditionals
= 0;
52 uint32_t SizeOfTransfer
= 0;
53 uint32_t Expected_CRC
= 0;
54 uint8_t SizeOfLastPacket
= 0;
55 uint32_t Next_Packet
= 0;
66 uint32_t downSizeOfLastPacket
= 0;
67 uint32_t downPacketTotal
= 0;
68 uint32_t downPacketCurrent
= 0;
69 DFUTransfer downType
= 0;
70 /* Extern variables ----------------------------------------------------------*/
71 extern DFUStates DeviceState
;
72 extern uint8_t JumpToApp
;
73 extern int32_t platform_senddata(const uint8_t *msg
, uint16_t msg_len
);
74 /* Private function prototypes -----------------------------------------------*/
75 static uint32_t baseOfAdressType(uint8_t type
);
76 static uint8_t isBiggerThanAvailable(uint8_t type
, uint32_t size
);
77 static void OPDfuIni(uint8_t discover
);
78 bool flash_read(uint8_t *buffer
, uint32_t adr
, DFUProgType type
);
79 /* Private functions ---------------------------------------------------------*/
80 void sendData(uint8_t *buf
, uint16_t size
);
81 uint32_t CalcFirmCRC(void);
83 void DataDownload(__attribute__((unused
)) DownloadAction action
)
85 if ((DeviceState
== downloading
)) {
90 SendBuffer
[1] = Download
;
91 SendBuffer
[2] = downPacketCurrent
>> 24;
92 SendBuffer
[3] = downPacketCurrent
>> 16;
93 SendBuffer
[4] = downPacketCurrent
>> 8;
94 SendBuffer
[5] = downPacketCurrent
;
95 if (downPacketCurrent
== downPacketTotal
- 1) {
96 packetSize
= downSizeOfLastPacket
;
100 for (uint8_t x
= 0; x
< packetSize
; ++x
) {
101 partoffset
= (downPacketCurrent
* 14 * 4) + (x
* 4);
102 offset
= baseOfAdressType(downType
) + partoffset
;
103 if (!flash_read(SendBuffer
+ (6 + x
* 4), offset
,
104 currentProgrammingDestination
)) {
105 DeviceState
= Last_operation_failed
;
108 downPacketCurrent
= downPacketCurrent
+ 1;
109 if (downPacketCurrent
> downPacketTotal
- 1) {
110 DeviceState
= Last_operation_Success
;
111 Aditionals
= (uint32_t)Download
;
113 sendData(SendBuffer
+ 1, 63);
117 static uint32_t unpack_uint32(uint8_t *buffer
)
119 uint32_t ret
= buffer
[0] << 24;
121 ret
+= buffer
[1] << 16;
122 ret
+= buffer
[2] << 8;
127 static void pack_uint32(uint32_t value
, uint8_t *buffer
)
129 buffer
[0] = value
>> 24;
130 buffer
[1] = value
>> 16;
131 buffer
[2] = value
>> 8;
136 void processComand(uint8_t *xReceive_Buffer
)
138 Command
= xReceive_Buffer
[COMMAND
];
139 EchoReqFlag
= (Command
>> 7);
140 EchoAnsFlag
= (Command
>> 6) & 0x01;
141 StartFlag
= (Command
>> 5) & 0x01;
142 Count
= unpack_uint32(&xReceive_Buffer
[COUNT
]);
143 Data
= unpack_uint32(&xReceive_Buffer
[DATA
]);
144 Data0
= xReceive_Buffer
[DATA
];
145 Data1
= xReceive_Buffer
[DATA
+ 1];
146 Data2
= xReceive_Buffer
[DATA
+ 2];
147 Data3
= xReceive_Buffer
[DATA
+ 3];
148 for (uint32_t i
= 0; i
< 3; i
++) {
149 Opt
[i
] = unpack_uint32(&xReceive_Buffer
[DATA
+ 4 * (i
+ 1)]);
152 Command
= Command
& 0b00011111;
154 if (EchoReqFlag
== 1) {
155 memcpy(echoBuffer
, xReceive_Buffer
, 64);
159 if (((DeviceState
== BLidle
) && (Data0
< numberOfDevices
))
160 || (DeviceState
== DFUidle
)) {
164 DeviceState
= DFUidle
;
165 currentProgrammingDestination
= devicesTable
[Data0
].programmingType
;
166 currentDeviceCanRead
= devicesTable
[Data0
].readWriteFlags
& 0x01;
167 currentDeviceCanWrite
= devicesTable
[Data0
].readWriteFlags
>> 1
169 currentDevice
= devicesTable
[Data0
];
171 switch (currentProgrammingDestination
) {
173 result
= PIOS_BL_HELPER_FLASH_Ini();
175 case Remote_flash_via_spi
:
179 DeviceState
= Last_operation_failed
;
180 Aditionals
= (uint16_t)Command
;
183 DeviceState
= Last_operation_failed
;
184 Aditionals
= (uint32_t)Command
;
189 if ((DeviceState
== DFUidle
) || (DeviceState
== uploading
)) {
190 if ((StartFlag
== 1) && (Next_Packet
== 0)) {
191 TransferType
= Data0
;
192 SizeOfTransfer
= Count
;
194 Expected_CRC
= unpack_uint32(&xReceive_Buffer
[DATA
+ 2]);
195 SizeOfLastPacket
= Data1
;
197 if (isBiggerThanAvailable(TransferType
, (SizeOfTransfer
- 1)
198 * 14 * 4 + SizeOfLastPacket
* 4) == true) {
199 DeviceState
= outsideDevCapabilities
;
200 Aditionals
= (uint32_t)Command
;
203 if (TransferType
== FW
) {
204 switch (currentProgrammingDestination
) {
206 result
= PIOS_BL_HELPER_FLASH_Start();
208 case Remote_flash_via_spi
:
216 DeviceState
= Last_operation_failed
;
217 Aditionals
= (uint32_t)Command
;
219 DeviceState
= uploading
;
222 } else if ((StartFlag
!= 1) && (Next_Packet
!= 0)) {
223 if (Count
> SizeOfTransfer
) {
224 DeviceState
= too_many_packets
;
226 } else if (Count
== Next_Packet
- 1) {
227 uint8_t numberOfWords
= 14;
228 if (Count
== SizeOfTransfer
- 1) { // is this the last packet?
229 numberOfWords
= SizeOfLastPacket
;
234 switch (currentProgrammingDestination
) {
236 for (uint8_t x
= 0; x
< numberOfWords
; ++x
) {
238 Data
= unpack_uint32(&xReceive_Buffer
[DATA
+ offset
]);
239 aux
= baseOfAdressType(TransferType
) + (uint32_t)(
240 Count
* 14 * 4 + x
* 4);
242 for (int retry
= 0; retry
< MAX_WRI_RETRYS
; ++retry
) {
244 result
= (FLASH_ProgramWord(aux
, Data
)
245 == FLASH_COMPLETE
) ? 1 : 0;
250 case Remote_flash_via_spi
:
251 result
= false; // No support for this for the OPLink Mini
258 DeviceState
= Last_operation_failed
;
259 Aditionals
= (uint32_t)Command
;
264 DeviceState
= wrong_packet_received
;
268 DeviceState
= Last_operation_failed
;
269 Aditionals
= (uint32_t)Command
;
273 case Req_Capabilities
:
276 Buffer
[1] = Rep_Capabilities
;
283 Buffer
[7] = numberOfDevices
;
284 uint16_t WRFlags
= 0;
285 for (int x
= 0; x
< numberOfDevices
; ++x
) {
286 WRFlags
= ((devicesTable
[x
].readWriteFlags
<< (x
* 2))
289 Buffer
[8] = WRFlags
>> 8;
292 pack_uint32(devicesTable
[Data0
- 1].sizeOfCode
, &Buffer
[2]);
294 Buffer
[7] = devicesTable
[Data0
- 1].BL_Version
;
295 Buffer
[8] = devicesTable
[Data0
- 1].sizeOfDescription
;
296 Buffer
[9] = devicesTable
[Data0
- 1].devID
;
297 pack_uint32(devicesTable
[Data0
- 1].FW_Crc
, &Buffer
[10]);
298 Buffer
[14] = devicesTable
[Data0
- 1].devID
>> 8;
299 Buffer
[15] = devicesTable
[Data0
- 1].devID
;
301 sendData(Buffer
+ 1, 63);
304 if (Data
== 0x5AFE) {
305 /* Force board into safe mode */
306 PIOS_IAP_WriteBootCount(0xFFFF);
308 // pass any Opt value to the firmware
309 PIOS_IAP_WriteBootCmd(0, Opt
[0]);
310 PIOS_IAP_WriteBootCmd(1, Opt
[1]);
311 PIOS_IAP_WriteBootCmd(2, Opt
[2]);
319 case Abort_Operation
:
321 DeviceState
= DFUidle
;
325 if (DeviceState
== uploading
) {
326 if (Next_Packet
- 1 == SizeOfTransfer
) {
328 if ((TransferType
!= FW
) || (Expected_CRC
== CalcFirmCRC())) {
329 DeviceState
= Last_operation_Success
;
331 DeviceState
= CRC_Fail
;
334 if (Next_Packet
- 1 < SizeOfTransfer
) {
336 DeviceState
= too_few_packets
;
341 if (DeviceState
== DFUidle
) {
343 downPacketTotal
= Count
;
344 downSizeOfLastPacket
= Data1
;
345 if (isBiggerThanAvailable(downType
, (downPacketTotal
- 1) * 14
346 + downSizeOfLastPacket
) == 1) {
347 DeviceState
= outsideDevCapabilities
;
348 Aditionals
= (uint32_t)Command
;
350 downPacketCurrent
= 0;
351 DeviceState
= downloading
;
354 DeviceState
= Last_operation_failed
;
355 Aditionals
= (uint32_t)Command
;
361 Buffer
[1] = Status_Rep
;
362 if (DeviceState
== wrong_packet_received
) {
363 pack_uint32(Aditionals
, &Buffer
[2]);
366 Buffer
[3] = ((uint16_t)Aditionals
) >> 8;
367 Buffer
[4] = ((uint16_t)Aditionals
);
370 Buffer
[6] = DeviceState
;
374 sendData(Buffer
+ 1, 63);
375 if (DeviceState
== Last_operation_Success
) {
376 DeviceState
= DFUidle
;
383 if (EchoReqFlag
== 1) {
384 echoBuffer
[1] = echoBuffer
[1] | EchoAnsFlag
;
385 sendData(echoBuffer
+ 1, 63);
388 void OPDfuIni(uint8_t discover
)
390 const struct pios_board_info
*bdinfo
= &pios_board_info_blob
;
393 dev
.programmingType
= Self_flash
;
394 dev
.readWriteFlags
= (BOARD_READABLE
| (BOARD_WRITABLE
<< 1));
395 dev
.startOfUserCode
= bdinfo
->fw_base
;
396 dev
.sizeOfCode
= bdinfo
->fw_size
;
397 dev
.sizeOfDescription
= bdinfo
->desc_size
;
398 dev
.BL_Version
= bdinfo
->bl_rev
;
399 dev
.FW_Crc
= CalcFirmCRC();
400 dev
.devID
= (bdinfo
->board_type
<< 8) | (bdinfo
->board_rev
);
401 dev
.devType
= bdinfo
->hw_type
;
403 devicesTable
[0] = dev
;
405 // TODO check other devices trough spi or whatever
408 uint32_t baseOfAdressType(DFUTransfer type
)
412 return currentDevice
.startOfUserCode
;
416 return currentDevice
.startOfUserCode
+ currentDevice
.sizeOfCode
;
424 uint8_t isBiggerThanAvailable(DFUTransfer type
, uint32_t size
)
428 return (size
> currentDevice
.sizeOfCode
) ? 1 : 0;
432 return (size
> currentDevice
.sizeOfDescription
) ? 1 : 0;
440 uint32_t CalcFirmCRC()
442 switch (currentProgrammingDestination
) {
444 return PIOS_BL_HELPER_CRC_Memory_Calc();
447 case Remote_flash_via_spi
:
457 void sendData(uint8_t *buf
, uint16_t size
)
459 platform_senddata(buf
, size
);
462 bool flash_read(uint8_t *buffer
, uint32_t adr
, DFUProgType type
)
465 case Remote_flash_via_spi
:
466 return false; // We should not get this for the OPLink Mini
470 for (uint8_t x
= 0; x
< 4; ++x
) {
471 buffer
[x
] = *PIOS_BL_HELPER_FLASH_If_Read(adr
+ x
);