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"
39 #include "drivers/pwm_output.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
54 #elif defined(AT32F435)
61 #define RX_LED_OFF LED0_OFF
62 #define RX_LED_ON LED0_ON
64 #define TX_LED_OFF LED1_OFF
65 #define TX_LED_ON LED1_ON
67 #define TX_LED_OFF LED0_OFF
68 #define TX_LED_ON LED0_ON
77 #define SERIAL_4WAY_INTERFACE_NAME_STR "m4wFCIntf"
78 // *** change to adapt Revision
79 #define SERIAL_4WAY_VER_MAIN 20
80 #define SERIAL_4WAY_VER_SUB_1 (uint8_t) 0
81 #define SERIAL_4WAY_VER_SUB_2 (uint8_t) 06
83 #define SERIAL_4WAY_PROTOCOL_VER 108
86 #if (SERIAL_4WAY_VER_MAIN > 24)
87 #error "beware of SERIAL_4WAY_VER_SUB_1 is uint8_t"
90 #define SERIAL_4WAY_VERSION (uint16_t) ((SERIAL_4WAY_VER_MAIN * 1000) + (SERIAL_4WAY_VER_SUB_1 * 100) + SERIAL_4WAY_VER_SUB_2)
92 #define SERIAL_4WAY_VERSION_HI (uint8_t) (SERIAL_4WAY_VERSION / 100)
93 #define SERIAL_4WAY_VERSION_LO (uint8_t) (SERIAL_4WAY_VERSION % 100)
95 #define CMD_TIMEOUT_US 50000
96 #define ARG_TIMEOUT_US 25000
97 #define DAT_TIMEOUT_US 10000
98 #define CRC_TIMEOUT_US 10000
100 static uint8_t escCount
;
102 escHardware_t escHardware
[MAX_SUPPORTED_MOTORS
];
104 uint8_t selected_esc
;
106 uint8_32_u DeviceInfo
;
108 #define DeviceInfoSize 4
110 inline bool isMcuConnected(void)
112 return (DeviceInfo
.bytes
[0] > 0);
115 inline bool isEscHi(uint8_t selEsc
)
117 return (IORead(escHardware
[selEsc
].io
) != Bit_RESET
);
119 inline bool isEscLo(uint8_t selEsc
)
121 return (IORead(escHardware
[selEsc
].io
) == Bit_RESET
);
124 inline void setEscHi(uint8_t selEsc
)
126 IOHi(escHardware
[selEsc
].io
);
129 inline void setEscLo(uint8_t selEsc
)
131 IOLo(escHardware
[selEsc
].io
);
134 inline void setEscInput(uint8_t selEsc
)
136 IOConfigGPIO(escHardware
[selEsc
].io
, IOCFG_IPU
);
139 inline void setEscOutput(uint8_t selEsc
)
141 IOConfigGPIO(escHardware
[selEsc
].io
, IOCFG_OUT_PP
);
144 uint8_t esc4wayInit(void)
146 // StopPwmAllMotors();
147 // XXX Review effect of motor refactor
148 //pwmDisableMotors();
150 memset(&escHardware
, 0, sizeof(escHardware
));
151 pwmOutputPort_t
*pwmMotors
= pwmGetMotors();
152 for (volatile uint8_t i
= 0; i
< MAX_SUPPORTED_MOTORS
; i
++) {
153 if (pwmMotors
[i
].enabled
) {
154 if (pwmMotors
[i
].io
!= IO_NONE
) {
155 escHardware
[escCount
].io
= pwmMotors
[i
].io
;
156 setEscInput(escCount
);
166 void esc4wayRelease(void)
168 while (escCount
> 0) {
170 IOConfigGPIO(escHardware
[escCount
].io
, IOCFG_AF_PP
);
176 #define SET_DISCONNECTED DeviceInfo.words[0] = 0
178 #define INTF_MODE_IDX 3 // index for DeviceInfostate
180 // Interface related only
181 // establish and test connection to the Interface
184 // ESC + CMD PARAM_LEN [PARAM (if len > 0)] CRC16_Hi CRC16_Lo
186 // ESC CMD PARAM_LEN [PARAM (if len > 0)] + ACK (uint8_t OK or ERR) + CRC16_Hi CRC16_Lo
188 #define cmd_Remote_Escape 0x2E // '.'
189 #define cmd_Local_Escape 0x2F // '/'
191 // Test Interface still present
192 #define cmd_InterfaceTestAlive 0x30 // '0' alive
195 // get Protocol Version Number 01..255
196 #define cmd_ProtocolGetVersion 0x31 // '1' version
197 // RETURN: uint8_t VersionNumber + ACK
199 // get Version String
200 #define cmd_InterfaceGetName 0x32 // '2' name
201 // RETURN: String + ACK
203 //get Version Number 01..255
204 #define cmd_InterfaceGetVersion 0x33 // '3' version
205 // RETURN: uint8_t AVersionNumber + ACK
207 // Exit / Restart Interface - can be used to switch to Box Mode
208 #define cmd_InterfaceExit 0x34 // '4' exit
211 // Reset the Device connected to the Interface
212 #define cmd_DeviceReset 0x35 // '5' reset
215 // Get the Device ID connected
216 // #define cmd_DeviceGetID 0x36 //'6' device id removed since 06/106
217 // RETURN: uint8_t DeviceID + ACK
219 // Initialize Flash Access for Device connected
220 #define cmd_DeviceInitFlash 0x37 // '7' init flash access
223 // Erase the whole Device Memory of connected Device
224 #define cmd_DeviceEraseAll 0x38 // '8' erase all
227 // Erase one Page of Device Memory of connected Device
228 #define cmd_DevicePageErase 0x39 // '9' page erase
229 // PARAM: uint8_t APageNumber
232 // Read to Buffer from Device Memory of connected Device // Buffer Len is Max 256 Bytes
233 // BuffLen = 0 means 256 Bytes
234 #define cmd_DeviceRead 0x3A // ':' read Device
235 // PARAM: uint8_t ADRESS_Hi + ADRESS_Lo + BuffLen[0..255]
236 // RETURN: PARAM: uint8_t ADRESS_Hi + ADRESS_Lo + BUffLen + Buffer[0..255] ACK
238 // Write to Buffer for Device Memory of connected Device // Buffer Len is Max 256 Bytes
239 // BuffLen = 0 means 256 Bytes
240 #define cmd_DeviceWrite 0x3B // ';' write
241 // PARAM: uint8_t ADRESS_Hi + ADRESS_Lo + BUffLen + Buffer[0..255]
244 // Set C2CK low infinite ) permanent Reset state
245 #define cmd_DeviceC2CK_LOW 0x3C // '<'
248 // Read to Buffer from Device Memory of connected Device //Buffer Len is Max 256 Bytes
249 // BuffLen = 0 means 256 Bytes
250 #define cmd_DeviceReadEEprom 0x3D // '=' read Device
251 // PARAM: uint8_t ADRESS_Hi + ADRESS_Lo + BuffLen[0..255]
252 // RETURN: PARAM: uint8_t ADRESS_Hi + ADRESS_Lo + BUffLen + Buffer[0..255] ACK
254 // Write to Buffer for Device Memory of connected Device // Buffer Len is Max 256 Bytes
255 // BuffLen = 0 means 256 Bytes
256 #define cmd_DeviceWriteEEprom 0x3E // '>' write
257 // PARAM: uint8_t ADRESS_Hi + ADRESS_Lo + BUffLen + Buffer[0..255]
260 // Set Interface Mode
261 #define cmd_InterfaceSetMode 0x3F // '?'
263 // #define imSIL_BLB 1
264 // #define imATM_BLB 2
266 // PARAM: uint8_t Mode
267 // RETURN: ACK or ACK_I_INVALID_CHANNEL
269 //Write to Buffer for Verify Device Memory of connected Device //Buffer Len is Max 256 Bytes
270 //BuffLen = 0 means 256 Bytes
271 #define cmd_DeviceVerify 0x40 //'@' write
272 //PARAM: uint8_t ADRESS_Hi + ADRESS_Lo + BUffLen + Buffer[0..255]
277 // #define ACK_I_UNKNOWN_ERROR 0x01
278 #define ACK_I_INVALID_CMD 0x02
279 #define ACK_I_INVALID_CRC 0x03
280 #define ACK_I_VERIFY_ERROR 0x04
281 // #define ACK_D_INVALID_COMMAND 0x05
282 // #define ACK_D_COMMAND_FAILED 0x06
283 // #define ACK_D_UNKNOWN_ERROR 0x07
285 #define ACK_I_INVALID_CHANNEL 0x08
286 #define ACK_I_INVALID_PARAM 0x09
287 #define ACK_D_GENERAL_ERROR 0x0F
289 /* Copyright (c) 2002, 2003, 2004 Marek Michalkiewicz
290 Copyright (c) 2005, 2007 Joerg Wunsch
291 Copyright (c) 2013 Dave Hylands
292 Copyright (c) 2013 Frederic Nadeau
295 Redistribution and use in source and binary forms, with or without
296 modification, are permitted provided that the following conditions are met:
298 * Redistributions of source code must retain the above copyright
299 notice, this list of conditions and the following disclaimer.
301 * Redistributions in binary form must reproduce the above copyright
302 notice, this list of conditions and the following disclaimer in
303 the documentation and/or other materials provided with the
306 * Neither the name of the copyright holders nor the names of
307 contributors may be used to endorse or promote products derived
308 from this software without specific prior written permission.
310 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
311 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
312 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
313 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
314 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
315 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
316 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
317 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
318 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
319 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
320 POSSIBILITY OF SUCH DAMAGE. */
321 static uint16_t _crc_xmodem_update (uint16_t crc
, uint8_t data
)
325 crc
= crc
^ ((uint16_t)data
<< 8);
326 for (i
=0; i
< 8; i
++) {
328 crc
= (crc
<< 1) ^ 0x1021;
336 #define ATMEL_DEVICE_MATCH ((pDeviceInfo->words[0] == 0x9307) || (pDeviceInfo->words[0] == 0x930A) || \
337 (pDeviceInfo->words[0] == 0x930F) || (pDeviceInfo->words[0] == 0x940B))
339 #define SILABS_DEVICE_MATCH ((pDeviceInfo->words[0] > 0xE800) && (pDeviceInfo->words[0] < 0xF900))
341 // BLHeli_32 MCU ID hi > 0x00 and < 0x90 / lo always = 0x06
342 #define ARM_DEVICE_MATCH ((pDeviceInfo->bytes[1] > 0x00) && (pDeviceInfo->bytes[1] < 0x90) && (pDeviceInfo->bytes[0] == 0x06))
344 static uint8_t CurrentInterfaceMode
;
346 static uint8_t Connect(uint8_32_u
*pDeviceInfo
)
348 for (uint8_t I
= 0; I
< 3; ++I
) {
349 #if (defined(USE_SERIAL_4WAY_BLHELI_BOOTLOADER) && defined(USE_SERIAL_4WAY_SK_BOOTLOADER))
350 if ((CurrentInterfaceMode
!= imARM_BLB
) && Stk_ConnectEx(pDeviceInfo
) && ATMEL_DEVICE_MATCH
) {
351 CurrentInterfaceMode
= imSK
;
354 if (BL_ConnectEx(pDeviceInfo
)) {
355 if SILABS_DEVICE_MATCH
{
356 CurrentInterfaceMode
= imSIL_BLB
;
358 } else if ATMEL_DEVICE_MATCH
{
359 CurrentInterfaceMode
= imATM_BLB
;
361 } else if ARM_DEVICE_MATCH
{
362 CurrentInterfaceMode
= imARM_BLB
;
367 #elif defined(USE_SERIAL_4WAY_BLHELI_BOOTLOADER)
368 if (BL_ConnectEx(pDeviceInfo
)) {
369 if SILABS_DEVICE_MATCH
{
370 CurrentInterfaceMode
= imSIL_BLB
;
372 } else if ATMEL_DEVICE_MATCH
{
373 CurrentInterfaceMode
= imATM_BLB
;
375 } else if ARM_DEVICE_MATCH
{
376 CurrentInterfaceMode
= imARM_BLB
;
380 #elif defined(USE_SERIAL_4WAY_SK_BOOTLOADER)
381 if (Stk_ConnectEx(pDeviceInfo
)) {
382 CurrentInterfaceMode
= imSK
;
383 if ATMEL_DEVICE_MATCH
return 1;
390 static serialPort_t
*port
;
392 static bool ReadByte(uint8_t *data
, timeDelta_t timeoutUs
)
394 #ifdef USE_TIMEOUT_4WAYIF
395 timeUs_t startTime
= micros();
396 while (!serialRxBytesWaiting(port
)) {
397 if (timeoutUs
&& (cmpTimeUs(micros(), startTime
) > timeoutUs
)) {
405 while (!serialRxBytesWaiting(port
));
408 *data
= serialRead(port
);
413 static uint8_16_u CRC_in
;
414 static bool ReadByteCrc(uint8_t *data
, timeDelta_t timeoutUs
)
416 bool timedOut
= ReadByte(data
, timeoutUs
);
419 CRC_in
.word
= _crc_xmodem_update(CRC_in
.word
, *data
);
425 static void WriteByte(uint8_t b
)
427 serialWrite(port
, b
);
430 static uint8_16_u CRCout
;
431 static void WriteByteCrc(uint8_t b
)
434 CRCout
.word
= _crc_xmodem_update(CRCout
.word
, b
);
437 void esc4wayProcess(serialPort_t
*mspPort
)
439 uint8_t ParamBuf
[256];
444 uint8_16_u CRC_check
;
453 // Start here with UART Main loop
455 // fix for buzzer often starts beeping continuously when the ESCs are read
456 // switch beeper silent here
459 bool isExitScheduled
= false;
462 bool timedOut
= false;
464 // restart looking for new sequence from host
467 // No timeout as BLHeliSuite32 has this loops sitting indefinitely waiting for input
468 ReadByteCrc(&ESC
, 0);
469 } while (ESC
!= cmd_Local_Escape
);
474 O_PARAM
= &Dummy
.bytes
[0];
477 timedOut
= ReadByteCrc(&CMD
, CMD_TIMEOUT_US
) ||
478 ReadByteCrc(&ioMem
.D_FLASH_ADDR_H
, ARG_TIMEOUT_US
) ||
479 ReadByteCrc(&ioMem
.D_FLASH_ADDR_L
, ARG_TIMEOUT_US
) ||
480 ReadByteCrc(&I_PARAM_LEN
, ARG_TIMEOUT_US
);
483 uint8_t i
= I_PARAM_LEN
;
487 timedOut
= ReadByteCrc(InBuff
++, DAT_TIMEOUT_US
);
488 } while ((--i
> 0) && !timedOut
);
490 for (int8_t i
= 1; (i
>= 0) && !timedOut
; i
--) {
491 timedOut
= ReadByte(&CRC_check
.bytes
[i
], CRC_TIMEOUT_US
);
495 if ((CRC_check
.word
== CRC_in
.word
) && !timedOut
) {
498 ACK_OUT
= ACK_I_INVALID_CRC
;
503 if (ACK_OUT
== ACK_OK
)
505 // wtf.D_FLASH_ADDR_H=Adress_H;
506 // wtf.D_FLASH_ADDR_L=Adress_L;
507 ioMem
.D_PTR_I
= ParamBuf
;
510 // ******* Interface related stuff *******
511 case cmd_InterfaceTestAlive
:
513 if (isMcuConnected()) {
514 switch (CurrentInterfaceMode
)
516 #ifdef USE_SERIAL_4WAY_BLHELI_BOOTLOADER
521 if (!BL_SendCMDKeepAlive()) { // SetStateDisconnected() included
522 ACK_OUT
= ACK_D_GENERAL_ERROR
;
527 #ifdef USE_SERIAL_4WAY_SK_BOOTLOADER
530 if (!Stk_SignOn()) { // SetStateDisconnected();
531 ACK_OUT
= ACK_D_GENERAL_ERROR
;
537 ACK_OUT
= ACK_D_GENERAL_ERROR
;
539 if ( ACK_OUT
!= ACK_OK
) SET_DISCONNECTED
;
543 case cmd_ProtocolGetVersion
:
545 // Only interface itself, no matter what Device
546 Dummy
.bytes
[0] = SERIAL_4WAY_PROTOCOL_VER
;
550 case cmd_InterfaceGetName
:
552 // Only interface itself, no matter what Device
554 O_PARAM_LEN
= strlen(SERIAL_4WAY_INTERFACE_NAME_STR
);
555 O_PARAM
= (uint8_t *)SERIAL_4WAY_INTERFACE_NAME_STR
;
559 case cmd_InterfaceGetVersion
:
561 // Only interface itself, no matter what Device
562 // Dummy = iUart_res_InterfVersion;
564 Dummy
.bytes
[0] = SERIAL_4WAY_VERSION_HI
;
565 Dummy
.bytes
[1] = SERIAL_4WAY_VERSION_LO
;
568 case cmd_InterfaceExit
:
570 isExitScheduled
= true;
573 case cmd_InterfaceSetMode
:
575 #if defined(USE_SERIAL_4WAY_BLHELI_BOOTLOADER) && defined(USE_SERIAL_4WAY_SK_BOOTLOADER)
576 if ((ParamBuf
[0] <= imARM_BLB
) && (ParamBuf
[0] >= imSIL_BLB
))
577 #elif defined(USE_SERIAL_4WAY_BLHELI_BOOTLOADER)
578 if (((ParamBuf
[0] <= imATM_BLB
)||(ParamBuf
[0] == imARM_BLB
)) && (ParamBuf
[0] >= imSIL_BLB
))
579 #elif defined(USE_SERIAL_4WAY_SK_BOOTLOADER)
580 if (ParamBuf
[0] == imSK
)
583 CurrentInterfaceMode
= ParamBuf
[0];
585 ACK_OUT
= ACK_I_INVALID_PARAM
;
590 case cmd_DeviceReset
:
592 bool rebootEsc
= false;
593 if (ParamBuf
[0] < escCount
) {
594 // Channel may change here
595 selected_esc
= ParamBuf
[0];
596 if (ioMem
.D_FLASH_ADDR_L
== 1) {
601 ACK_OUT
= ACK_I_INVALID_CHANNEL
;
604 switch (CurrentInterfaceMode
)
607 #ifdef USE_SERIAL_4WAY_BLHELI_BOOTLOADER
611 BL_SendCMDRunRestartBootloader(&DeviceInfo
);
614 setEscLo(selected_esc
);
615 timeMs_t m
= millis();
616 while (millis() - m
< 300);
617 setEscHi(selected_esc
);
623 #ifdef USE_SERIAL_4WAY_SK_BOOTLOADER
633 case cmd_DeviceInitFlash
:
636 if (ParamBuf
[0] < escCount
) {
637 //Channel may change here
638 //ESC_LO or ESC_HI; Halt state for prev channel
639 selected_esc
= ParamBuf
[0];
641 ACK_OUT
= ACK_I_INVALID_CHANNEL
;
644 O_PARAM_LEN
= DeviceInfoSize
; //4
645 O_PARAM
= (uint8_t *)&DeviceInfo
;
646 if (Connect(&DeviceInfo
)) {
647 DeviceInfo
.bytes
[INTF_MODE_IDX
] = CurrentInterfaceMode
;
650 ACK_OUT
= ACK_D_GENERAL_ERROR
;
655 #ifdef USE_SERIAL_4WAY_SK_BOOTLOADER
656 case cmd_DeviceEraseAll
:
658 switch (CurrentInterfaceMode
)
662 if (!Stk_Chip_Erase()) ACK_OUT
=ACK_D_GENERAL_ERROR
;
666 ACK_OUT
= ACK_I_INVALID_CMD
;
672 #ifdef USE_SERIAL_4WAY_BLHELI_BOOTLOADER
673 case cmd_DevicePageErase
:
675 switch (CurrentInterfaceMode
)
680 Dummy
.bytes
[0] = ParamBuf
[0];
681 if (CurrentInterfaceMode
== imARM_BLB
) {
682 // Address =Page * 1024
683 ioMem
.D_FLASH_ADDR_H
= (Dummy
.bytes
[0] << 2);
685 // Address =Page * 512
686 ioMem
.D_FLASH_ADDR_H
= (Dummy
.bytes
[0] << 1);
688 ioMem
.D_FLASH_ADDR_L
= 0;
689 if (!BL_PageErase(&ioMem
)) ACK_OUT
= ACK_D_GENERAL_ERROR
;
693 ACK_OUT
= ACK_I_INVALID_CMD
;
699 //*** Device Memory Read Ops ***
702 ioMem
.D_NUM_BYTES
= ParamBuf
[0];
704 wtf.D_FLASH_ADDR_H=Adress_H;
705 wtf.D_FLASH_ADDR_L=Adress_L;
708 switch (CurrentInterfaceMode
)
710 #ifdef USE_SERIAL_4WAY_BLHELI_BOOTLOADER
715 if (!BL_ReadFlash(CurrentInterfaceMode
, &ioMem
))
717 ACK_OUT
= ACK_D_GENERAL_ERROR
;
722 #ifdef USE_SERIAL_4WAY_SK_BOOTLOADER
725 if (!Stk_ReadFlash(&ioMem
))
727 ACK_OUT
= ACK_D_GENERAL_ERROR
;
733 ACK_OUT
= ACK_I_INVALID_CMD
;
735 if (ACK_OUT
== ACK_OK
)
737 O_PARAM_LEN
= ioMem
.D_NUM_BYTES
;
738 O_PARAM
= (uint8_t *)&ParamBuf
;
743 case cmd_DeviceReadEEprom
:
745 ioMem
.D_NUM_BYTES
= ParamBuf
[0];
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
756 if (!BL_ReadEEprom(&ioMem
))
758 ACK_OUT
= ACK_D_GENERAL_ERROR
;
763 #ifdef USE_SERIAL_4WAY_SK_BOOTLOADER
766 if (!Stk_ReadEEprom(&ioMem
))
768 ACK_OUT
= ACK_D_GENERAL_ERROR
;
774 ACK_OUT
= ACK_I_INVALID_CMD
;
776 if (ACK_OUT
== ACK_OK
)
778 O_PARAM_LEN
= ioMem
.D_NUM_BYTES
;
779 O_PARAM
= (uint8_t *)&ParamBuf
;
784 //*** Device Memory Write Ops ***
785 case cmd_DeviceWrite
:
787 ioMem
.D_NUM_BYTES
= I_PARAM_LEN
;
789 wtf.D_FLASH_ADDR_H=Adress_H;
790 wtf.D_FLASH_ADDR_L=Adress_L;
793 switch (CurrentInterfaceMode
)
795 #ifdef USE_SERIAL_4WAY_BLHELI_BOOTLOADER
800 if (!BL_WriteFlash(&ioMem
)) {
801 ACK_OUT
= ACK_D_GENERAL_ERROR
;
806 #ifdef USE_SERIAL_4WAY_SK_BOOTLOADER
809 if (!Stk_WriteFlash(&ioMem
))
811 ACK_OUT
= ACK_D_GENERAL_ERROR
;
820 case cmd_DeviceWriteEEprom
:
822 ioMem
.D_NUM_BYTES
= I_PARAM_LEN
;
823 ACK_OUT
= ACK_D_GENERAL_ERROR
;
825 wtf.D_FLASH_ADDR_H=Adress_H;
826 wtf.D_FLASH_ADDR_L=Adress_L;
829 switch (CurrentInterfaceMode
)
831 #ifdef USE_SERIAL_4WAY_BLHELI_BOOTLOADER
834 ACK_OUT
= ACK_I_INVALID_CMD
;
839 if (BL_WriteEEprom(&ioMem
))
846 #ifdef USE_SERIAL_4WAY_SK_BOOTLOADER
849 if (Stk_WriteEEprom(&ioMem
))
859 //*** Device Memory Verify Ops ***
860 #ifdef USE_SERIAL_4WAY_BLHELI_BOOTLOADER
861 case cmd_DeviceVerify
:
863 switch (CurrentInterfaceMode
)
867 ioMem
.D_NUM_BYTES
= I_PARAM_LEN
;
869 wtf.D_FLASH_ADDR_H=Adress_H;
870 wtf.D_FLASH_ADDR_L=Adress_L;
874 ACK_OUT
= BL_VerifyFlash(&ioMem
);
880 ACK_OUT
= ACK_I_VERIFY_ERROR
;
883 ACK_OUT
= ACK_D_GENERAL_ERROR
;
890 ACK_OUT
= ACK_I_INVALID_CMD
;
899 ACK_OUT
= ACK_I_INVALID_CMD
;
908 serialBeginWrite(port
);
909 WriteByteCrc(cmd_Remote_Escape
);
911 WriteByteCrc(ioMem
.D_FLASH_ADDR_H
);
912 WriteByteCrc(ioMem
.D_FLASH_ADDR_L
);
913 WriteByteCrc(O_PARAM_LEN
);
915 uint8_t i
= O_PARAM_LEN
;
917 while (!serialTxBytesFree(port
));
919 WriteByteCrc(*O_PARAM
);
924 WriteByteCrc(ACK_OUT
);
925 WriteByte(CRCout
.bytes
[1]);
926 WriteByte(CRCout
.bytes
[0]);
927 serialEndWrite(port
);
931 if (isExitScheduled
) {