// // Created by YY on 2019/12/21. // #include #include #include #include "mcu_if.h" #include "../common/apptimer.h" #include "../utils/crc16.h" #include "../defs.h" #include "../jni_log.h" #include "../common/serial_port.h" #include "../rtk_platform/platform.h" #include "../rtk_module/parse_gps.h" #include "../native-lib.h" #include "../rtk_module/virtual_rtk.h" #define DEBUG(fmt, args...) LOGD(" <%s>: " fmt, __func__, ##args) #define MCU_UART UART_1 enum parse_status_t { SYNC_HEAD_ONE, SYNC_HEAD_TWO, GET_ID_HI, GET_ID_LO, GET_LENGTH_HI, GET_LENGTH_LO, GET_PAYLOAD, GET_CRC16_HI, GET_CRC16_LO }; #define ID_CM_APP_BOOT 0x0001 #define ID_MC_MCU_BOOT 0x8001 #define ID_CM_DFU_UPLOAD 0x0002 #define ID_MC_DFU_RSP 0x8002 #define ID_CM_RW_INFO 0x0003 #define ID_MC_RW_INFO_RSP 0x8003 #define ID_CM_MCU_DFU_REQ 0x0004 #define ID_MC_MCU_DFU_RSP 0x8004 #define ID_CM_MCU_DFU_DATA 0x0005 #define ID_CM_MCU_DFU_DATA_CMP 0x0006 #define ID_MC_CAR_INFO2 0x8006 #define ID_MC_CAR_INFO 0x8007 #define ID_MC_RTK_DATA 0x8008 #define ID_CM_RTK_DATA 0x0008 #define ID_CM_READ_RFCARD 0x0009 #define ID_MC_RFCARD_RSP 0x8009 #define ID_CM_SHUTDOWN 0x0020 #define ID_MC_GNSS_DATA 0x800A #define ID_CM_SINAN_CMD_DATA 0x000B static parse_status_t parse_status; static struct { uint16_t id; uint16_t length; uint16_t rx_len; uint8_t buffer[4096 + 4]; uint16_t crc16; }McuPkt; static uint8_t *dfuFile = NULL; static uint8_t dfuFileBitmap[128]; static int dfuFileLength = 0; static int dfuTryCnt = 0; const int DFU_MAX_TRY = 3; const int DFU_FILE_BLOCK_SIZE = 896; static int (*WriteMcu)(int id, const void *buf, int len); static int WriteBluetooth(int id, const void *buf, int len); static void *UartThread1(void *p); static void ParseMcuTimeout(union sigval sig); static void McuCommandEntry(uint16_t id, const uint8_t *data, int length); static void SendDfuFile(int fileLen, int sentLen, int blockLen, const uint8_t *data); static void GoNextDfuLater(union sigval sig); static void GoNextDfu(void); static void ReadCardTimeout(union sigval sig); void McuCommModeSel(int mode) { if (mode == 0) { WriteMcu = WriteSerialPort; } else { WriteMcu = WriteBluetooth; } } void ParseMcuInit(void) { dfuFile = NULL; dfuFileLength = 0; parse_status = SYNC_HEAD_ONE; AppTimer_delete(ParseMcuTimeout); // SendMcuCommand(ID_CM_APP_BOOT, NULL, 0); } static int WriteBluetooth(int id, const void *buf, int len) { SendToBluetooth((uint8_t *)buf, len); return len; } #define PARSE_BUFF_SIZE 4096 static void *UartThread1(void *p) { struct serial_config *cfg = (struct serial_config *) p; int res = InitSerialPort(MCU_UART, cfg->baud, cfg->data_bit, cfg->verify_bit, cfg->stop_bit, cfg->flow_ctrl); DEBUG("Serial %s open %d", cfg->name, res); uint8_t RxBuf[PARSE_BUFF_SIZE]; int RxBufLen = 0; if (res == 0) ParseMcuInit(); while (res == 0) { int ul = ReadSerialPort(MCU_UART, (uint8_t *)RxBuf + RxBufLen, sizeof(RxBuf) - RxBufLen); RxBufLen += ul; /*{ static char buffd[16384]; buffd[0] = 0; int i = 0; for (i = 0; i < ul; i++) { if ((i % 32) == 0) { sprintf(buffd + strlen(buffd), "\n"); } sprintf(buffd + strlen(buffd), "%02X ", RxBuf[i]); if (strlen(buffd) > 800) { DEBUG("%s <- %s...", "UART", buffd); buffd[0] = 0; } } if (strlen(buffd) > 0) DEBUG("%s <- %s", "UART", buffd); }*/ if (RxBufLen > 0) { // DEBUG("RECV LEN %d", RxBufLen); if (Virtual2IsConnected()) { } else { ParseMcu(RxBuf, RxBufLen); } RxBufLen = 0; } } if (res == 0) { UninitSerialPort(MCU_UART); } pthread_exit(NULL); } void ParseMcu(const uint8_t *data, int length) { int x = 0; while (x < length) { uint8_t c = data[x]; switch (parse_status) { case SYNC_HEAD_ONE: if (c == 0x55) { parse_status = SYNC_HEAD_TWO; AppTimer_delete(ParseMcuTimeout); AppTimer_add(ParseMcuTimeout, D_SEC(5)); } x++; break; case SYNC_HEAD_TWO: if (c == 0xAA) { parse_status = GET_ID_HI; } else if (c != 0x55) { parse_status = SYNC_HEAD_ONE; } x++; break; case GET_ID_HI: McuPkt.id = c; parse_status = GET_ID_LO; x++; break; case GET_ID_LO: McuPkt.id <<= 8; McuPkt.id += c; parse_status = GET_LENGTH_HI; x++; break; case GET_LENGTH_HI: McuPkt.rx_len = 0; McuPkt.length = c; parse_status = GET_LENGTH_LO; x++; break; case GET_LENGTH_LO: McuPkt.length <<= 8; McuPkt.length += c; parse_status = GET_PAYLOAD; if (McuPkt.length >= 1500) { DEBUG("Pkt Too large!"); parse_status = SYNC_HEAD_ONE; AppTimer_delete(ParseMcuTimeout); } McuPkt.buffer[0] = HI_UINT16(McuPkt.id); McuPkt.buffer[1] = LO_UINT16(McuPkt.id); McuPkt.buffer[2] = HI_UINT16(McuPkt.length); McuPkt.buffer[3] = LO_UINT16(McuPkt.length); x++; break; case GET_PAYLOAD: if (length - x >= McuPkt.length - McuPkt.rx_len) { memcpy(McuPkt.buffer + 4 + McuPkt.rx_len, data + x, McuPkt.length - McuPkt.rx_len); x += McuPkt.length - McuPkt.rx_len; McuPkt.rx_len = McuPkt.length; parse_status = GET_CRC16_HI; } else { memcpy(McuPkt.buffer + 4 + McuPkt.rx_len, data + x, length - x); McuPkt.rx_len += length - x; x = length; } break; case GET_CRC16_HI: McuPkt.crc16 = c; parse_status = GET_CRC16_LO; x++; break; case GET_CRC16_LO: { McuPkt.crc16 <<= 8; McuPkt.crc16 += c; uint16_t crc16 = CRCCCITT(McuPkt.buffer, McuPkt.length + 4, 0, 0); // DEBUG("mcuif crc16 but 0x%04X exp 0x%04X", McuPkt.crc16, crc16); if (McuPkt.crc16 == crc16) { McuCommandEntry(McuPkt.id, McuPkt.buffer + 4, McuPkt.length); } parse_status = SYNC_HEAD_ONE; AppTimer_delete(ParseMcuTimeout); x++; break; } default: break; } } } void SendMcuCommand(uint16_t id, const uint8_t *data, int length) { uint8_t buffer[2048]; int x = 0; buffer[x++] = 0x55; buffer[x++] = 0xAA; buffer[x++] = HI_UINT16(id); buffer[x++] = LO_UINT16(id); buffer[x++] = HI_UINT16(length); buffer[x++] = LO_UINT16(length); if (data != NULL && length > 0) { memcpy(buffer + x, data, length); x += length; } uint16_t crc16 = CRCCCITT(buffer + 2, length + 4, 0, 0); buffer[x++] = HI_UINT16(crc16); buffer[x++] = LO_UINT16(crc16); WriteMcu(MCU_UART, buffer, x); } void ConfigMCU(bool ayDevice) { if (ayDevice) { McuCommModeSel(0); // TODO static struct serial_config serialConfig; strcpy(serialConfig.name, "/dev/ttyHSL1"); serialConfig.baud = 115200; serialConfig.data_bit = 8; serialConfig.verify_bit = 'N'; serialConfig.stop_bit = 1; serialConfig.flow_ctrl = 0; pthread_t pid; pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);//detached pthread_create(&pid, &attr, UartThread1, &serialConfig); } else { McuCommModeSel(1); } } void SendRtkToMcu(const uint8_t *data, int length) { SendMcuCommand(ID_CM_RTK_DATA, data, length); } static void ParseMcuTimeout(union sigval sig) { AppTimer_delete(ParseMcuTimeout); parse_status = SYNC_HEAD_ONE; } static void sendrtk(union sigval sig) { uint8_t data[486]; memset(data, 0x86, sizeof(data)); SendMcuCommand(ID_CM_RTK_DATA, data, sizeof(data)); SendMcuCommand(ID_CM_READ_RFCARD, NULL, 0); AppTimer_delete(sendrtk); AppTimer_add(sendrtk, D_SEC(1)); } static uint8_t GnssBuf[PARSE_BUFF_SIZE]; static int GnssBufLen = 0; static void McuCommandEntry(uint16_t id, const uint8_t *data, int length) { static int ii = 0; switch (id) { case ID_MC_MCU_BOOT: DEBUG("MCU BOOT"); if (length == 8) { PlatformStatusChanged(CAN_UPDATE_EVT, data, length); } break; case ID_MC_DFU_RSP: DEBUG("ID_MC_DFU_RSP %d len %d", data[0], length); if (data[0] == 0) { // 第一包传输成功 dfuFileBitmap[0] |= 0x01; } else if (data[0] == 10) { // 升级完成 memset(dfuFileBitmap, 0xFF, sizeof(dfuFileBitmap)); } else if (data[0] == 11) { // 放弃传输 UploadDfuFileEnd(); } else if (data[0] == 12) { // 全部重传 memset(dfuFileBitmap, 0, sizeof(dfuFileBitmap)); } else if (data[0] == 13) { // 部分重传,有后续字段 DEBUG("BITMAP %02X %02X %02X %02X %02X", data[1], data[2], data[3], data[4], data[5]); int total = dfuFileLength / DFU_FILE_BLOCK_SIZE + ((dfuFileLength % DFU_FILE_BLOCK_SIZE)?1:0); int a = 0, b = 0; for (int i = 1; i < length; ++i) { for (int j = 0; j < 8; ++j) { if ((data[i] & BV(j))) b++; a++; if (a == total) { i = length; break; } } } DEBUG("BITMAP total %d succ %d", total, b); //memset(dfuFileBitmap, 0, sizeof(dfuFileBitmap)); memcpy(dfuFileBitmap, data + 1, length - 1); if (total % 8) { dfuFileBitmap[total/8] &= ~BV((total%8) - 1); } else { dfuFileBitmap[(total+7)/8 - 1] &= ~BV(7); } // dfuFileBitmap[total/8] &= ~BV(total%8); } dfuTryCnt = 0; AppTimer_delete(GoNextDfuLater); GoNextDfu(); break; case ID_MC_RW_INFO_RSP: break; case ID_MC_MCU_DFU_RSP: break; case ID_MC_CAR_INFO2: // DEBUG("ID_MC_CAR_INFO2 %d", length); if (length > 0) { PlatformStatusChanged(CAR_SENSOR_UPDATE_EVT, data, length); } break; case ID_MC_CAR_INFO: { // DEBUG("ID_MC_CAR_INFO %d", length); if (length > 0) PlatformStatusChanged(MCU_UPDATE_EVT, data, length); break; } case ID_MC_RTK_DATA: DEBUG("ID_MC_RTK_DATA"); break; case ID_MC_RFCARD_RSP: DEBUG("ID_MC_RFCARD_RSP"); AppTimer_delete(ReadCardTimeout); if (length > 0) PlatformStatusChanged(CARD_UPDATE_EVT, data, length); break; case ID_MC_GNSS_DATA: { length = (length > PARSE_BUFF_SIZE - GnssBufLen) ? (PARSE_BUFF_SIZE - GnssBufLen) : length; memcpy(GnssBuf + GnssBufLen, data, length); GnssBufLen += length; if (GnssBufLen > 0) { if (VirtualIsConnected()) { //PC模拟用时 static bool first = false; if (!first) { first = true; uint8_t buff[33] = "emulator"; buff[32] = 1; PlatformStatusChanged(RTK_STATUS_EVT, buff, 33); } GnssBufLen = 0; } else { const uint8_t *ptr = parseGPS(GnssBuf, GnssBuf + GnssBufLen); if (ptr != GnssBuf) { memcpy(GnssBuf, ptr, GnssBufLen - (ptr - GnssBuf)); GnssBufLen -= ptr - GnssBuf; } else if (GnssBufLen == PARSE_BUFF_SIZE) { //填满了,且没有一个\r,都抛弃 DEBUG("Parse GPS error"); GnssBufLen = 0; } } } break; } default: break; } } static void SendDfuFile(int fileLen, int sentLen, int blockLen, const uint8_t *data) { uint8_t buffer[1024]; int x = 0; DEBUG("SendDfuFile fileLen %d sentLen %d blockLen %d", fileLen, sentLen, blockLen); buffer[x++] = BREAK_UINT32(fileLen, 3); buffer[x++] = BREAK_UINT32(fileLen, 2); buffer[x++] = BREAK_UINT32(fileLen, 1); buffer[x++] = BREAK_UINT32(fileLen, 0); buffer[x++] = BREAK_UINT32(sentLen, 3); buffer[x++] = BREAK_UINT32(sentLen, 2); buffer[x++] = BREAK_UINT32(sentLen, 1); buffer[x++] = BREAK_UINT32(sentLen, 0); buffer[x++] = HI_UINT16(blockLen); buffer[x++] = LO_UINT16(blockLen); memcpy(buffer + x, data, blockLen); x += blockLen; SendMcuCommand(ID_CM_DFU_UPLOAD, buffer, x); } static void GoNextDfuLater(union sigval sig) { AppTimer_delete(GoNextDfuLater); GoNextDfu(); } static void GoNextDfu(void) { int dfuFileSent = 0, currDfuBlockLength = 0; if (dfuFileLength == 0 || dfuFile == NULL) return; int row = 0, col = 0; dfuFileSent = dfuFileLength; for (row = 0; row < sizeof(dfuFileBitmap); ++row) { for (col = 0; col < 8; ++col) { if ((dfuFileBitmap[row] & BV(col)) == 0) { DEBUG("ROW = %d COL = %d", row, col); dfuFileSent = row * DFU_FILE_BLOCK_SIZE * 8 + col * DFU_FILE_BLOCK_SIZE; goto GET_FILE_START; } } } GET_FILE_START: currDfuBlockLength = (dfuFileLength - dfuFileSent > DFU_FILE_BLOCK_SIZE) ? DFU_FILE_BLOCK_SIZE : (dfuFileLength - dfuFileSent); if (dfuFileSent >= dfuFileLength || currDfuBlockLength == 0) { UploadDfuFileEnd(); return; } SendDfuFile(dfuFileLength, dfuFileSent, currDfuBlockLength, dfuFile + dfuFileSent); if (dfuFileSent > 0 && dfuFileSent + currDfuBlockLength < dfuFileLength) { dfuFileBitmap[row] |= BV(col); } if (dfuFileSent == 0 || dfuFileSent + currDfuBlockLength == dfuFileLength) { dfuTryCnt++; if (dfuTryCnt > DFU_MAX_TRY) { UploadDfuFileEnd(); return; } DEBUG("GoNextDfuLater 3 sec..."); AppTimer_add(GoNextDfuLater, D_SEC(3)); } else { AppTimer_add(GoNextDfuLater, 10); } } void UploadDfuFileEnd(void) { DEBUG("UploadDfuFileEnd"); if (dfuFile != NULL) free(dfuFile); dfuFileLength = 0; AppTimer_delete(GoNextDfuLater); } void UploadDfuFile(const uint8_t *file, int length) { DEBUG("UploadDfuFile %ld", length); if (length > 0) { if (dfuFile != NULL) free(dfuFile); dfuTryCnt = 0; dfuFile = (uint8_t *) malloc(length); dfuFileLength = length; memcpy(dfuFile, file, length); memset(dfuFileBitmap, 0, sizeof(dfuFileBitmap)); AppTimer_delete(GoNextDfuLater); GoNextDfu(); } } static int readCartCnt = 0; static void ReadCardTimeout(union sigval sig) { AppTimer_delete(ReadCardTimeout); readCartCnt++; if (readCartCnt < 2) { AppTimer_add(ReadCardTimeout, D_SEC(3)); SendMcuCommand(ID_CM_READ_RFCARD, NULL, 0); } else { uint8_t data[8] = {0}; PlatformStatusChanged(CARD_UPDATE_EVT, data, sizeof(data)); } } void ReadCard(void) { readCartCnt = 0; AppTimer_delete(ReadCardTimeout); AppTimer_add(ReadCardTimeout, D_SEC(3)); SendMcuCommand(ID_CM_READ_RFCARD, NULL, 0); } void ShutdownInd(int timeout) { uint8_t v = timeout; SendMcuCommand(ID_CM_SHUTDOWN, &v, 1); }