Merge pull request #11198 from SteveCEvans/sce_rc2
[betaflight.git] / src / main / io / serial_4way.c
blob0648090ea9f4dd601c2e18b481491072c4a6477f
1 /*
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)
8 * any later version.
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/>.
22 * Author: 4712
25 #include <stdbool.h>
26 #include <stdint.h>
27 #include <string.h>
29 #include "platform.h"
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"
47 #endif
48 #if defined(USE_SERIAL_4WAY_SK_BOOTLOADER)
49 #include "io/serial_4way_stk500v2.h"
50 #endif
52 #if defined(USE_HAL_DRIVER)
53 #define Bit_RESET GPIO_PIN_RESET
54 #endif
56 #define USE_TXRX_LED
58 #ifdef USE_TXRX_LED
59 #define RX_LED_OFF LED0_OFF
60 #define RX_LED_ON LED0_ON
61 #ifdef LED1
62 #define TX_LED_OFF LED1_OFF
63 #define TX_LED_ON LED1_ON
64 #else
65 #define TX_LED_OFF LED0_OFF
66 #define TX_LED_ON LED0_ON
67 #endif
68 #else
69 #define RX_LED_OFF
70 #define RX_LED_ON
71 #define TX_LED_OFF
72 #define TX_LED_ON
73 #endif
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) 05
81 #define SERIAL_4WAY_PROTOCOL_VER 108
82 // *** end
84 #if (SERIAL_4WAY_VER_MAIN > 24)
85 #error "beware of SERIAL_4WAY_VER_SUB_1 is uint8_t"
86 #endif
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];
97 uint8_t selected_esc;
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();
142 escCount = 0;
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);
150 setEscHi(escCount);
151 escCount++;
155 motorDisable();
156 return escCount;
159 void esc4wayRelease(void)
161 while (escCount > 0) {
162 escCount--;
163 IOConfigGPIO(escHardware[escCount].io, IOCFG_AF_PP);
164 setEscLo(escCount);
166 motorEnable();
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
177 // Send Structure
178 // ESC + CMD PARAM_LEN [PARAM (if len > 0)] CRC16_Hi CRC16_Lo
179 // Return
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
187 // RETURN: ACK
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
204 // RETURN: ACK
206 // Reset the Device connected to the Interface
207 #define cmd_DeviceReset 0x35 // '5' reset
208 // RETURN: ACK
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
216 // RETURN: ACK
218 // Erase the whole Device Memory of connected Device
219 #define cmd_DeviceEraseAll 0x38 // '8' erase all
220 // RETURN: ACK
222 // Erase one Page of Device Memory of connected Device
223 #define cmd_DevicePageErase 0x39 // '9' page erase
224 // PARAM: uint8_t APageNumber
225 // RETURN: ACK
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]
237 // RETURN: ACK
239 // Set C2CK low infinite ) permanent Reset state
240 #define cmd_DeviceC2CK_LOW 0x3C // '<'
241 // RETURN: ACK
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]
253 // RETURN: ACK
255 // Set Interface Mode
256 #define cmd_InterfaceSetMode 0x3F // '?'
257 // #define imC2 0
258 // #define imSIL_BLB 1
259 // #define imATM_BLB 2
260 // #define imSK 3
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]
268 //RETURN: ACK
271 // responses
272 #define ACK_OK 0x00
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
289 All rights reserved.
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
300 distribution.
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) {
318 int i;
320 crc = crc ^ ((uint16_t)data << 8);
321 for (i=0; i < 8; i++) {
322 if (crc & 0x8000)
323 crc = (crc << 1) ^ 0x1021;
324 else
325 crc <<= 1;
327 return crc;
329 // * End copyright
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] == 0xF310) || (pDeviceInfo->words[0] == 0xF330) || \
336 (pDeviceInfo->words[0] == 0xF410) || (pDeviceInfo->words[0] == 0xF390) || \
337 (pDeviceInfo->words[0] == 0xF850) || (pDeviceInfo->words[0] == 0xE8B1) || \
338 (pDeviceInfo->words[0] == 0xE8B2))
340 // BLHeli_32 MCU ID hi > 0x00 and < 0x90 / lo always = 0x06
341 #define ARM_DEVICE_MATCH ((pDeviceInfo->bytes[1] > 0x00) && (pDeviceInfo->bytes[1] < 0x90) && (pDeviceInfo->bytes[0] == 0x06))
343 static uint8_t CurrentInterfaceMode;
345 static uint8_t Connect(uint8_32_u *pDeviceInfo)
347 for (uint8_t I = 0; I < 3; ++I) {
348 #if (defined(USE_SERIAL_4WAY_BLHELI_BOOTLOADER) && defined(USE_SERIAL_4WAY_SK_BOOTLOADER))
349 if ((CurrentInterfaceMode != imARM_BLB) && Stk_ConnectEx(pDeviceInfo) && ATMEL_DEVICE_MATCH) {
350 CurrentInterfaceMode = imSK;
351 return 1;
352 } else {
353 if (BL_ConnectEx(pDeviceInfo)) {
354 if SILABS_DEVICE_MATCH {
355 CurrentInterfaceMode = imSIL_BLB;
356 return 1;
357 } else if ATMEL_DEVICE_MATCH {
358 CurrentInterfaceMode = imATM_BLB;
359 return 1;
360 } else if ARM_DEVICE_MATCH {
361 CurrentInterfaceMode = imARM_BLB;
362 return 1;
366 #elif defined(USE_SERIAL_4WAY_BLHELI_BOOTLOADER)
367 if (BL_ConnectEx(pDeviceInfo)) {
368 if SILABS_DEVICE_MATCH {
369 CurrentInterfaceMode = imSIL_BLB;
370 return 1;
371 } else if ATMEL_DEVICE_MATCH {
372 CurrentInterfaceMode = imATM_BLB;
373 return 1;
374 } else if ARM_DEVICE_MATCH {
375 CurrentInterfaceMode = imARM_BLB;
376 return 1;
379 #elif defined(USE_SERIAL_4WAY_SK_BOOTLOADER)
380 if (Stk_ConnectEx(pDeviceInfo)) {
381 CurrentInterfaceMode = imSK;
382 if ATMEL_DEVICE_MATCH return 1;
384 #endif
386 return 0;
389 static serialPort_t *port;
391 static uint8_t ReadByte(void)
393 // need timeout?
394 while (!serialRxBytesWaiting(port));
395 return serialRead(port);
398 static uint8_16_u CRC_in;
399 static uint8_t ReadByteCrc(void)
401 uint8_t b = ReadByte();
402 CRC_in.word = _crc_xmodem_update(CRC_in.word, b);
403 return b;
406 static void WriteByte(uint8_t b)
408 serialWrite(port, b);
411 static uint8_16_u CRCout;
412 static void WriteByteCrc(uint8_t b)
414 WriteByte(b);
415 CRCout.word = _crc_xmodem_update(CRCout.word, b);
418 void esc4wayProcess(serialPort_t *mspPort)
421 uint8_t ParamBuf[256];
422 uint8_t ESC;
423 uint8_t I_PARAM_LEN;
424 uint8_t CMD;
425 uint8_t ACK_OUT;
426 uint8_16_u CRC_check;
427 uint8_16_u Dummy;
428 uint8_t O_PARAM_LEN;
429 uint8_t *O_PARAM;
430 uint8_t *InBuff;
431 ioMem_t ioMem;
433 port = mspPort;
435 // Start here with UART Main loop
436 #ifdef USE_BEEPER
437 // fix for buzzer often starts beeping continuously when the ESCs are read
438 // switch beeper silent here
439 beeperSilence();
440 #endif
441 bool isExitScheduled = false;
443 while (1) {
444 // restart looking for new sequence from host
445 do {
446 CRC_in.word = 0;
447 ESC = ReadByteCrc();
448 } while (ESC != cmd_Local_Escape);
450 RX_LED_ON;
452 Dummy.word = 0;
453 O_PARAM = &Dummy.bytes[0];
454 O_PARAM_LEN = 1;
455 CMD = ReadByteCrc();
456 ioMem.D_FLASH_ADDR_H = ReadByteCrc();
457 ioMem.D_FLASH_ADDR_L = ReadByteCrc();
458 I_PARAM_LEN = ReadByteCrc();
460 InBuff = ParamBuf;
461 uint8_t i = I_PARAM_LEN;
462 do {
463 *InBuff = ReadByteCrc();
464 InBuff++;
465 i--;
466 } while (i != 0);
468 CRC_check.bytes[1] = ReadByte();
469 CRC_check.bytes[0] = ReadByte();
471 if (CRC_check.word == CRC_in.word) {
472 ACK_OUT = ACK_OK;
473 } else {
474 ACK_OUT = ACK_I_INVALID_CRC;
477 TX_LED_ON;
479 if (ACK_OUT == ACK_OK)
481 // wtf.D_FLASH_ADDR_H=Adress_H;
482 // wtf.D_FLASH_ADDR_L=Adress_L;
483 ioMem.D_PTR_I = ParamBuf;
486 switch (CMD) {
487 // ******* Interface related stuff *******
488 case cmd_InterfaceTestAlive:
490 if (isMcuConnected()) {
491 switch (CurrentInterfaceMode)
493 #ifdef USE_SERIAL_4WAY_BLHELI_BOOTLOADER
494 case imATM_BLB:
495 case imSIL_BLB:
496 case imARM_BLB:
498 if (!BL_SendCMDKeepAlive()) { // SetStateDisconnected() included
499 ACK_OUT = ACK_D_GENERAL_ERROR;
501 break;
503 #endif
504 #ifdef USE_SERIAL_4WAY_SK_BOOTLOADER
505 case imSK:
507 if (!Stk_SignOn()) { // SetStateDisconnected();
508 ACK_OUT = ACK_D_GENERAL_ERROR;
510 break;
512 #endif
513 default:
514 ACK_OUT = ACK_D_GENERAL_ERROR;
516 if ( ACK_OUT != ACK_OK) SET_DISCONNECTED;
518 break;
520 case cmd_ProtocolGetVersion:
522 // Only interface itself, no matter what Device
523 Dummy.bytes[0] = SERIAL_4WAY_PROTOCOL_VER;
524 break;
527 case cmd_InterfaceGetName:
529 // Only interface itself, no matter what Device
530 // O_PARAM_LEN=16;
531 O_PARAM_LEN = strlen(SERIAL_4WAY_INTERFACE_NAME_STR);
532 O_PARAM = (uint8_t *)SERIAL_4WAY_INTERFACE_NAME_STR;
533 break;
536 case cmd_InterfaceGetVersion:
538 // Only interface itself, no matter what Device
539 // Dummy = iUart_res_InterfVersion;
540 O_PARAM_LEN = 2;
541 Dummy.bytes[0] = SERIAL_4WAY_VERSION_HI;
542 Dummy.bytes[1] = SERIAL_4WAY_VERSION_LO;
543 break;
545 case cmd_InterfaceExit:
547 isExitScheduled = true;
548 break;
550 case cmd_InterfaceSetMode:
552 #if defined(USE_SERIAL_4WAY_BLHELI_BOOTLOADER) && defined(USE_SERIAL_4WAY_SK_BOOTLOADER)
553 if ((ParamBuf[0] <= imARM_BLB) && (ParamBuf[0] >= imSIL_BLB)) {
554 #elif defined(USE_SERIAL_4WAY_BLHELI_BOOTLOADER)
555 if (((ParamBuf[0] <= imATM_BLB)||(ParamBuf[0] == imARM_BLB)) && (ParamBuf[0] >= imSIL_BLB)) {
556 #elif defined(USE_SERIAL_4WAY_SK_BOOTLOADER)
557 if (ParamBuf[0] == imSK) {
558 #endif
559 CurrentInterfaceMode = ParamBuf[0];
560 } else {
561 ACK_OUT = ACK_I_INVALID_PARAM;
563 break;
566 case cmd_DeviceReset:
568 bool rebootEsc = false;
569 if (ParamBuf[0] < escCount) {
570 // Channel may change here
571 selected_esc = ParamBuf[0];
572 if (ioMem.D_FLASH_ADDR_L == 1) {
573 rebootEsc = true;
576 else {
577 ACK_OUT = ACK_I_INVALID_CHANNEL;
578 break;
580 switch (CurrentInterfaceMode)
582 case imSIL_BLB:
583 #ifdef USE_SERIAL_4WAY_BLHELI_BOOTLOADER
584 case imATM_BLB:
585 case imARM_BLB:
587 BL_SendCMDRunRestartBootloader(&DeviceInfo);
588 if (rebootEsc) {
589 ESC_OUTPUT;
590 setEscLo(selected_esc);
591 timeMs_t m = millis();
592 while (millis() - m < 300);
593 setEscHi(selected_esc);
594 ESC_INPUT;
596 break;
598 #endif
599 #ifdef USE_SERIAL_4WAY_SK_BOOTLOADER
600 case imSK:
602 break;
604 #endif
606 SET_DISCONNECTED;
607 break;
609 case cmd_DeviceInitFlash:
611 SET_DISCONNECTED;
612 if (ParamBuf[0] < escCount) {
613 //Channel may change here
614 //ESC_LO or ESC_HI; Halt state for prev channel
615 selected_esc = ParamBuf[0];
616 } else {
617 ACK_OUT = ACK_I_INVALID_CHANNEL;
618 break;
620 O_PARAM_LEN = DeviceInfoSize; //4
621 O_PARAM = (uint8_t *)&DeviceInfo;
622 if (Connect(&DeviceInfo)) {
623 DeviceInfo.bytes[INTF_MODE_IDX] = CurrentInterfaceMode;
624 } else {
625 SET_DISCONNECTED;
626 ACK_OUT = ACK_D_GENERAL_ERROR;
628 break;
631 #ifdef USE_SERIAL_4WAY_SK_BOOTLOADER
632 case cmd_DeviceEraseAll:
634 switch (CurrentInterfaceMode)
636 case imSK:
638 if (!Stk_Chip_Erase()) ACK_OUT=ACK_D_GENERAL_ERROR;
639 break;
641 default:
642 ACK_OUT = ACK_I_INVALID_CMD;
644 break;
646 #endif
648 #ifdef USE_SERIAL_4WAY_BLHELI_BOOTLOADER
649 case cmd_DevicePageErase:
651 switch (CurrentInterfaceMode)
653 case imSIL_BLB:
654 case imARM_BLB:
656 Dummy.bytes[0] = ParamBuf[0];
657 if (CurrentInterfaceMode == imARM_BLB) {
658 // Address =Page * 1024
659 ioMem.D_FLASH_ADDR_H = (Dummy.bytes[0] << 2);
660 } else {
661 // Address =Page * 512
662 ioMem.D_FLASH_ADDR_H = (Dummy.bytes[0] << 1);
664 ioMem.D_FLASH_ADDR_L = 0;
665 if (!BL_PageErase(&ioMem)) ACK_OUT = ACK_D_GENERAL_ERROR;
666 break;
668 default:
669 ACK_OUT = ACK_I_INVALID_CMD;
671 break;
673 #endif
675 //*** Device Memory Read Ops ***
676 case cmd_DeviceRead:
678 ioMem.D_NUM_BYTES = ParamBuf[0];
680 wtf.D_FLASH_ADDR_H=Adress_H;
681 wtf.D_FLASH_ADDR_L=Adress_L;
682 wtf.D_PTR_I = BUF_I;
684 switch (CurrentInterfaceMode)
686 #ifdef USE_SERIAL_4WAY_BLHELI_BOOTLOADER
687 case imSIL_BLB:
688 case imATM_BLB:
689 case imARM_BLB:
691 if (!BL_ReadFlash(CurrentInterfaceMode, &ioMem))
693 ACK_OUT = ACK_D_GENERAL_ERROR;
695 break;
697 #endif
698 #ifdef USE_SERIAL_4WAY_SK_BOOTLOADER
699 case imSK:
701 if (!Stk_ReadFlash(&ioMem))
703 ACK_OUT = ACK_D_GENERAL_ERROR;
705 break;
707 #endif
708 default:
709 ACK_OUT = ACK_I_INVALID_CMD;
711 if (ACK_OUT == ACK_OK)
713 O_PARAM_LEN = ioMem.D_NUM_BYTES;
714 O_PARAM = (uint8_t *)&ParamBuf;
716 break;
719 case cmd_DeviceReadEEprom:
721 ioMem.D_NUM_BYTES = ParamBuf[0];
723 wtf.D_FLASH_ADDR_H = Adress_H;
724 wtf.D_FLASH_ADDR_L = Adress_L;
725 wtf.D_PTR_I = BUF_I;
727 switch (CurrentInterfaceMode)
729 #ifdef USE_SERIAL_4WAY_BLHELI_BOOTLOADER
730 case imATM_BLB:
732 if (!BL_ReadEEprom(&ioMem))
734 ACK_OUT = ACK_D_GENERAL_ERROR;
736 break;
738 #endif
739 #ifdef USE_SERIAL_4WAY_SK_BOOTLOADER
740 case imSK:
742 if (!Stk_ReadEEprom(&ioMem))
744 ACK_OUT = ACK_D_GENERAL_ERROR;
746 break;
748 #endif
749 default:
750 ACK_OUT = ACK_I_INVALID_CMD;
752 if (ACK_OUT == ACK_OK)
754 O_PARAM_LEN = ioMem.D_NUM_BYTES;
755 O_PARAM = (uint8_t *)&ParamBuf;
757 break;
760 //*** Device Memory Write Ops ***
761 case cmd_DeviceWrite:
763 ioMem.D_NUM_BYTES = I_PARAM_LEN;
765 wtf.D_FLASH_ADDR_H=Adress_H;
766 wtf.D_FLASH_ADDR_L=Adress_L;
767 wtf.D_PTR_I = BUF_I;
769 switch (CurrentInterfaceMode)
771 #ifdef USE_SERIAL_4WAY_BLHELI_BOOTLOADER
772 case imSIL_BLB:
773 case imATM_BLB:
774 case imARM_BLB:
776 if (!BL_WriteFlash(&ioMem)) {
777 ACK_OUT = ACK_D_GENERAL_ERROR;
779 break;
781 #endif
782 #ifdef USE_SERIAL_4WAY_SK_BOOTLOADER
783 case imSK:
785 if (!Stk_WriteFlash(&ioMem))
787 ACK_OUT = ACK_D_GENERAL_ERROR;
789 break;
791 #endif
793 break;
796 case cmd_DeviceWriteEEprom:
798 ioMem.D_NUM_BYTES = I_PARAM_LEN;
799 ACK_OUT = ACK_D_GENERAL_ERROR;
801 wtf.D_FLASH_ADDR_H=Adress_H;
802 wtf.D_FLASH_ADDR_L=Adress_L;
803 wtf.D_PTR_I = BUF_I;
805 switch (CurrentInterfaceMode)
807 #ifdef USE_SERIAL_4WAY_BLHELI_BOOTLOADER
808 case imSIL_BLB:
810 ACK_OUT = ACK_I_INVALID_CMD;
811 break;
813 case imATM_BLB:
815 if (BL_WriteEEprom(&ioMem))
817 ACK_OUT = ACK_OK;
819 break;
821 #endif
822 #ifdef USE_SERIAL_4WAY_SK_BOOTLOADER
823 case imSK:
825 if (Stk_WriteEEprom(&ioMem))
827 ACK_OUT = ACK_OK;
829 break;
831 #endif
833 break;
835 //*** Device Memory Verify Ops ***
836 #ifdef USE_SERIAL_4WAY_BLHELI_BOOTLOADER
837 case cmd_DeviceVerify:
839 switch (CurrentInterfaceMode)
841 case imARM_BLB:
843 ioMem.D_NUM_BYTES = I_PARAM_LEN;
845 wtf.D_FLASH_ADDR_H=Adress_H;
846 wtf.D_FLASH_ADDR_L=Adress_L;
847 wtf.D_PTR_I = BUF_I;
850 ACK_OUT = BL_VerifyFlash(&ioMem);
851 switch (ACK_OUT) {
852 case brSUCCESS:
853 ACK_OUT = ACK_OK;
854 break;
855 case brERRORVERIFY:
856 ACK_OUT = ACK_I_VERIFY_ERROR;
857 break;
858 default:
859 ACK_OUT = ACK_D_GENERAL_ERROR;
860 break;
862 break;
864 default:
866 ACK_OUT = ACK_I_INVALID_CMD;
867 break;
870 break;
872 #endif
873 default:
875 ACK_OUT = ACK_I_INVALID_CMD;
880 CRCout.word = 0;
882 RX_LED_OFF;
884 serialBeginWrite(port);
885 WriteByteCrc(cmd_Remote_Escape);
886 WriteByteCrc(CMD);
887 WriteByteCrc(ioMem.D_FLASH_ADDR_H);
888 WriteByteCrc(ioMem.D_FLASH_ADDR_L);
889 WriteByteCrc(O_PARAM_LEN);
891 i=O_PARAM_LEN;
892 do {
893 while (!serialTxBytesFree(port));
895 WriteByteCrc(*O_PARAM);
896 O_PARAM++;
897 i--;
898 } while (i > 0);
900 WriteByteCrc(ACK_OUT);
901 WriteByte(CRCout.bytes[1]);
902 WriteByte(CRCout.bytes[0]);
903 serialEndWrite(port);
905 TX_LED_OFF;
906 if (isExitScheduled) {
907 esc4wayRelease();
908 return;
915 #endif