fctom1215
2020-02-11 3ce7d9cbccabf7f94d8203a98796599cd9dd5411
lib/src/main/cpp/mcu/mcu_if.cpp
@@ -4,6 +4,7 @@
#include <cstring>
#include <pthread.h>
#include <cstdlib>
#include "mcu_if.h"
#include "../common/apptimer.h"
#include "../utils/crc16.h"
@@ -29,8 +30,8 @@
#define ID_CM_APP_BOOT          0x0001
#define ID_MC_MCU_BOOT          0x8001
#define ID_CM_INQ_MCU_VER       0x0002
#define ID_MC_MCU_VER           0x8002
#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
@@ -54,12 +55,27 @@
    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 void *UartThread1(void *p);
static void ParseMcuTimeout(union sigval sig);
static void McuCommandEntry(uint16_t id, const uint8_t *data, int lenth);
static void SendDfuFile(int fileLen, int sentLen, int blockLen, const uint8_t *data);
static void GoNextDfuLater(union sigval sig);
static void GoNextDfu(void);
void ParseMcuInit(void)
{
    dfuFile = NULL;
    dfuFileLength = 0;
    parse_status = SYNC_HEAD_ONE;
    AppTimer_delete(ParseMcuTimeout);
@@ -284,8 +300,54 @@
        case ID_MC_MCU_BOOT:
            DEBUG("MCU BOOT");
            break;
        case ID_MC_MCU_VER:
            DEBUG("MCU VER");
        case ID_MC_DFU_RSP:
            DEBUG("ID_MC_DFU_RSP %d len %d", data[0], lenth);
            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 < lenth; ++i) {
                    for (int j = 0; j < 8; ++j) {
                        if ((data[i] & BV(j))) b++;
                        a++;
                        if (a == total) {
                            i = lenth;
                            break;
                        }
                    }
                }
                DEBUG("BITMAP total %d succ %d", total, b);
                //memset(dfuFileBitmap, 0, sizeof(dfuFileBitmap));
                memcpy(dfuFileBitmap, data + 1, lenth - 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;
@@ -293,9 +355,16 @@
            break;
        case ID_MC_MCU_DFU_DATA_RSP:
            break;
        case ID_MC_CAR_INFO:
            DEBUG("ID_MC_CAR_INFO");
        case ID_MC_CAR_INFO: {
            DEBUG("ID_MC_CAR_INFO %d", lenth);
            char ver[64] = {0};
            memcpy(ver, data, 32);
            DEBUG("ID_MC_CAR_INFO %s", ver);
            break;
        }
        case ID_MC_RTK_DATA:
            DEBUG("ID_MC_RTK_DATA");
            break;
@@ -306,3 +375,113 @@
            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();
    }
}