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
)
161 || (DeviceState
== failed_jump
)) {
165 DeviceState
= DFUidle
;
166 currentProgrammingDestination
= devicesTable
[Data0
].programmingType
;
167 currentDeviceCanRead
= devicesTable
[Data0
].readWriteFlags
& 0x01;
168 currentDeviceCanWrite
= devicesTable
[Data0
].readWriteFlags
>> 1
170 currentDevice
= devicesTable
[Data0
];
172 switch (currentProgrammingDestination
) {
174 result
= PIOS_BL_HELPER_FLASH_Ini();
176 case Remote_flash_via_spi
:
180 DeviceState
= Last_operation_failed
;
181 Aditionals
= (uint16_t)Command
;
184 DeviceState
= Last_operation_failed
;
185 Aditionals
= (uint32_t)Command
;
190 if ((DeviceState
== DFUidle
) || (DeviceState
== uploading
)) {
191 if ((StartFlag
== 1) && (Next_Packet
== 0)) {
192 TransferType
= Data0
;
193 SizeOfTransfer
= Count
;
195 Expected_CRC
= unpack_uint32(&xReceive_Buffer
[DATA
+ 2]);
196 SizeOfLastPacket
= Data1
;
198 if (isBiggerThanAvailable(TransferType
, (SizeOfTransfer
- 1)
199 * 14 * 4 + SizeOfLastPacket
* 4) == true) {
200 DeviceState
= outsideDevCapabilities
;
201 Aditionals
= (uint32_t)Command
;
204 if (TransferType
== FW
) {
205 switch (currentProgrammingDestination
) {
207 result
= PIOS_BL_HELPER_FLASH_Start();
209 case Remote_flash_via_spi
:
217 DeviceState
= Last_operation_failed
;
218 Aditionals
= (uint32_t)Command
;
220 DeviceState
= uploading
;
223 } else if ((StartFlag
!= 1) && (Next_Packet
!= 0)) {
224 if (Count
> SizeOfTransfer
) {
225 DeviceState
= too_many_packets
;
227 } else if (Count
== Next_Packet
- 1) {
228 uint8_t numberOfWords
= 14;
229 if (Count
== SizeOfTransfer
- 1) { // is this the last packet?
230 numberOfWords
= SizeOfLastPacket
;
235 switch (currentProgrammingDestination
) {
237 for (uint8_t x
= 0; x
< numberOfWords
; ++x
) {
239 Data
= unpack_uint32(&xReceive_Buffer
[DATA
+ offset
]);
240 aux
= baseOfAdressType(TransferType
) + (uint32_t)(
241 Count
* 14 * 4 + x
* 4);
243 for (int retry
= 0; retry
< MAX_WRI_RETRYS
; ++retry
) {
245 result
= (FLASH_ProgramWord(aux
, Data
)
246 == FLASH_COMPLETE
) ? 1 : 0;
251 case Remote_flash_via_spi
:
252 result
= false; // No support for this for the OPLink Mini
259 DeviceState
= Last_operation_failed
;
260 Aditionals
= (uint32_t)Command
;
265 DeviceState
= wrong_packet_received
;
269 DeviceState
= Last_operation_failed
;
270 Aditionals
= (uint32_t)Command
;
274 case Req_Capabilities
:
277 Buffer
[1] = Rep_Capabilities
;
284 Buffer
[7] = numberOfDevices
;
285 uint16_t WRFlags
= 0;
286 for (int x
= 0; x
< numberOfDevices
; ++x
) {
287 WRFlags
= ((devicesTable
[x
].readWriteFlags
<< (x
* 2))
290 Buffer
[8] = WRFlags
>> 8;
293 pack_uint32(devicesTable
[Data0
- 1].sizeOfCode
, &Buffer
[2]);
295 Buffer
[7] = devicesTable
[Data0
- 1].BL_Version
;
296 Buffer
[8] = devicesTable
[Data0
- 1].sizeOfDescription
;
297 Buffer
[9] = devicesTable
[Data0
- 1].devID
;
298 pack_uint32(devicesTable
[Data0
- 1].FW_Crc
, &Buffer
[10]);
299 Buffer
[14] = devicesTable
[Data0
- 1].devID
>> 8;
300 Buffer
[15] = devicesTable
[Data0
- 1].devID
;
302 sendData(Buffer
+ 1, 63);
305 if (Data
== 0x5AFE) {
306 /* Force board into safe mode */
307 PIOS_IAP_WriteBootCount(0xFFFF);
309 // pass any Opt value to the firmware
310 PIOS_IAP_WriteBootCmd(0, Opt
[0]);
311 PIOS_IAP_WriteBootCmd(1, Opt
[1]);
312 PIOS_IAP_WriteBootCmd(2, Opt
[2]);
320 case Abort_Operation
:
322 DeviceState
= DFUidle
;
326 if (DeviceState
== uploading
) {
327 if (Next_Packet
- 1 == SizeOfTransfer
) {
329 if ((TransferType
!= FW
) || (Expected_CRC
== CalcFirmCRC())) {
330 DeviceState
= Last_operation_Success
;
332 DeviceState
= CRC_Fail
;
335 if (Next_Packet
- 1 < SizeOfTransfer
) {
337 DeviceState
= too_few_packets
;
342 if (DeviceState
== DFUidle
) {
344 downPacketTotal
= Count
;
345 downSizeOfLastPacket
= Data1
;
346 if (isBiggerThanAvailable(downType
, (downPacketTotal
- 1) * 14
347 + downSizeOfLastPacket
) == 1) {
348 DeviceState
= outsideDevCapabilities
;
349 Aditionals
= (uint32_t)Command
;
351 downPacketCurrent
= 0;
352 DeviceState
= downloading
;
355 DeviceState
= Last_operation_failed
;
356 Aditionals
= (uint32_t)Command
;
362 Buffer
[1] = Status_Rep
;
363 if (DeviceState
== wrong_packet_received
) {
364 pack_uint32(Aditionals
, &Buffer
[2]);
367 Buffer
[3] = ((uint16_t)Aditionals
) >> 8;
368 Buffer
[4] = ((uint16_t)Aditionals
);
371 Buffer
[6] = DeviceState
;
375 sendData(Buffer
+ 1, 63);
376 if (DeviceState
== Last_operation_Success
) {
377 DeviceState
= DFUidle
;
384 if (EchoReqFlag
== 1) {
385 echoBuffer
[1] = echoBuffer
[1] | EchoAnsFlag
;
386 sendData(echoBuffer
+ 1, 63);
389 void OPDfuIni(uint8_t discover
)
391 const struct pios_board_info
*bdinfo
= &pios_board_info_blob
;
394 dev
.programmingType
= Self_flash
;
395 dev
.readWriteFlags
= (BOARD_READABLE
| (BOARD_WRITABLE
<< 1));
396 dev
.startOfUserCode
= bdinfo
->fw_base
;
397 dev
.sizeOfCode
= bdinfo
->fw_size
;
398 dev
.sizeOfDescription
= bdinfo
->desc_size
;
399 dev
.BL_Version
= bdinfo
->bl_rev
;
400 dev
.FW_Crc
= CalcFirmCRC();
401 dev
.devID
= (bdinfo
->board_type
<< 8) | (bdinfo
->board_rev
);
402 dev
.devType
= bdinfo
->hw_type
;
404 devicesTable
[0] = dev
;
406 // TODO check other devices trough spi or whatever
409 uint32_t baseOfAdressType(DFUTransfer type
)
413 return currentDevice
.startOfUserCode
;
417 return currentDevice
.startOfUserCode
+ currentDevice
.sizeOfCode
;
425 uint8_t isBiggerThanAvailable(DFUTransfer type
, uint32_t size
)
429 return (size
> currentDevice
.sizeOfCode
) ? 1 : 0;
433 return (size
> currentDevice
.sizeOfDescription
) ? 1 : 0;
441 uint32_t CalcFirmCRC()
443 switch (currentProgrammingDestination
) {
445 return PIOS_BL_HELPER_CRC_Memory_Calc();
448 case Remote_flash_via_spi
:
458 void sendData(uint8_t *buf
, uint16_t size
)
460 platform_senddata(buf
, size
);
463 bool flash_read(uint8_t *buffer
, uint32_t adr
, DFUProgType type
)
466 case Remote_flash_via_spi
:
467 return false; // We should not get this for the OPLink Mini
471 for (uint8_t x
= 0; x
< 4; ++x
) {
472 buffer
[x
] = *PIOS_BL_HELPER_FLASH_If_Read(adr
+ x
);