Refactor missing prototypes 2 (#14170)
[betaflight.git] / src / main / io / serial_4way.c
blob552fc5d58c17215e5f5db964099257b7d98d532c
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"
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"
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 #elif defined(AT32F435)
55 #define Bit_RESET 0
56 #endif
58 #define USE_TXRX_LED
60 #ifdef USE_TXRX_LED
61 #define RX_LED_OFF LED0_OFF
62 #define RX_LED_ON LED0_ON
63 #ifdef LED1
64 #define TX_LED_OFF LED1_OFF
65 #define TX_LED_ON LED1_ON
66 #else
67 #define TX_LED_OFF LED0_OFF
68 #define TX_LED_ON LED0_ON
69 #endif
70 #else
71 #define RX_LED_OFF
72 #define RX_LED_ON
73 #define TX_LED_OFF
74 #define TX_LED_ON
75 #endif
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
84 // *** end
86 #if (SERIAL_4WAY_VER_MAIN > 24)
87 #error "beware of SERIAL_4WAY_VER_SUB_1 is uint8_t"
88 #endif
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();
149 escCount = 0;
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);
157 setEscHi(escCount);
158 escCount++;
162 motorDisable();
163 return escCount;
166 void esc4wayRelease(void)
168 while (escCount > 0) {
169 escCount--;
170 IOConfigGPIO(escHardware[escCount].io, IOCFG_AF_PP);
171 setEscLo(escCount);
173 motorEnable();
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
183 // Send Structure
184 // ESC + CMD PARAM_LEN [PARAM (if len > 0)] CRC16_Hi CRC16_Lo
185 // Return
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
193 // RETURN: ACK
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
209 // RETURN: ACK
211 // Reset the Device connected to the Interface
212 #define cmd_DeviceReset 0x35 // '5' reset
213 // RETURN: ACK
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
221 // RETURN: ACK
223 // Erase the whole Device Memory of connected Device
224 #define cmd_DeviceEraseAll 0x38 // '8' erase all
225 // RETURN: ACK
227 // Erase one Page of Device Memory of connected Device
228 #define cmd_DevicePageErase 0x39 // '9' page erase
229 // PARAM: uint8_t APageNumber
230 // RETURN: ACK
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]
242 // RETURN: ACK
244 // Set C2CK low infinite ) permanent Reset state
245 #define cmd_DeviceC2CK_LOW 0x3C // '<'
246 // RETURN: ACK
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]
258 // RETURN: ACK
260 // Set Interface Mode
261 #define cmd_InterfaceSetMode 0x3F // '?'
262 // #define imC2 0
263 // #define imSIL_BLB 1
264 // #define imATM_BLB 2
265 // #define imSK 3
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]
273 //RETURN: ACK
275 // responses
276 #define ACK_OK 0x00
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
293 All rights reserved.
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
304 distribution.
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)
323 int i;
325 crc = crc ^ ((uint16_t)data << 8);
326 for (i=0; i < 8; i++) {
327 if (crc & 0x8000)
328 crc = (crc << 1) ^ 0x1021;
329 else
330 crc <<= 1;
332 return crc;
334 // * End copyright
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;
352 return 1;
353 } else {
354 if (BL_ConnectEx(pDeviceInfo)) {
355 if SILABS_DEVICE_MATCH {
356 CurrentInterfaceMode = imSIL_BLB;
357 return 1;
358 } else if ATMEL_DEVICE_MATCH {
359 CurrentInterfaceMode = imATM_BLB;
360 return 1;
361 } else if ARM_DEVICE_MATCH {
362 CurrentInterfaceMode = imARM_BLB;
363 return 1;
367 #elif defined(USE_SERIAL_4WAY_BLHELI_BOOTLOADER)
368 if (BL_ConnectEx(pDeviceInfo)) {
369 if SILABS_DEVICE_MATCH {
370 CurrentInterfaceMode = imSIL_BLB;
371 return 1;
372 } else if ATMEL_DEVICE_MATCH {
373 CurrentInterfaceMode = imATM_BLB;
374 return 1;
375 } else if ARM_DEVICE_MATCH {
376 CurrentInterfaceMode = imARM_BLB;
377 return 1;
380 #elif defined(USE_SERIAL_4WAY_SK_BOOTLOADER)
381 if (Stk_ConnectEx(pDeviceInfo)) {
382 CurrentInterfaceMode = imSK;
383 if ATMEL_DEVICE_MATCH return 1;
385 #endif
387 return 0;
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)) {
398 return true;
401 #else
402 UNUSED(timeoutUs);
404 // Wait indefinitely
405 while (!serialRxBytesWaiting(port));
406 #endif
408 *data = serialRead(port);
410 return false;
413 static uint8_16_u CRC_in;
414 static bool ReadByteCrc(uint8_t *data, timeDelta_t timeoutUs)
416 bool timedOut = ReadByte(data, timeoutUs);
418 if (!timedOut) {
419 CRC_in.word = _crc_xmodem_update(CRC_in.word, *data);
422 return timedOut;
425 static void WriteByte(uint8_t b)
427 serialWrite(port, b);
430 static uint8_16_u CRCout;
431 static void WriteByteCrc(uint8_t b)
433 WriteByte(b);
434 CRCout.word = _crc_xmodem_update(CRCout.word, b);
437 void esc4wayProcess(serialPort_t *mspPort)
439 uint8_t ParamBuf[256];
440 uint8_t ESC;
441 uint8_t I_PARAM_LEN;
442 uint8_t CMD;
443 uint8_t ACK_OUT;
444 uint8_16_u CRC_check;
445 uint8_16_u Dummy;
446 uint8_t O_PARAM_LEN;
447 uint8_t *O_PARAM;
448 uint8_t *InBuff;
449 ioMem_t ioMem;
451 port = mspPort;
453 // Start here with UART Main loop
454 #ifdef USE_BEEPER
455 // fix for buzzer often starts beeping continuously when the ESCs are read
456 // switch beeper silent here
457 beeperSilence();
458 #endif
459 bool isExitScheduled = false;
461 while (1) {
462 bool timedOut = false;
464 // restart looking for new sequence from host
465 do {
466 CRC_in.word = 0;
467 // No timeout as BLHeliSuite32 has this loops sitting indefinitely waiting for input
468 ReadByteCrc(&ESC, 0);
469 } while (ESC != cmd_Local_Escape);
471 RX_LED_ON;
473 Dummy.word = 0;
474 O_PARAM = &Dummy.bytes[0];
475 O_PARAM_LEN = 1;
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);
482 if (!timedOut) {
483 uint8_t i = I_PARAM_LEN;
485 InBuff = ParamBuf;
486 do {
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) {
496 ACK_OUT = ACK_OK;
497 } else {
498 ACK_OUT = ACK_I_INVALID_CRC;
501 TX_LED_ON;
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;
509 switch (CMD) {
510 // ******* Interface related stuff *******
511 case cmd_InterfaceTestAlive:
513 if (isMcuConnected()) {
514 switch (CurrentInterfaceMode)
516 #ifdef USE_SERIAL_4WAY_BLHELI_BOOTLOADER
517 case imATM_BLB:
518 case imSIL_BLB:
519 case imARM_BLB:
521 if (!BL_SendCMDKeepAlive()) { // SetStateDisconnected() included
522 ACK_OUT = ACK_D_GENERAL_ERROR;
524 break;
526 #endif
527 #ifdef USE_SERIAL_4WAY_SK_BOOTLOADER
528 case imSK:
530 if (!Stk_SignOn()) { // SetStateDisconnected();
531 ACK_OUT = ACK_D_GENERAL_ERROR;
533 break;
535 #endif
536 default:
537 ACK_OUT = ACK_D_GENERAL_ERROR;
539 if ( ACK_OUT != ACK_OK) SET_DISCONNECTED;
541 break;
543 case cmd_ProtocolGetVersion:
545 // Only interface itself, no matter what Device
546 Dummy.bytes[0] = SERIAL_4WAY_PROTOCOL_VER;
547 break;
550 case cmd_InterfaceGetName:
552 // Only interface itself, no matter what Device
553 // O_PARAM_LEN=16;
554 O_PARAM_LEN = strlen(SERIAL_4WAY_INTERFACE_NAME_STR);
555 O_PARAM = (uint8_t *)SERIAL_4WAY_INTERFACE_NAME_STR;
556 break;
559 case cmd_InterfaceGetVersion:
561 // Only interface itself, no matter what Device
562 // Dummy = iUart_res_InterfVersion;
563 O_PARAM_LEN = 2;
564 Dummy.bytes[0] = SERIAL_4WAY_VERSION_HI;
565 Dummy.bytes[1] = SERIAL_4WAY_VERSION_LO;
566 break;
568 case cmd_InterfaceExit:
570 isExitScheduled = true;
571 break;
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)
581 #endif
583 CurrentInterfaceMode = ParamBuf[0];
584 } else {
585 ACK_OUT = ACK_I_INVALID_PARAM;
587 break;
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) {
597 rebootEsc = true;
600 else {
601 ACK_OUT = ACK_I_INVALID_CHANNEL;
602 break;
604 switch (CurrentInterfaceMode)
606 case imSIL_BLB:
607 #ifdef USE_SERIAL_4WAY_BLHELI_BOOTLOADER
608 case imATM_BLB:
609 case imARM_BLB:
611 BL_SendCMDRunRestartBootloader(&DeviceInfo);
612 if (rebootEsc) {
613 ESC_OUTPUT;
614 setEscLo(selected_esc);
615 timeMs_t m = millis();
616 while (millis() - m < 300);
617 setEscHi(selected_esc);
618 ESC_INPUT;
620 break;
622 #endif
623 #ifdef USE_SERIAL_4WAY_SK_BOOTLOADER
624 case imSK:
626 break;
628 #endif
630 SET_DISCONNECTED;
631 break;
633 case cmd_DeviceInitFlash:
635 SET_DISCONNECTED;
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];
640 } else {
641 ACK_OUT = ACK_I_INVALID_CHANNEL;
642 break;
644 O_PARAM_LEN = DeviceInfoSize; //4
645 O_PARAM = (uint8_t *)&DeviceInfo;
646 if (Connect(&DeviceInfo)) {
647 DeviceInfo.bytes[INTF_MODE_IDX] = CurrentInterfaceMode;
648 } else {
649 SET_DISCONNECTED;
650 ACK_OUT = ACK_D_GENERAL_ERROR;
652 break;
655 #ifdef USE_SERIAL_4WAY_SK_BOOTLOADER
656 case cmd_DeviceEraseAll:
658 switch (CurrentInterfaceMode)
660 case imSK:
662 if (!Stk_Chip_Erase()) ACK_OUT=ACK_D_GENERAL_ERROR;
663 break;
665 default:
666 ACK_OUT = ACK_I_INVALID_CMD;
668 break;
670 #endif
672 #ifdef USE_SERIAL_4WAY_BLHELI_BOOTLOADER
673 case cmd_DevicePageErase:
675 switch (CurrentInterfaceMode)
677 case imSIL_BLB:
678 case imARM_BLB:
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);
684 } else {
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;
690 break;
692 default:
693 ACK_OUT = ACK_I_INVALID_CMD;
695 break;
697 #endif
699 //*** Device Memory Read Ops ***
700 case cmd_DeviceRead:
702 ioMem.D_NUM_BYTES = ParamBuf[0];
704 wtf.D_FLASH_ADDR_H=Adress_H;
705 wtf.D_FLASH_ADDR_L=Adress_L;
706 wtf.D_PTR_I = BUF_I;
708 switch (CurrentInterfaceMode)
710 #ifdef USE_SERIAL_4WAY_BLHELI_BOOTLOADER
711 case imSIL_BLB:
712 case imATM_BLB:
713 case imARM_BLB:
715 if (!BL_ReadFlash(CurrentInterfaceMode, &ioMem))
717 ACK_OUT = ACK_D_GENERAL_ERROR;
719 break;
721 #endif
722 #ifdef USE_SERIAL_4WAY_SK_BOOTLOADER
723 case imSK:
725 if (!Stk_ReadFlash(&ioMem))
727 ACK_OUT = ACK_D_GENERAL_ERROR;
729 break;
731 #endif
732 default:
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;
740 break;
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;
749 wtf.D_PTR_I = BUF_I;
751 switch (CurrentInterfaceMode)
753 #ifdef USE_SERIAL_4WAY_BLHELI_BOOTLOADER
754 case imATM_BLB:
756 if (!BL_ReadEEprom(&ioMem))
758 ACK_OUT = ACK_D_GENERAL_ERROR;
760 break;
762 #endif
763 #ifdef USE_SERIAL_4WAY_SK_BOOTLOADER
764 case imSK:
766 if (!Stk_ReadEEprom(&ioMem))
768 ACK_OUT = ACK_D_GENERAL_ERROR;
770 break;
772 #endif
773 default:
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;
781 break;
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;
791 wtf.D_PTR_I = BUF_I;
793 switch (CurrentInterfaceMode)
795 #ifdef USE_SERIAL_4WAY_BLHELI_BOOTLOADER
796 case imSIL_BLB:
797 case imATM_BLB:
798 case imARM_BLB:
800 if (!BL_WriteFlash(&ioMem)) {
801 ACK_OUT = ACK_D_GENERAL_ERROR;
803 break;
805 #endif
806 #ifdef USE_SERIAL_4WAY_SK_BOOTLOADER
807 case imSK:
809 if (!Stk_WriteFlash(&ioMem))
811 ACK_OUT = ACK_D_GENERAL_ERROR;
813 break;
815 #endif
817 break;
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;
827 wtf.D_PTR_I = BUF_I;
829 switch (CurrentInterfaceMode)
831 #ifdef USE_SERIAL_4WAY_BLHELI_BOOTLOADER
832 case imSIL_BLB:
834 ACK_OUT = ACK_I_INVALID_CMD;
835 break;
837 case imATM_BLB:
839 if (BL_WriteEEprom(&ioMem))
841 ACK_OUT = ACK_OK;
843 break;
845 #endif
846 #ifdef USE_SERIAL_4WAY_SK_BOOTLOADER
847 case imSK:
849 if (Stk_WriteEEprom(&ioMem))
851 ACK_OUT = ACK_OK;
853 break;
855 #endif
857 break;
859 //*** Device Memory Verify Ops ***
860 #ifdef USE_SERIAL_4WAY_BLHELI_BOOTLOADER
861 case cmd_DeviceVerify:
863 switch (CurrentInterfaceMode)
865 case imARM_BLB:
867 ioMem.D_NUM_BYTES = I_PARAM_LEN;
869 wtf.D_FLASH_ADDR_H=Adress_H;
870 wtf.D_FLASH_ADDR_L=Adress_L;
871 wtf.D_PTR_I = BUF_I;
874 ACK_OUT = BL_VerifyFlash(&ioMem);
875 switch (ACK_OUT) {
876 case brSUCCESS:
877 ACK_OUT = ACK_OK;
878 break;
879 case brERRORVERIFY:
880 ACK_OUT = ACK_I_VERIFY_ERROR;
881 break;
882 default:
883 ACK_OUT = ACK_D_GENERAL_ERROR;
884 break;
886 break;
888 default:
890 ACK_OUT = ACK_I_INVALID_CMD;
891 break;
894 break;
896 #endif
897 default:
899 ACK_OUT = ACK_I_INVALID_CMD;
904 CRCout.word = 0;
906 RX_LED_OFF;
908 serialBeginWrite(port);
909 WriteByteCrc(cmd_Remote_Escape);
910 WriteByteCrc(CMD);
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;
916 do {
917 while (!serialTxBytesFree(port));
919 WriteByteCrc(*O_PARAM);
920 O_PARAM++;
921 i--;
922 } while (i > 0);
924 WriteByteCrc(ACK_OUT);
925 WriteByte(CRCout.bytes[1]);
926 WriteByte(CRCout.bytes[0]);
927 serialEndWrite(port);
929 TX_LED_OFF;
931 if (isExitScheduled) {
932 esc4wayRelease();
933 return;
939 #endif