2 * This file is part of Cleanflight.
4 * Cleanflight is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * Cleanflight is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with Cleanflight. If not, see <http://www.gnu.org/licenses/>.
25 #ifdef USE_SERIAL_4WAY_BLHELI_INTERFACE
27 #include "drivers/buf_writer.h"
28 #include "drivers/io.h"
29 #include "drivers/serial.h"
30 #include "drivers/timer.h"
31 #include "drivers/pwm_mapping.h"
32 #include "drivers/pwm_output.h"
33 #include "drivers/light_led.h"
34 #include "drivers/system.h"
36 #include "flight/mixer.h"
38 #include "io/beeper.h"
39 #include "io/serial_4way.h"
41 #ifdef USE_SERIAL_4WAY_BLHELI_BOOTLOADER
42 #include "io/serial_4way_avrootloader.h"
44 #if defined(USE_SERIAL_4WAY_SK_BOOTLOADER)
45 #include "io/serial_4way_stk500v2.h"
48 #if defined(USE_HAL_DRIVER)
49 #define Bit_RESET GPIO_PIN_RESET
55 #define RX_LED_OFF LED0_OFF
56 #define RX_LED_ON LED0_ON
58 #define TX_LED_OFF LED1_OFF
59 #define TX_LED_ON LED1_ON
61 #define TX_LED_OFF LED0_OFF
62 #define TX_LED_ON LED0_ON
71 #define SERIAL_4WAY_INTERFACE_NAME_STR "m4wFCIntf"
72 // *** change to adapt Revision
73 #define SERIAL_4WAY_VER_MAIN 20
74 #define SERIAL_4WAY_VER_SUB_1 (uint8_t) 0
75 #define SERIAL_4WAY_VER_SUB_2 (uint8_t) 05
77 #define SERIAL_4WAY_PROTOCOL_VER 107
80 #if (SERIAL_4WAY_VER_MAIN > 24)
81 #error "beware of SERIAL_4WAY_VER_SUB_1 is uint8_t"
84 #define SERIAL_4WAY_VERSION (uint16_t) ((SERIAL_4WAY_VER_MAIN * 1000) + (SERIAL_4WAY_VER_SUB_1 * 100) + SERIAL_4WAY_VER_SUB_2)
86 #define SERIAL_4WAY_VERSION_HI (uint8_t) (SERIAL_4WAY_VERSION / 100)
87 #define SERIAL_4WAY_VERSION_LO (uint8_t) (SERIAL_4WAY_VERSION % 100)
89 static uint8_t escCount
;
91 escHardware_t escHardware
[MAX_SUPPORTED_MOTORS
];
95 uint8_32_u DeviceInfo
;
97 #define DeviceInfoSize 4
99 inline bool isMcuConnected(void)
101 return (DeviceInfo
.bytes
[0] > 0);
104 inline bool isEscHi(uint8_t selEsc
)
106 return (IORead(escHardware
[selEsc
].io
) != Bit_RESET
);
108 inline bool isEscLo(uint8_t selEsc
)
110 return (IORead(escHardware
[selEsc
].io
) == Bit_RESET
);
113 inline void setEscHi(uint8_t selEsc
)
115 IOHi(escHardware
[selEsc
].io
);
118 inline void setEscLo(uint8_t selEsc
)
120 IOLo(escHardware
[selEsc
].io
);
123 inline void setEscInput(uint8_t selEsc
)
125 IOConfigGPIO(escHardware
[selEsc
].io
, IOCFG_IPU
);
128 inline void setEscOutput(uint8_t selEsc
)
130 IOConfigGPIO(escHardware
[selEsc
].io
, IOCFG_OUT_PP
);
133 uint8_t esc4wayInit(void)
135 // StopPwmAllMotors();
138 memset(&escHardware
, 0, sizeof(escHardware
));
140 for (int idx
= 0; idx
< getMotorCount(); idx
++) {
141 ioTag_t tag
= pwmGetMotorPinTag(idx
);
142 if (tag
!= IOTAG_NONE
) {
143 escHardware
[escCount
].io
= IOGetByTag(tag
);
144 setEscInput(escCount
);
153 void esc4wayRelease(void)
155 while (escCount
> 0) {
157 IOConfigGPIO(escHardware
[escCount
].io
, IOCFG_AF_PP
);
164 #define SET_DISCONNECTED DeviceInfo.words[0] = 0
166 #define INTF_MODE_IDX 3 // index for DeviceInfostate
168 // Interface related only
169 // establish and test connection to the Interface
172 // ESC + CMD PARAM_LEN [PARAM (if len > 0)] CRC16_Hi CRC16_Lo
174 // ESC CMD PARAM_LEN [PARAM (if len > 0)] + ACK (uint8_t OK or ERR) + CRC16_Hi CRC16_Lo
176 #define cmd_Remote_Escape 0x2E // '.'
177 #define cmd_Local_Escape 0x2F // '/'
179 // Test Interface still present
180 #define cmd_InterfaceTestAlive 0x30 // '0' alive
183 // get Protocol Version Number 01..255
184 #define cmd_ProtocolGetVersion 0x31 // '1' version
185 // RETURN: uint8_t VersionNumber + ACK
187 // get Version String
188 #define cmd_InterfaceGetName 0x32 // '2' name
189 // RETURN: String + ACK
191 //get Version Number 01..255
192 #define cmd_InterfaceGetVersion 0x33 // '3' version
193 // RETURN: uint8_t AVersionNumber + ACK
196 // Exit / Restart Interface - can be used to switch to Box Mode
197 #define cmd_InterfaceExit 0x34 // '4' exit
200 // Reset the Device connected to the Interface
201 #define cmd_DeviceReset 0x35 // '5' reset
204 // Get the Device ID connected
205 // #define cmd_DeviceGetID 0x36 //'6' device id removed since 06/106
206 // RETURN: uint8_t DeviceID + ACK
208 // Initialize Flash Access for Device connected
209 #define cmd_DeviceInitFlash 0x37 // '7' init flash access
212 // Erase the whole Device Memory of connected Device
213 #define cmd_DeviceEraseAll 0x38 // '8' erase all
216 // Erase one Page of Device Memory of connected Device
217 #define cmd_DevicePageErase 0x39 // '9' page erase
218 // PARAM: uint8_t APageNumber
221 // Read to Buffer from Device Memory of connected Device // Buffer Len is Max 256 Bytes
222 // BuffLen = 0 means 256 Bytes
223 #define cmd_DeviceRead 0x3A // ':' read Device
224 // PARAM: uint8_t ADRESS_Hi + ADRESS_Lo + BuffLen[0..255]
225 // RETURN: PARAM: uint8_t ADRESS_Hi + ADRESS_Lo + BUffLen + Buffer[0..255] ACK
227 // Write to Buffer for Device Memory of connected Device // Buffer Len is Max 256 Bytes
228 // BuffLen = 0 means 256 Bytes
229 #define cmd_DeviceWrite 0x3B // ';' write
230 // PARAM: uint8_t ADRESS_Hi + ADRESS_Lo + BUffLen + Buffer[0..255]
233 // Set C2CK low infinite ) permanent Reset state
234 #define cmd_DeviceC2CK_LOW 0x3C // '<'
237 // Read to Buffer from Device Memory of connected Device //Buffer Len is Max 256 Bytes
238 // BuffLen = 0 means 256 Bytes
239 #define cmd_DeviceReadEEprom 0x3D // '=' read Device
240 // PARAM: uint8_t ADRESS_Hi + ADRESS_Lo + BuffLen[0..255]
241 // RETURN: PARAM: uint8_t ADRESS_Hi + ADRESS_Lo + BUffLen + Buffer[0..255] ACK
243 // Write to Buffer for Device Memory of connected Device // Buffer Len is Max 256 Bytes
244 // BuffLen = 0 means 256 Bytes
245 #define cmd_DeviceWriteEEprom 0x3E // '>' write
246 // PARAM: uint8_t ADRESS_Hi + ADRESS_Lo + BUffLen + Buffer[0..255]
249 // Set Interface Mode
250 #define cmd_InterfaceSetMode 0x3F // '?'
252 // #define imSIL_BLB 1
253 // #define imATM_BLB 2
255 // PARAM: uint8_t Mode
256 // RETURN: ACK or ACK_I_INVALID_CHANNEL
258 //Write to Buffer for Verify Device Memory of connected Device //Buffer Len is Max 256 Bytes
259 //BuffLen = 0 means 256 Bytes
260 #define cmd_DeviceVerify 0x40 //'@' write
261 //PARAM: uint8_t ADRESS_Hi + ADRESS_Lo + BUffLen + Buffer[0..255]
267 // #define ACK_I_UNKNOWN_ERROR 0x01
268 #define ACK_I_INVALID_CMD 0x02
269 #define ACK_I_INVALID_CRC 0x03
270 #define ACK_I_VERIFY_ERROR 0x04
271 // #define ACK_D_INVALID_COMMAND 0x05
272 // #define ACK_D_COMMAND_FAILED 0x06
273 // #define ACK_D_UNKNOWN_ERROR 0x07
275 #define ACK_I_INVALID_CHANNEL 0x08
276 #define ACK_I_INVALID_PARAM 0x09
277 #define ACK_D_GENERAL_ERROR 0x0F
279 /* Copyright (c) 2002, 2003, 2004 Marek Michalkiewicz
280 Copyright (c) 2005, 2007 Joerg Wunsch
281 Copyright (c) 2013 Dave Hylands
282 Copyright (c) 2013 Frederic Nadeau
285 Redistribution and use in source and binary forms, with or without
286 modification, are permitted provided that the following conditions are met:
288 * Redistributions of source code must retain the above copyright
289 notice, this list of conditions and the following disclaimer.
291 * Redistributions in binary form must reproduce the above copyright
292 notice, this list of conditions and the following disclaimer in
293 the documentation and/or other materials provided with the
296 * Neither the name of the copyright holders nor the names of
297 contributors may be used to endorse or promote products derived
298 from this software without specific prior written permission.
300 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
301 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
302 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
303 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
304 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
305 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
306 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
307 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
308 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
309 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
310 POSSIBILITY OF SUCH DAMAGE. */
311 uint16_t _crc_xmodem_update (uint16_t crc
, uint8_t data
) {
314 crc
= crc
^ ((uint16_t)data
<< 8);
315 for (i
=0; i
< 8; i
++) {
317 crc
= (crc
<< 1) ^ 0x1021;
326 #define ATMEL_DEVICE_MATCH ((pDeviceInfo->words[0] == 0x9307) || (pDeviceInfo->words[0] == 0x930A) || \
327 (pDeviceInfo->words[0] == 0x930F) || (pDeviceInfo->words[0] == 0x940B))
329 #define SILABS_DEVICE_MATCH ((pDeviceInfo->words[0] == 0xF310)||(pDeviceInfo->words[0] == 0xF330) || \
330 (pDeviceInfo->words[0] == 0xF410) || (pDeviceInfo->words[0] == 0xF390) || \
331 (pDeviceInfo->words[0] == 0xF850) || (pDeviceInfo->words[0] == 0xE8B1) || \
332 (pDeviceInfo->words[0] == 0xE8B2))
334 // BLHeli_32 MCU ID hi > 0x00 and < 0x90 / lo always = 0x06
335 #define ARM_DEVICE_MATCH ((pDeviceInfo->bytes[1] > 0x00) && (pDeviceInfo->bytes[1] < 0x90) && (pDeviceInfo->bytes[0] == 0x06))
337 static uint8_t CurrentInterfaceMode
;
339 static uint8_t Connect(uint8_32_u
*pDeviceInfo
)
341 for (uint8_t I
= 0; I
< 3; ++I
) {
342 #if (defined(USE_SERIAL_4WAY_BLHELI_BOOTLOADER) && defined(USE_SERIAL_4WAY_SK_BOOTLOADER))
343 if ((CurrentInterfaceMode
!= imARM_BLB
) && Stk_ConnectEx(pDeviceInfo
) && ATMEL_DEVICE_MATCH
) {
344 CurrentInterfaceMode
= imSK
;
347 if (BL_ConnectEx(pDeviceInfo
)) {
348 if SILABS_DEVICE_MATCH
{
349 CurrentInterfaceMode
= imSIL_BLB
;
351 } else if ATMEL_DEVICE_MATCH
{
352 CurrentInterfaceMode
= imATM_BLB
;
354 } else if ARM_DEVICE_MATCH
{
355 CurrentInterfaceMode
= imARM_BLB
;
360 #elif defined(USE_SERIAL_4WAY_BLHELI_BOOTLOADER)
361 if (BL_ConnectEx(pDeviceInfo
)) {
362 if SILABS_DEVICE_MATCH
{
363 CurrentInterfaceMode
= imSIL_BLB
;
365 } else if ATMEL_DEVICE_MATCH
{
366 CurrentInterfaceMode
= imATM_BLB
;
368 } else if ARM_DEVICE_MATCH
{
369 CurrentInterfaceMode
= imARM_BLB
;
373 #elif defined(USE_SERIAL_4WAY_SK_BOOTLOADER)
374 if (Stk_ConnectEx(pDeviceInfo
)) {
375 CurrentInterfaceMode
= imSK
;
376 if ATMEL_DEVICE_MATCH
return 1;
383 static serialPort_t
*port
;
385 static uint8_t ReadByte(void)
388 while (!serialRxBytesWaiting(port
));
389 return serialRead(port
);
392 static uint8_16_u CRC_in
;
393 static uint8_t ReadByteCrc(void)
395 uint8_t b
= ReadByte();
396 CRC_in
.word
= _crc_xmodem_update(CRC_in
.word
, b
);
400 static void WriteByte(uint8_t b
)
402 serialWrite(port
, b
);
405 static uint8_16_u CRCout
;
406 static void WriteByteCrc(uint8_t b
)
409 CRCout
.word
= _crc_xmodem_update(CRCout
.word
, b
);
412 void esc4wayProcess(serialPort_t
*mspPort
)
415 uint8_t ParamBuf
[256];
420 uint8_16_u CRC_check
;
429 // Start here with UART Main loop
430 #if defined(BEEPER) || defined(USE_DSHOT)
431 // fix for buzzer often starts beeping continuously when the ESCs are read
432 // switch beeper silent here
435 bool isExitScheduled
= false;
438 // restart looking for new sequence from host
442 } while (ESC
!= cmd_Local_Escape
);
447 O_PARAM
= &Dummy
.bytes
[0];
450 ioMem
.D_FLASH_ADDR_H
= ReadByteCrc();
451 ioMem
.D_FLASH_ADDR_L
= ReadByteCrc();
452 I_PARAM_LEN
= ReadByteCrc();
455 uint8_t i
= I_PARAM_LEN
;
457 *InBuff
= ReadByteCrc();
462 CRC_check
.bytes
[1] = ReadByte();
463 CRC_check
.bytes
[0] = ReadByte();
465 if (CRC_check
.word
== CRC_in
.word
) {
468 ACK_OUT
= ACK_I_INVALID_CRC
;
473 if (ACK_OUT
== ACK_OK
)
475 // wtf.D_FLASH_ADDR_H=Adress_H;
476 // wtf.D_FLASH_ADDR_L=Adress_L;
477 ioMem
.D_PTR_I
= ParamBuf
;
481 // ******* Interface related stuff *******
482 case cmd_InterfaceTestAlive
:
484 if (isMcuConnected()) {
485 switch (CurrentInterfaceMode
)
487 #ifdef USE_SERIAL_4WAY_BLHELI_BOOTLOADER
492 if (!BL_SendCMDKeepAlive()) { // SetStateDisconnected() included
493 ACK_OUT
= ACK_D_GENERAL_ERROR
;
498 #ifdef USE_SERIAL_4WAY_SK_BOOTLOADER
501 if (!Stk_SignOn()) { // SetStateDisconnected();
502 ACK_OUT
= ACK_D_GENERAL_ERROR
;
508 ACK_OUT
= ACK_D_GENERAL_ERROR
;
510 if ( ACK_OUT
!= ACK_OK
) SET_DISCONNECTED
;
514 case cmd_ProtocolGetVersion
:
516 // Only interface itself, no matter what Device
517 Dummy
.bytes
[0] = SERIAL_4WAY_PROTOCOL_VER
;
521 case cmd_InterfaceGetName
:
523 // Only interface itself, no matter what Device
525 O_PARAM_LEN
= strlen(SERIAL_4WAY_INTERFACE_NAME_STR
);
526 O_PARAM
= (uint8_t *)SERIAL_4WAY_INTERFACE_NAME_STR
;
530 case cmd_InterfaceGetVersion
:
532 // Only interface itself, no matter what Device
533 // Dummy = iUart_res_InterfVersion;
535 Dummy
.bytes
[0] = SERIAL_4WAY_VERSION_HI
;
536 Dummy
.bytes
[1] = SERIAL_4WAY_VERSION_LO
;
539 case cmd_InterfaceExit
:
541 isExitScheduled
= true;
544 case cmd_InterfaceSetMode
:
546 #if defined(USE_SERIAL_4WAY_BLHELI_BOOTLOADER) && defined(USE_SERIAL_4WAY_SK_BOOTLOADER)
547 if ((ParamBuf
[0] <= imARM_BLB
) && (ParamBuf
[0] >= imSIL_BLB
)) {
548 #elif defined(USE_SERIAL_4WAY_BLHELI_BOOTLOADER)
549 if (((ParamBuf
[0] <= imATM_BLB
)||(ParamBuf
[0] == imARM_BLB
)) && (ParamBuf
[0] >= imSIL_BLB
)) {
550 #elif defined(USE_SERIAL_4WAY_SK_BOOTLOADER)
551 if (ParamBuf
[0] == imSK
) {
553 CurrentInterfaceMode
= ParamBuf
[0];
555 ACK_OUT
= ACK_I_INVALID_PARAM
;
560 case cmd_DeviceReset
:
562 if (ParamBuf
[0] < escCount
) {
563 // Channel may change here
564 selected_esc
= ParamBuf
[0];
567 ACK_OUT
= ACK_I_INVALID_CHANNEL
;
570 switch (CurrentInterfaceMode
)
573 #ifdef USE_SERIAL_4WAY_BLHELI_BOOTLOADER
577 BL_SendCMDRunRestartBootloader(&DeviceInfo
);
581 #ifdef USE_SERIAL_4WAY_SK_BOOTLOADER
591 case cmd_DeviceInitFlash
:
594 if (ParamBuf
[0] < escCount
) {
595 //Channel may change here
596 //ESC_LO or ESC_HI; Halt state for prev channel
597 selected_esc
= ParamBuf
[0];
599 ACK_OUT
= ACK_I_INVALID_CHANNEL
;
602 O_PARAM_LEN
= DeviceInfoSize
; //4
603 O_PARAM
= (uint8_t *)&DeviceInfo
;
604 if (Connect(&DeviceInfo
)) {
605 DeviceInfo
.bytes
[INTF_MODE_IDX
] = CurrentInterfaceMode
;
608 ACK_OUT
= ACK_D_GENERAL_ERROR
;
613 #ifdef USE_SERIAL_4WAY_SK_BOOTLOADER
614 case cmd_DeviceEraseAll
:
616 switch (CurrentInterfaceMode
)
620 if (!Stk_Chip_Erase()) ACK_OUT
=ACK_D_GENERAL_ERROR
;
624 ACK_OUT
= ACK_I_INVALID_CMD
;
630 #ifdef USE_SERIAL_4WAY_BLHELI_BOOTLOADER
631 case cmd_DevicePageErase
:
633 switch (CurrentInterfaceMode
)
638 Dummy
.bytes
[0] = ParamBuf
[0];
639 if (CurrentInterfaceMode
== imARM_BLB
) {
640 // Address =Page * 1024
641 ioMem
.D_FLASH_ADDR_H
= (Dummy
.bytes
[0] << 2);
643 // Address =Page * 512
644 ioMem
.D_FLASH_ADDR_H
= (Dummy
.bytes
[0] << 1);
646 ioMem
.D_FLASH_ADDR_L
= 0;
647 if (!BL_PageErase(&ioMem
)) ACK_OUT
= ACK_D_GENERAL_ERROR
;
651 ACK_OUT
= ACK_I_INVALID_CMD
;
657 //*** Device Memory Read Ops ***
660 ioMem
.D_NUM_BYTES
= ParamBuf
[0];
662 wtf.D_FLASH_ADDR_H=Adress_H;
663 wtf.D_FLASH_ADDR_L=Adress_L;
666 switch (CurrentInterfaceMode
)
668 #ifdef USE_SERIAL_4WAY_BLHELI_BOOTLOADER
673 if (!BL_ReadFlash(CurrentInterfaceMode
, &ioMem
))
675 ACK_OUT
= ACK_D_GENERAL_ERROR
;
680 #ifdef USE_SERIAL_4WAY_SK_BOOTLOADER
683 if (!Stk_ReadFlash(&ioMem
))
685 ACK_OUT
= ACK_D_GENERAL_ERROR
;
691 ACK_OUT
= ACK_I_INVALID_CMD
;
693 if (ACK_OUT
== ACK_OK
)
695 O_PARAM_LEN
= ioMem
.D_NUM_BYTES
;
696 O_PARAM
= (uint8_t *)&ParamBuf
;
701 case cmd_DeviceReadEEprom
:
703 ioMem
.D_NUM_BYTES
= ParamBuf
[0];
705 wtf.D_FLASH_ADDR_H = Adress_H;
706 wtf.D_FLASH_ADDR_L = Adress_L;
709 switch (CurrentInterfaceMode
)
711 #ifdef USE_SERIAL_4WAY_BLHELI_BOOTLOADER
714 if (!BL_ReadEEprom(&ioMem
))
716 ACK_OUT
= ACK_D_GENERAL_ERROR
;
721 #ifdef USE_SERIAL_4WAY_SK_BOOTLOADER
724 if (!Stk_ReadEEprom(&ioMem
))
726 ACK_OUT
= ACK_D_GENERAL_ERROR
;
732 ACK_OUT
= ACK_I_INVALID_CMD
;
734 if (ACK_OUT
== ACK_OK
)
736 O_PARAM_LEN
= ioMem
.D_NUM_BYTES
;
737 O_PARAM
= (uint8_t *)&ParamBuf
;
742 //*** Device Memory Write Ops ***
743 case cmd_DeviceWrite
:
745 ioMem
.D_NUM_BYTES
= I_PARAM_LEN
;
747 wtf.D_FLASH_ADDR_H=Adress_H;
748 wtf.D_FLASH_ADDR_L=Adress_L;
751 switch (CurrentInterfaceMode
)
753 #ifdef USE_SERIAL_4WAY_BLHELI_BOOTLOADER
758 if (!BL_WriteFlash(&ioMem
)) {
759 ACK_OUT
= ACK_D_GENERAL_ERROR
;
764 #ifdef USE_SERIAL_4WAY_SK_BOOTLOADER
767 if (!Stk_WriteFlash(&ioMem
))
769 ACK_OUT
= ACK_D_GENERAL_ERROR
;
778 case cmd_DeviceWriteEEprom
:
780 ioMem
.D_NUM_BYTES
= I_PARAM_LEN
;
781 ACK_OUT
= ACK_D_GENERAL_ERROR
;
783 wtf.D_FLASH_ADDR_H=Adress_H;
784 wtf.D_FLASH_ADDR_L=Adress_L;
787 switch (CurrentInterfaceMode
)
789 #ifdef USE_SERIAL_4WAY_BLHELI_BOOTLOADER
792 ACK_OUT
= ACK_I_INVALID_CMD
;
797 if (BL_WriteEEprom(&ioMem
))
804 #ifdef USE_SERIAL_4WAY_SK_BOOTLOADER
807 if (Stk_WriteEEprom(&ioMem
))
817 //*** Device Memory Verify Ops ***
818 #ifdef USE_SERIAL_4WAY_BLHELI_BOOTLOADER
819 case cmd_DeviceVerify
:
821 switch (CurrentInterfaceMode
)
825 ioMem
.D_NUM_BYTES
= I_PARAM_LEN
;
827 wtf.D_FLASH_ADDR_H=Adress_H;
828 wtf.D_FLASH_ADDR_L=Adress_L;
832 ACK_OUT
= BL_VerifyFlash(&ioMem
);
838 ACK_OUT
= ACK_I_VERIFY_ERROR
;
841 ACK_OUT
= ACK_D_GENERAL_ERROR
;
848 ACK_OUT
= ACK_I_INVALID_CMD
;
857 ACK_OUT
= ACK_I_INVALID_CMD
;
866 serialBeginWrite(port
);
867 WriteByteCrc(cmd_Remote_Escape
);
869 WriteByteCrc(ioMem
.D_FLASH_ADDR_H
);
870 WriteByteCrc(ioMem
.D_FLASH_ADDR_L
);
871 WriteByteCrc(O_PARAM_LEN
);
875 while (!serialTxBytesFree(port
));
877 WriteByteCrc(*O_PARAM
);
882 WriteByteCrc(ACK_OUT
);
883 WriteByte(CRCout
.bytes
[1]);
884 WriteByte(CRCout
.bytes
[0]);
885 serialEndWrite(port
);
888 if (isExitScheduled
) {