25 #ifdef USE_SERIAL_4WAY_BLHELI_INTERFACE
29 #include "drivers/buf_writer.h"
30 #include "drivers/io.h"
31 #include "drivers/serial.h"
32 #include "drivers/timer.h"
33 #include "drivers/pwm_output.h"
34 #include "drivers/light_led.h"
35 #include "drivers/system.h"
37 #include "flight/mixer.h"
39 #include "io/beeper.h"
43 #ifdef USE_SERIAL_4WAY_BLHELI_BOOTLOADER
46 #if defined(USE_SERIAL_4WAY_SK_BOOTLOADER)
50 #if defined(USE_HAL_DRIVER)
51 #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"
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) 01
81 #define SERIAL_4WAY_PROTOCOL_VER 107
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;
101 #define DeviceInfoSize 4
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);
129 IOConfigGPIO(escHardware[selEsc].io, IOCFG_IPU);
134 IOConfigGPIO(escHardware[selEsc].io, IOCFG_OUT_PP);
142 memset(&escHardware, 0,
sizeof(escHardware));
143 pwmOutputPort_t *pwmMotors = pwmGetMotors();
144 for (
volatile uint8_t
i = 0;
i < MAX_SUPPORTED_MOTORS;
i++) {
145 if (pwmMotors[
i].enabled) {
146 if (pwmMotors[
i].io != IO_NONE) {
147 escHardware[escCount].
io = pwmMotors[
i].io;
159 while (escCount > 0) {
161 IOConfigGPIO(escHardware[escCount].io, IOCFG_AF_PP);
168 #define SET_DISCONNECTED DeviceInfo.words[0] = 0
170 #define INTF_MODE_IDX 3 // index for DeviceInfostate
180 #define cmd_Remote_Escape 0x2E // '.'
181 #define cmd_Local_Escape 0x2F // '/'
184 #define cmd_InterfaceTestAlive 0x30 // '0' alive
188 #define cmd_ProtocolGetVersion 0x31 // '1' version
192 #define cmd_InterfaceGetName 0x32 // '2' name
196 #define cmd_InterfaceGetVersion 0x33 // '3' version
201 #define cmd_InterfaceExit 0x34 // '4' exit
205 #define cmd_DeviceReset 0x35 // '5' reset
213 #define cmd_DeviceInitFlash 0x37 // '7' init flash access
217 #define cmd_DeviceEraseAll 0x38 // '8' erase all
221 #define cmd_DevicePageErase 0x39 // '9' page erase
227 #define cmd_DeviceRead 0x3A // ':' read Device
233 #define cmd_DeviceWrite 0x3B // ';' write
238 #define cmd_DeviceC2CK_LOW 0x3C // '<'
243 #define cmd_DeviceReadEEprom 0x3D // '=' read Device
249 #define cmd_DeviceWriteEEprom 0x3E // '>' write
254 #define cmd_InterfaceSetMode 0x3F // '?'
264 #define cmd_DeviceVerify 0x40 //'@' write
272 #define ACK_I_INVALID_CMD 0x02
273 #define ACK_I_INVALID_CRC 0x03
274 #define ACK_I_VERIFY_ERROR 0x04
279 #define ACK_I_INVALID_CHANNEL 0x08
280 #define ACK_I_INVALID_PARAM 0x09
281 #define ACK_D_GENERAL_ERROR 0x0F
315 uint16_t _crc_xmodem_update (uint16_t
crc, uint8_t
data) {
318 crc = crc ^ ((uint16_t)data << 8);
319 for (
i=0;
i < 8;
i++){
321 crc = (
crc << 1) ^ 0x1021;
330 #define ATMEL_DEVICE_MATCH ((pDeviceInfo->words[0] == 0x9307) || (pDeviceInfo->words[0] == 0x930A) || \
331 (pDeviceInfo->words[0] == 0x930F) || (pDeviceInfo->words[0] == 0x940B))
333 #define SILABS_DEVICE_MATCH ((pDeviceInfo->words[0] == 0xF310)||(pDeviceInfo->words[0] ==0xF330) || \
334 (pDeviceInfo->words[0] == 0xF410) || (pDeviceInfo->words[0] == 0xF390) || \
335 (pDeviceInfo->words[0] == 0xF850) || (pDeviceInfo->words[0] == 0xE8B1) || \
336 (pDeviceInfo->words[0] == 0xE8B2))
338 #define ARM_DEVICE_MATCH ((pDeviceInfo->words[0] == 0x1F06) || \
339 (pDeviceInfo->words[0] == 0x3306) || (pDeviceInfo->words[0] == 0x3406))
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))
348 CurrentInterfaceMode =
imSK;
352 if SILABS_DEVICE_MATCH {
355 }
else if ATMEL_DEVICE_MATCH {
358 }
else if ARM_DEVICE_MATCH {
364 #elif defined(USE_SERIAL_4WAY_BLHELI_BOOTLOADER)
366 if SILABS_DEVICE_MATCH {
369 }
else if ATMEL_DEVICE_MATCH {
372 }
else if ARM_DEVICE_MATCH {
377 #elif defined(USE_SERIAL_4WAY_SK_BOOTLOADER)
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);
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);
410 static void WriteByteCrc(uint8_t b)
413 CRCout.word = _crc_xmodem_update(CRCout.word, b);
419 uint8_t ParamBuf[256];
439 bool isExitScheduled =
false;
446 }
while (ESC != cmd_Local_Escape);
451 O_PARAM = &Dummy.bytes[0];
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)
490 case cmd_InterfaceTestAlive:
493 switch(CurrentInterfaceMode)
495 #ifdef USE_SERIAL_4WAY_BLHELI_BOOTLOADER
501 ACK_OUT = ACK_D_GENERAL_ERROR;
506 #ifdef USE_SERIAL_4WAY_SK_BOOTLOADER
510 ACK_OUT = ACK_D_GENERAL_ERROR;
516 ACK_OUT = ACK_D_GENERAL_ERROR;
518 if ( ACK_OUT != ACK_OK) SET_DISCONNECTED;
522 case cmd_ProtocolGetVersion:
525 Dummy.bytes[0] = SERIAL_4WAY_PROTOCOL_VER;
529 case cmd_InterfaceGetName:
533 O_PARAM_LEN = strlen(SERIAL_4WAY_INTERFACE_NAME_STR);
534 O_PARAM = (uint8_t *)SERIAL_4WAY_INTERFACE_NAME_STR;
538 case cmd_InterfaceGetVersion:
543 Dummy.bytes[0] = SERIAL_4WAY_VERSION_HI;
544 Dummy.bytes[1] = SERIAL_4WAY_VERSION_LO;
547 case cmd_InterfaceExit:
549 isExitScheduled =
true;
552 case cmd_InterfaceSetMode:
554 #if defined(USE_SERIAL_4WAY_BLHELI_BOOTLOADER) && defined(USE_SERIAL_4WAY_SK_BOOTLOADER)
556 #elif defined(USE_SERIAL_4WAY_BLHELI_BOOTLOADER)
558 #elif defined(USE_SERIAL_4WAY_SK_BOOTLOADER)
559 if (ParamBuf[0] ==
imSK) {
561 CurrentInterfaceMode = ParamBuf[0];
563 ACK_OUT = ACK_I_INVALID_PARAM;
568 case cmd_DeviceReset:
570 if (ParamBuf[0] < escCount) {
575 ACK_OUT = ACK_I_INVALID_CHANNEL;
578 switch (CurrentInterfaceMode)
581 #ifdef USE_SERIAL_4WAY_BLHELI_BOOTLOADER
589 #ifdef USE_SERIAL_4WAY_SK_BOOTLOADER
599 case cmd_DeviceInitFlash:
602 if (ParamBuf[0] < escCount) {
607 ACK_OUT = ACK_I_INVALID_CHANNEL;
610 O_PARAM_LEN = DeviceInfoSize;
611 O_PARAM = (uint8_t *)&DeviceInfo;
612 if(Connect(&DeviceInfo)) {
613 DeviceInfo.bytes[INTF_MODE_IDX] = CurrentInterfaceMode;
616 ACK_OUT = ACK_D_GENERAL_ERROR;
621 #ifdef USE_SERIAL_4WAY_SK_BOOTLOADER
622 case cmd_DeviceEraseAll:
624 switch(CurrentInterfaceMode)
632 ACK_OUT = ACK_I_INVALID_CMD;
638 #ifdef USE_SERIAL_4WAY_BLHELI_BOOTLOADER
639 case cmd_DevicePageErase:
641 switch (CurrentInterfaceMode)
646 Dummy.bytes[0] = ParamBuf[0];
655 if (!
BL_PageErase(&ioMem)) ACK_OUT = ACK_D_GENERAL_ERROR;
659 ACK_OUT = ACK_I_INVALID_CMD;
674 switch(CurrentInterfaceMode)
676 #ifdef USE_SERIAL_4WAY_BLHELI_BOOTLOADER
683 ACK_OUT = ACK_D_GENERAL_ERROR;
688 #ifdef USE_SERIAL_4WAY_SK_BOOTLOADER
693 ACK_OUT = ACK_D_GENERAL_ERROR;
699 ACK_OUT = ACK_I_INVALID_CMD;
701 if (ACK_OUT == ACK_OK)
704 O_PARAM = (uint8_t *)&ParamBuf;
709 case cmd_DeviceReadEEprom:
717 switch (CurrentInterfaceMode)
719 #ifdef USE_SERIAL_4WAY_BLHELI_BOOTLOADER
724 ACK_OUT = ACK_D_GENERAL_ERROR;
729 #ifdef USE_SERIAL_4WAY_SK_BOOTLOADER
734 ACK_OUT = ACK_D_GENERAL_ERROR;
740 ACK_OUT = ACK_I_INVALID_CMD;
742 if(ACK_OUT == ACK_OK)
745 O_PARAM = (uint8_t *)&ParamBuf;
751 case cmd_DeviceWrite:
759 switch (CurrentInterfaceMode)
761 #ifdef USE_SERIAL_4WAY_BLHELI_BOOTLOADER
767 ACK_OUT = ACK_D_GENERAL_ERROR;
772 #ifdef USE_SERIAL_4WAY_SK_BOOTLOADER
777 ACK_OUT = ACK_D_GENERAL_ERROR;
786 case cmd_DeviceWriteEEprom:
789 ACK_OUT = ACK_D_GENERAL_ERROR;
795 switch (CurrentInterfaceMode)
797 #ifdef USE_SERIAL_4WAY_BLHELI_BOOTLOADER
800 ACK_OUT = ACK_I_INVALID_CMD;
812 #ifdef USE_SERIAL_4WAY_SK_BOOTLOADER
826 #ifdef USE_SERIAL_4WAY_BLHELI_BOOTLOADER
827 case cmd_DeviceVerify:
829 switch (CurrentInterfaceMode)
846 ACK_OUT = ACK_I_VERIFY_ERROR;
849 ACK_OUT = ACK_D_GENERAL_ERROR;
856 ACK_OUT = ACK_I_INVALID_CMD;
865 ACK_OUT = ACK_I_INVALID_CMD;
878 serialBeginWrite(port);
879 WriteByteCrc(cmd_Remote_Escape);
883 WriteByteCrc(O_PARAM_LEN);
887 while (!serialTxBytesFree(port));
889 WriteByteCrc(*O_PARAM);
894 WriteByteCrc(ACK_OUT);
895 WriteByte(CRCout.bytes[1]);
896 WriteByte(CRCout.bytes[0]);
897 serialEndWrite(port);
900 if (isExitScheduled) {
uint8_t BL_VerifyFlash(ioMem_t *pMem)
int32_t PIOS_IRQ_Enable(void)
void setEscInput(uint8_t selEsc)
uint8_t esc4wayInit(void)
uint8_t Stk_WriteEEprom(ioMem_t *pMem)
uint8_t BL_ReadEEprom(ioMem_t *pMem)
void setEscHi(uint8_t selEsc)
void BL_SendCMDRunRestartBootloader(uint8_32_u *pDeviceInfo)
uint8_t Stk_WriteFlash(ioMem_t *pMem)
bool isEscLo(uint8_t selEsc)
bool isMcuConnected(void)
uint8_t BL_WriteEEprom(ioMem_t *pMem)
void esc4wayRelease(void)
uint8_t BL_SendCMDKeepAlive(void)
uint8_t data[XFER_BYTES_PER_PACKET]
uint8_t Stk_ConnectEx(uint8_32_u *pDeviceInfo)
uint8_t BL_PageErase(ioMem_t *pMem)
bool isEscHi(uint8_t selEsc)
uint8_t Stk_Chip_Erase(void)
uint8_t Stk_ReadFlash(ioMem_t *pMem)
uint8_t BL_ReadFlash(uint8_t interface_mode, ioMem_t *pMem)
void setEscLo(uint8_t selEsc)
int32_t PIOS_IRQ_Disable(void)
void esc4wayProcess(struct serialPort_s *mspPort)
uint8_t BL_WriteFlash(ioMem_t *pMem)
uint8_t BL_ConnectEx(uint8_32_u *pDeviceInfo)
uint8_t Stk_ReadEEprom(ioMem_t *pMem)
void setEscOutput(uint8_t selEsc)