2 * This file is part of Cleanflight and Betaflight.
4 * Cleanflight and Betaflight are free software. You can redistribute
5 * this software and/or modify this software under the terms of the
6 * GNU General Public License as published by the Free Software
7 * Foundation, either version 3 of the License, or (at your option)
10 * Cleanflight and Betaflight are distributed in the hope that they
11 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 * See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this software.
18 * If not, see <http://www.gnu.org/licenses/>.
31 #ifdef USE_SERIAL_4WAY_BLHELI_INTERFACE
33 #include "drivers/buf_writer.h"
34 #include "drivers/io.h"
35 #include "drivers/serial.h"
36 #include "drivers/time.h"
37 #include "drivers/timer.h"
38 #include "drivers/light_led.h"
40 #include "flight/mixer.h"
42 #include "io/beeper.h"
43 #include "io/serial_4way.h"
45 #ifdef USE_SERIAL_4WAY_BLHELI_BOOTLOADER
46 #include "io/serial_4way_avrootloader.h"
48 #if defined(USE_SERIAL_4WAY_SK_BOOTLOADER)
49 #include "io/serial_4way_stk500v2.h"
52 #if defined(USE_HAL_DRIVER)
53 #define Bit_RESET GPIO_PIN_RESET
59 #define RX_LED_OFF LED0_OFF
60 #define RX_LED_ON LED0_ON
62 #define TX_LED_OFF LED1_OFF
63 #define TX_LED_ON LED1_ON
65 #define TX_LED_OFF LED0_OFF
66 #define TX_LED_ON LED0_ON
75 #define SERIAL_4WAY_INTERFACE_NAME_STR "m4wFCIntf"
76 // *** change to adapt Revision
77 #define SERIAL_4WAY_VER_MAIN 20
78 #define SERIAL_4WAY_VER_SUB_1 (uint8_t) 0
79 #define SERIAL_4WAY_VER_SUB_2 (uint8_t) 06
81 #define SERIAL_4WAY_PROTOCOL_VER 108
84 #if (SERIAL_4WAY_VER_MAIN > 24)
85 #error "beware of SERIAL_4WAY_VER_SUB_1 is uint8_t"
88 #define SERIAL_4WAY_VERSION (uint16_t) ((SERIAL_4WAY_VER_MAIN * 1000) + (SERIAL_4WAY_VER_SUB_1 * 100) + SERIAL_4WAY_VER_SUB_2)
90 #define SERIAL_4WAY_VERSION_HI (uint8_t) (SERIAL_4WAY_VERSION / 100)
91 #define SERIAL_4WAY_VERSION_LO (uint8_t) (SERIAL_4WAY_VERSION % 100)
93 static uint8_t escCount
;
95 escHardware_t escHardware
[MAX_SUPPORTED_MOTORS
];
99 uint8_32_u DeviceInfo
;
101 #define DeviceInfoSize 4
103 inline bool isMcuConnected(void)
105 return (DeviceInfo
.bytes
[0] > 0);
108 inline bool isEscHi(uint8_t selEsc
)
110 return (IORead(escHardware
[selEsc
].io
) != Bit_RESET
);
112 inline bool isEscLo(uint8_t selEsc
)
114 return (IORead(escHardware
[selEsc
].io
) == Bit_RESET
);
117 inline void setEscHi(uint8_t selEsc
)
119 IOHi(escHardware
[selEsc
].io
);
122 inline void setEscLo(uint8_t selEsc
)
124 IOLo(escHardware
[selEsc
].io
);
127 inline void setEscInput(uint8_t selEsc
)
129 IOConfigGPIO(escHardware
[selEsc
].io
, IOCFG_IPU
);
132 inline void setEscOutput(uint8_t selEsc
)
134 IOConfigGPIO(escHardware
[selEsc
].io
, IOCFG_OUT_PP
);
137 uint8_t esc4wayInit(void)
139 // StopPwmAllMotors();
140 // XXX Review effect of motor refactor
141 //pwmDisableMotors();
143 memset(&escHardware
, 0, sizeof(escHardware
));
144 pwmOutputPort_t
*pwmMotors
= pwmGetMotors();
145 for (volatile uint8_t i
= 0; i
< MAX_SUPPORTED_MOTORS
; i
++) {
146 if (pwmMotors
[i
].enabled
) {
147 if (pwmMotors
[i
].io
!= IO_NONE
) {
148 escHardware
[escCount
].io
= pwmMotors
[i
].io
;
149 setEscInput(escCount
);
159 void esc4wayRelease(void)
161 while (escCount
> 0) {
163 IOConfigGPIO(escHardware
[escCount
].io
, IOCFG_AF_PP
);
170 #define SET_DISCONNECTED DeviceInfo.words[0] = 0
172 #define INTF_MODE_IDX 3 // index for DeviceInfostate
174 // Interface related only
175 // establish and test connection to the Interface
178 // ESC + CMD PARAM_LEN [PARAM (if len > 0)] CRC16_Hi CRC16_Lo
180 // ESC CMD PARAM_LEN [PARAM (if len > 0)] + ACK (uint8_t OK or ERR) + CRC16_Hi CRC16_Lo
182 #define cmd_Remote_Escape 0x2E // '.'
183 #define cmd_Local_Escape 0x2F // '/'
185 // Test Interface still present
186 #define cmd_InterfaceTestAlive 0x30 // '0' alive
189 // get Protocol Version Number 01..255
190 #define cmd_ProtocolGetVersion 0x31 // '1' version
191 // RETURN: uint8_t VersionNumber + ACK
193 // get Version String
194 #define cmd_InterfaceGetName 0x32 // '2' name
195 // RETURN: String + ACK
197 //get Version Number 01..255
198 #define cmd_InterfaceGetVersion 0x33 // '3' version
199 // RETURN: uint8_t AVersionNumber + ACK
202 // Exit / Restart Interface - can be used to switch to Box Mode
203 #define cmd_InterfaceExit 0x34 // '4' exit
206 // Reset the Device connected to the Interface
207 #define cmd_DeviceReset 0x35 // '5' reset
210 // Get the Device ID connected
211 // #define cmd_DeviceGetID 0x36 //'6' device id removed since 06/106
212 // RETURN: uint8_t DeviceID + ACK
214 // Initialize Flash Access for Device connected
215 #define cmd_DeviceInitFlash 0x37 // '7' init flash access
218 // Erase the whole Device Memory of connected Device
219 #define cmd_DeviceEraseAll 0x38 // '8' erase all
222 // Erase one Page of Device Memory of connected Device
223 #define cmd_DevicePageErase 0x39 // '9' page erase
224 // PARAM: uint8_t APageNumber
227 // Read to Buffer from Device Memory of connected Device // Buffer Len is Max 256 Bytes
228 // BuffLen = 0 means 256 Bytes
229 #define cmd_DeviceRead 0x3A // ':' read Device
230 // PARAM: uint8_t ADRESS_Hi + ADRESS_Lo + BuffLen[0..255]
231 // RETURN: PARAM: uint8_t ADRESS_Hi + ADRESS_Lo + BUffLen + Buffer[0..255] ACK
233 // Write to Buffer for Device Memory of connected Device // Buffer Len is Max 256 Bytes
234 // BuffLen = 0 means 256 Bytes
235 #define cmd_DeviceWrite 0x3B // ';' write
236 // PARAM: uint8_t ADRESS_Hi + ADRESS_Lo + BUffLen + Buffer[0..255]
239 // Set C2CK low infinite ) permanent Reset state
240 #define cmd_DeviceC2CK_LOW 0x3C // '<'
243 // Read to Buffer from Device Memory of connected Device //Buffer Len is Max 256 Bytes
244 // BuffLen = 0 means 256 Bytes
245 #define cmd_DeviceReadEEprom 0x3D // '=' read Device
246 // PARAM: uint8_t ADRESS_Hi + ADRESS_Lo + BuffLen[0..255]
247 // RETURN: PARAM: uint8_t ADRESS_Hi + ADRESS_Lo + BUffLen + Buffer[0..255] ACK
249 // Write to Buffer for Device Memory of connected Device // Buffer Len is Max 256 Bytes
250 // BuffLen = 0 means 256 Bytes
251 #define cmd_DeviceWriteEEprom 0x3E // '>' write
252 // PARAM: uint8_t ADRESS_Hi + ADRESS_Lo + BUffLen + Buffer[0..255]
255 // Set Interface Mode
256 #define cmd_InterfaceSetMode 0x3F // '?'
258 // #define imSIL_BLB 1
259 // #define imATM_BLB 2
261 // PARAM: uint8_t Mode
262 // RETURN: ACK or ACK_I_INVALID_CHANNEL
264 //Write to Buffer for Verify Device Memory of connected Device //Buffer Len is Max 256 Bytes
265 //BuffLen = 0 means 256 Bytes
266 #define cmd_DeviceVerify 0x40 //'@' write
267 //PARAM: uint8_t ADRESS_Hi + ADRESS_Lo + BUffLen + Buffer[0..255]
273 // #define ACK_I_UNKNOWN_ERROR 0x01
274 #define ACK_I_INVALID_CMD 0x02
275 #define ACK_I_INVALID_CRC 0x03
276 #define ACK_I_VERIFY_ERROR 0x04
277 // #define ACK_D_INVALID_COMMAND 0x05
278 // #define ACK_D_COMMAND_FAILED 0x06
279 // #define ACK_D_UNKNOWN_ERROR 0x07
281 #define ACK_I_INVALID_CHANNEL 0x08
282 #define ACK_I_INVALID_PARAM 0x09
283 #define ACK_D_GENERAL_ERROR 0x0F
285 /* Copyright (c) 2002, 2003, 2004 Marek Michalkiewicz
286 Copyright (c) 2005, 2007 Joerg Wunsch
287 Copyright (c) 2013 Dave Hylands
288 Copyright (c) 2013 Frederic Nadeau
291 Redistribution and use in source and binary forms, with or without
292 modification, are permitted provided that the following conditions are met:
294 * Redistributions of source code must retain the above copyright
295 notice, this list of conditions and the following disclaimer.
297 * Redistributions in binary form must reproduce the above copyright
298 notice, this list of conditions and the following disclaimer in
299 the documentation and/or other materials provided with the
302 * Neither the name of the copyright holders nor the names of
303 contributors may be used to endorse or promote products derived
304 from this software without specific prior written permission.
306 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
307 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
308 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
309 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
310 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
311 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
312 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
313 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
314 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
315 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
316 POSSIBILITY OF SUCH DAMAGE. */
317 uint16_t _crc_xmodem_update (uint16_t crc
, uint8_t data
) {
320 crc
= crc
^ ((uint16_t)data
<< 8);
321 for (i
=0; i
< 8; i
++) {
323 crc
= (crc
<< 1) ^ 0x1021;
332 #define ATMEL_DEVICE_MATCH ((pDeviceInfo->words[0] == 0x9307) || (pDeviceInfo->words[0] == 0x930A) || \
333 (pDeviceInfo->words[0] == 0x930F) || (pDeviceInfo->words[0] == 0x940B))
335 #define SILABS_DEVICE_MATCH ((pDeviceInfo->words[0] > 0xE800) && (pDeviceInfo->words[0] < 0xF900))
338 // BLHeli_32 MCU ID hi > 0x00 and < 0x90 / lo always = 0x06
339 #define ARM_DEVICE_MATCH ((pDeviceInfo->bytes[1] > 0x00) && (pDeviceInfo->bytes[1] < 0x90) && (pDeviceInfo->bytes[0] == 0x06))
341 static uint8_t CurrentInterfaceMode
;
343 static uint8_t Connect(uint8_32_u
*pDeviceInfo
)
345 for (uint8_t I
= 0; I
< 3; ++I
) {
346 #if (defined(USE_SERIAL_4WAY_BLHELI_BOOTLOADER) && defined(USE_SERIAL_4WAY_SK_BOOTLOADER))
347 if ((CurrentInterfaceMode
!= imARM_BLB
) && Stk_ConnectEx(pDeviceInfo
) && ATMEL_DEVICE_MATCH
) {
348 CurrentInterfaceMode
= imSK
;
351 if (BL_ConnectEx(pDeviceInfo
)) {
352 if SILABS_DEVICE_MATCH
{
353 CurrentInterfaceMode
= imSIL_BLB
;
355 } else if ATMEL_DEVICE_MATCH
{
356 CurrentInterfaceMode
= imATM_BLB
;
358 } else if ARM_DEVICE_MATCH
{
359 CurrentInterfaceMode
= imARM_BLB
;
364 #elif defined(USE_SERIAL_4WAY_BLHELI_BOOTLOADER)
365 if (BL_ConnectEx(pDeviceInfo
)) {
366 if SILABS_DEVICE_MATCH
{
367 CurrentInterfaceMode
= imSIL_BLB
;
369 } else if ATMEL_DEVICE_MATCH
{
370 CurrentInterfaceMode
= imATM_BLB
;
372 } else if ARM_DEVICE_MATCH
{
373 CurrentInterfaceMode
= imARM_BLB
;
377 #elif defined(USE_SERIAL_4WAY_SK_BOOTLOADER)
378 if (Stk_ConnectEx(pDeviceInfo
)) {
379 CurrentInterfaceMode
= imSK
;
380 if ATMEL_DEVICE_MATCH
return 1;
387 static serialPort_t
*port
;
389 static uint8_t ReadByte(void)
392 while (!serialRxBytesWaiting(port
));
393 return serialRead(port
);
396 static uint8_16_u CRC_in
;
397 static uint8_t ReadByteCrc(void)
399 uint8_t b
= ReadByte();
400 CRC_in
.word
= _crc_xmodem_update(CRC_in
.word
, b
);
404 static void WriteByte(uint8_t b
)
406 serialWrite(port
, b
);
409 static uint8_16_u CRCout
;
410 static void WriteByteCrc(uint8_t b
)
413 CRCout
.word
= _crc_xmodem_update(CRCout
.word
, b
);
416 void esc4wayProcess(serialPort_t
*mspPort
)
419 uint8_t ParamBuf
[256];
424 uint8_16_u CRC_check
;
433 // Start here with UART Main loop
435 // fix for buzzer often starts beeping continuously when the ESCs are read
436 // switch beeper silent here
439 bool isExitScheduled
= false;
442 // restart looking for new sequence from host
446 } while (ESC
!= cmd_Local_Escape
);
451 O_PARAM
= &Dummy
.bytes
[0];
454 ioMem
.D_FLASH_ADDR_H
= ReadByteCrc();
455 ioMem
.D_FLASH_ADDR_L
= ReadByteCrc();
456 I_PARAM_LEN
= ReadByteCrc();
459 uint8_t i
= I_PARAM_LEN
;
461 *InBuff
= ReadByteCrc();
466 CRC_check
.bytes
[1] = ReadByte();
467 CRC_check
.bytes
[0] = ReadByte();
469 if (CRC_check
.word
== CRC_in
.word
) {
472 ACK_OUT
= ACK_I_INVALID_CRC
;
477 if (ACK_OUT
== ACK_OK
)
479 // wtf.D_FLASH_ADDR_H=Adress_H;
480 // wtf.D_FLASH_ADDR_L=Adress_L;
481 ioMem
.D_PTR_I
= ParamBuf
;
485 // ******* Interface related stuff *******
486 case cmd_InterfaceTestAlive
:
488 if (isMcuConnected()) {
489 switch (CurrentInterfaceMode
)
491 #ifdef USE_SERIAL_4WAY_BLHELI_BOOTLOADER
496 if (!BL_SendCMDKeepAlive()) { // SetStateDisconnected() included
497 ACK_OUT
= ACK_D_GENERAL_ERROR
;
502 #ifdef USE_SERIAL_4WAY_SK_BOOTLOADER
505 if (!Stk_SignOn()) { // SetStateDisconnected();
506 ACK_OUT
= ACK_D_GENERAL_ERROR
;
512 ACK_OUT
= ACK_D_GENERAL_ERROR
;
514 if ( ACK_OUT
!= ACK_OK
) SET_DISCONNECTED
;
518 case cmd_ProtocolGetVersion
:
520 // Only interface itself, no matter what Device
521 Dummy
.bytes
[0] = SERIAL_4WAY_PROTOCOL_VER
;
525 case cmd_InterfaceGetName
:
527 // Only interface itself, no matter what Device
529 O_PARAM_LEN
= strlen(SERIAL_4WAY_INTERFACE_NAME_STR
);
530 O_PARAM
= (uint8_t *)SERIAL_4WAY_INTERFACE_NAME_STR
;
534 case cmd_InterfaceGetVersion
:
536 // Only interface itself, no matter what Device
537 // Dummy = iUart_res_InterfVersion;
539 Dummy
.bytes
[0] = SERIAL_4WAY_VERSION_HI
;
540 Dummy
.bytes
[1] = SERIAL_4WAY_VERSION_LO
;
543 case cmd_InterfaceExit
:
545 isExitScheduled
= true;
548 case cmd_InterfaceSetMode
:
550 #if defined(USE_SERIAL_4WAY_BLHELI_BOOTLOADER) && defined(USE_SERIAL_4WAY_SK_BOOTLOADER)
551 if ((ParamBuf
[0] <= imARM_BLB
) && (ParamBuf
[0] >= imSIL_BLB
)) {
552 #elif defined(USE_SERIAL_4WAY_BLHELI_BOOTLOADER)
553 if (((ParamBuf
[0] <= imATM_BLB
)||(ParamBuf
[0] == imARM_BLB
)) && (ParamBuf
[0] >= imSIL_BLB
)) {
554 #elif defined(USE_SERIAL_4WAY_SK_BOOTLOADER)
555 if (ParamBuf
[0] == imSK
) {
557 CurrentInterfaceMode
= ParamBuf
[0];
559 ACK_OUT
= ACK_I_INVALID_PARAM
;
564 case cmd_DeviceReset
:
566 bool rebootEsc
= false;
567 if (ParamBuf
[0] < escCount
) {
568 // Channel may change here
569 selected_esc
= ParamBuf
[0];
570 if (ioMem
.D_FLASH_ADDR_L
== 1) {
575 ACK_OUT
= ACK_I_INVALID_CHANNEL
;
578 switch (CurrentInterfaceMode
)
581 #ifdef USE_SERIAL_4WAY_BLHELI_BOOTLOADER
585 BL_SendCMDRunRestartBootloader(&DeviceInfo
);
588 setEscLo(selected_esc
);
589 timeMs_t m
= millis();
590 while (millis() - m
< 300);
591 setEscHi(selected_esc
);
597 #ifdef USE_SERIAL_4WAY_SK_BOOTLOADER
607 case cmd_DeviceInitFlash
:
610 if (ParamBuf
[0] < escCount
) {
611 //Channel may change here
612 //ESC_LO or ESC_HI; Halt state for prev channel
613 selected_esc
= ParamBuf
[0];
615 ACK_OUT
= ACK_I_INVALID_CHANNEL
;
618 O_PARAM_LEN
= DeviceInfoSize
; //4
619 O_PARAM
= (uint8_t *)&DeviceInfo
;
620 if (Connect(&DeviceInfo
)) {
621 DeviceInfo
.bytes
[INTF_MODE_IDX
] = CurrentInterfaceMode
;
624 ACK_OUT
= ACK_D_GENERAL_ERROR
;
629 #ifdef USE_SERIAL_4WAY_SK_BOOTLOADER
630 case cmd_DeviceEraseAll
:
632 switch (CurrentInterfaceMode
)
636 if (!Stk_Chip_Erase()) ACK_OUT
=ACK_D_GENERAL_ERROR
;
640 ACK_OUT
= ACK_I_INVALID_CMD
;
646 #ifdef USE_SERIAL_4WAY_BLHELI_BOOTLOADER
647 case cmd_DevicePageErase
:
649 switch (CurrentInterfaceMode
)
654 Dummy
.bytes
[0] = ParamBuf
[0];
655 if (CurrentInterfaceMode
== imARM_BLB
) {
656 // Address =Page * 1024
657 ioMem
.D_FLASH_ADDR_H
= (Dummy
.bytes
[0] << 2);
659 // Address =Page * 512
660 ioMem
.D_FLASH_ADDR_H
= (Dummy
.bytes
[0] << 1);
662 ioMem
.D_FLASH_ADDR_L
= 0;
663 if (!BL_PageErase(&ioMem
)) ACK_OUT
= ACK_D_GENERAL_ERROR
;
667 ACK_OUT
= ACK_I_INVALID_CMD
;
673 //*** Device Memory Read Ops ***
676 ioMem
.D_NUM_BYTES
= ParamBuf
[0];
678 wtf.D_FLASH_ADDR_H=Adress_H;
679 wtf.D_FLASH_ADDR_L=Adress_L;
682 switch (CurrentInterfaceMode
)
684 #ifdef USE_SERIAL_4WAY_BLHELI_BOOTLOADER
689 if (!BL_ReadFlash(CurrentInterfaceMode
, &ioMem
))
691 ACK_OUT
= ACK_D_GENERAL_ERROR
;
696 #ifdef USE_SERIAL_4WAY_SK_BOOTLOADER
699 if (!Stk_ReadFlash(&ioMem
))
701 ACK_OUT
= ACK_D_GENERAL_ERROR
;
707 ACK_OUT
= ACK_I_INVALID_CMD
;
709 if (ACK_OUT
== ACK_OK
)
711 O_PARAM_LEN
= ioMem
.D_NUM_BYTES
;
712 O_PARAM
= (uint8_t *)&ParamBuf
;
717 case cmd_DeviceReadEEprom
:
719 ioMem
.D_NUM_BYTES
= ParamBuf
[0];
721 wtf.D_FLASH_ADDR_H = Adress_H;
722 wtf.D_FLASH_ADDR_L = Adress_L;
725 switch (CurrentInterfaceMode
)
727 #ifdef USE_SERIAL_4WAY_BLHELI_BOOTLOADER
730 if (!BL_ReadEEprom(&ioMem
))
732 ACK_OUT
= ACK_D_GENERAL_ERROR
;
737 #ifdef USE_SERIAL_4WAY_SK_BOOTLOADER
740 if (!Stk_ReadEEprom(&ioMem
))
742 ACK_OUT
= ACK_D_GENERAL_ERROR
;
748 ACK_OUT
= ACK_I_INVALID_CMD
;
750 if (ACK_OUT
== ACK_OK
)
752 O_PARAM_LEN
= ioMem
.D_NUM_BYTES
;
753 O_PARAM
= (uint8_t *)&ParamBuf
;
758 //*** Device Memory Write Ops ***
759 case cmd_DeviceWrite
:
761 ioMem
.D_NUM_BYTES
= I_PARAM_LEN
;
763 wtf.D_FLASH_ADDR_H=Adress_H;
764 wtf.D_FLASH_ADDR_L=Adress_L;
767 switch (CurrentInterfaceMode
)
769 #ifdef USE_SERIAL_4WAY_BLHELI_BOOTLOADER
774 if (!BL_WriteFlash(&ioMem
)) {
775 ACK_OUT
= ACK_D_GENERAL_ERROR
;
780 #ifdef USE_SERIAL_4WAY_SK_BOOTLOADER
783 if (!Stk_WriteFlash(&ioMem
))
785 ACK_OUT
= ACK_D_GENERAL_ERROR
;
794 case cmd_DeviceWriteEEprom
:
796 ioMem
.D_NUM_BYTES
= I_PARAM_LEN
;
797 ACK_OUT
= ACK_D_GENERAL_ERROR
;
799 wtf.D_FLASH_ADDR_H=Adress_H;
800 wtf.D_FLASH_ADDR_L=Adress_L;
803 switch (CurrentInterfaceMode
)
805 #ifdef USE_SERIAL_4WAY_BLHELI_BOOTLOADER
808 ACK_OUT
= ACK_I_INVALID_CMD
;
813 if (BL_WriteEEprom(&ioMem
))
820 #ifdef USE_SERIAL_4WAY_SK_BOOTLOADER
823 if (Stk_WriteEEprom(&ioMem
))
833 //*** Device Memory Verify Ops ***
834 #ifdef USE_SERIAL_4WAY_BLHELI_BOOTLOADER
835 case cmd_DeviceVerify
:
837 switch (CurrentInterfaceMode
)
841 ioMem
.D_NUM_BYTES
= I_PARAM_LEN
;
843 wtf.D_FLASH_ADDR_H=Adress_H;
844 wtf.D_FLASH_ADDR_L=Adress_L;
848 ACK_OUT
= BL_VerifyFlash(&ioMem
);
854 ACK_OUT
= ACK_I_VERIFY_ERROR
;
857 ACK_OUT
= ACK_D_GENERAL_ERROR
;
864 ACK_OUT
= ACK_I_INVALID_CMD
;
873 ACK_OUT
= ACK_I_INVALID_CMD
;
882 serialBeginWrite(port
);
883 WriteByteCrc(cmd_Remote_Escape
);
885 WriteByteCrc(ioMem
.D_FLASH_ADDR_H
);
886 WriteByteCrc(ioMem
.D_FLASH_ADDR_L
);
887 WriteByteCrc(O_PARAM_LEN
);
891 while (!serialTxBytesFree(port
));
893 WriteByteCrc(*O_PARAM
);
898 WriteByteCrc(ACK_OUT
);
899 WriteByte(CRCout
.bytes
[1]);
900 WriteByte(CRCout
.bytes
[0]);
901 serialEndWrite(port
);
904 if (isExitScheduled
) {