MAX_CARLINK_A270S/MXC_A27-PCB4.5-270T/app/moto/protocol/ota_protocol.c

546 lines
18 KiB
C
Raw Permalink Normal View History

2025-01-21 16:49:37 +08:00
#include <stdio.h>
#include <stddef.h>
#include <string.h>
#include "FreeRTOS.h"
#include "chip.h"
#include "board.h"
#include "serial.h"
#include "sysinfo.h"
#include "conversation_protocol.h"
#include "sfud.h"
#include "ota_update.h"
#include "updatefile.h"
#include "romfile.h"
#include "animation.h"
#include "ff_stdio.h"
#include "awtk.h"
#include "ota_protocol.h"
int flash_copy_demo(void);
extern uint8_t bt_upgrade_flag;
#if DEVICE_TYPE_SELECT != EMMC_FLASH
#include "ff_sfdisk.h"
#endif
typedef enum {
UART_FRAME_START,
UART_FRAME_FILEINFO,
UART_FRAME_FILEXFER,
UART_FRAME_FINISH,
} eUartFrameType;
typedef enum {
UUP_STATE_IDLE,
UUP_STATE_START,
UUP_STATE_GET_FILEINFO,
UUP_STATE_FILE_TFR,
UUP_STATE_END,
} eUartUpdateState;
#define UUP_ACK_OK 1
#define UUP_ACK_FAIL 0
#define UUP_MAX_FILE_SIZE 0x1000000
#define UUP_RX_FRAME_NUM 16
#define UUP_MAX_LOADER_SIZE STEPLDR_MAX_SIZE//0x10000
static int uup_status = UUP_STATE_IDLE;
static int uup_file_type = 0;
static int uup_file_size = 0;
static int uup_packet_num = 0;
static int uup_rev_packet = 0;
static int uup_rev_len = 0;
static char uup_filename[32];
static FF_FILE *uup_file = NULL;
#define UUP_PACKET_SIZE 128
#define UUP_MAX_FRAME_LEN (UUP_PACKET_SIZE + 16)
#define UUP_PACKET_A27_SIZE 4096
#define UUP_MAX_FRAME_A27_LEN (UUP_PACKET_A27_SIZE + 16)
#define UUP_RX_FRAME_NUM 16
#define BYTESPERPAGE 256
#define PAGESPERSECTORS 16
#define UUP_BUF_SIZE (BYTESPERPAGE * PAGESPERSECTORS)
#define IMAGE_RW_SIZE 0x10000
#define NEW_APPLDR_CHECKSUM_OFFSET 0x14
#define AMT630_BIN_OFFSET 0x41000
#define BOOTANIM_BIN_OFFSET 0x741000
#define ROM_BIN_OFFSET 0xb41000
#define NEW_APPFOOSET 0x17F0000
#define AMT630_BIN_MAX_SIZE 0x700000
/*
#define AMT630_BIN_OFFSET 0x41000
#define BOOTANIM_BIN_OFFSET 0x501000//0x341000
#define ROM_BIN_OFFSET 0x801000
#define NEW_APPFOOSET 0xb01000
#define AMT630_BIN_MAX_SIZE 0x4c0000
*/
static uint32_t uup_app_offset;
static uint32_t uup_burn_offset;
static unsigned char uup_buf[4096];
static unsigned int uup_buf_len = 0;
static unsigned int checksum = 0,calc_checksum = 0xffffffff;
static void uup_send_ack(UartPort_t *uap, int type, int ret)
{
/*unsigned char buf[7] = {0x55, 0x80, 0xc5, 0x02, 0x00, 0x00, 0x00};
int i;
buf[4] = type;
buf[5] = ret;
for (i = 1; i < 6; i++)
buf[6] ^= buf[i];
iUartWrite(uap, buf, 7, pdMS_TO_TICKS(100));*/
unsigned char buf[8] = {0x55, 0x80, 0xc5, 0x02, 0x00, 0x00, 0x00, 0x00};
int i;
buf[5] = type;
buf[6] = ret;
if(ret == 0){
Set_sys_power_on_self_test(100);
Set_sys_return_demo(2);
Set_sys_plan(0);
Set_sys_pace(0);
bt_upgrade_flag = 0;
}
for (i = 1; i < 7; i++)
buf[7] ^= buf[i];
// printf("630->uart:");
// for(uint8_t j=0;j<8;j++){
// printf("%02x ",buf[j]);
// }
// printf("\n");
iUartWrite(uap, buf, 8, pdMS_TO_TICKS(100));
}
void uup_ota_update(UartPort_t *uap, uint8_t *framebuf, size_t len)
{
int frametype = framebuf[0];
uint8_t *buf = framebuf + 1;
unsigned int framelen;
unsigned int packetnum;
sfud_flash *sflash = sfud_get_device(0);
SysInfo *sysinfo = GetSysInfo();
//printf("uup_ota_update frametype =%d \n",frametype);
switch (frametype) {
case UART_FRAME_START:
printf("UART3_Modification_Type .\n");
UART3_Modification_Type();
vTaskDelay(10);
printf("start sfud erase flash .\n");
//擦除flash
uup_app_offset = NEW_APPFOOSET;
uup_burn_offset = uup_app_offset;
//uup_send_ack(uap, frametype, UUP_ACK_OK);
//Set_sys_power_on_self_test(150);
printf("erase add %X , size %X .\r\n",uup_app_offset,AMT630_BIN_MAX_SIZE);
if(sfud_erase(sflash, uup_app_offset, AMT630_BIN_MAX_SIZE)==SFUD_SUCCESS){
vTaskDelay(100);
printf("UART3_Type_regression .\n");
UART3_Type_regression();
vTaskDelay(100);
printf("UART_FRAME_START sfud erase ok.\n");
uup_send_ack(uap, frametype, UUP_ACK_OK);
}else{
vTaskDelay(100);
printf("UART3_Type_regression .\n");
UART3_Type_regression();
vTaskDelay(100);
printf("UART_FRAME_START sfud erase fail.\n");
uup_send_ack(uap, frametype, UUP_ACK_FAIL);
}
uup_status = UUP_STATE_START;
break;
case UART_FRAME_FILEINFO:
if (uup_status != UUP_STATE_START && uup_status != UUP_STATE_GET_FILEINFO) {
uup_send_ack(uap, frametype, UUP_ACK_FAIL);
break;
}
uup_file_type = buf[0];
if (uup_file_type > UPFILE_TYPE_LNCHEMMC) {
printf("Rev wrong file type %d.\n", uup_file_type);
uup_send_ack(uap, frametype, UUP_ACK_FAIL);
break;
}
uup_packet_num = (buf[1] << 16) | (buf[2] << 8) | buf[3];
uup_file_size = 128 * uup_packet_num;
if (uup_file_size > AMT630_BIN_MAX_SIZE) {
printf("Rev wrong file size.\n");
printf("uup_file_size = 0x%x ,uup_packet_num = 0x%x .\n",uup_file_size,uup_packet_num);
uup_send_ack(uap, frametype, UUP_ACK_FAIL);
break;
}
printf("uup_file_size = 0x%x .\n",uup_file_size);
uup_packet_num = uup_packet_num/32;
Set_sys_plan(uup_packet_num);
printf("uup_packet_num = %d .\r\n",uup_packet_num);
uup_rev_packet = 0;
uup_send_ack(uap, frametype, UUP_ACK_OK);
uup_status = UUP_STATE_GET_FILEINFO;
calc_checksum = 0xffffffff;
break;
case UART_FRAME_FILEXFER:
if (uup_status != UUP_STATE_GET_FILEINFO && uup_status != UUP_STATE_FILE_TFR) {
uup_send_ack(uap, frametype, UUP_ACK_FAIL);
break;
}
packetnum = buf[0];
if ((uup_rev_packet & 0xff) != packetnum) {
printf("Wrong packet number.\n");
//printf("buf 0 - 4 : 0x%x ,0x%x ,0x%x ,0x%x ,0x%x \n",buf[0],buf[1],buf[2],buf[3],buf[4],buf[5]);
//printf("packetnum = 0x%x,uup_rev_packet = 0x%x \n",packetnum,uup_rev_packet);
uup_send_ack(uap, frametype, UUP_ACK_FAIL);
break;
}
//printf("uup_rev_packet==0 ---------TURE\n");
//printf("uup_rev_packet %d.\n", uup_rev_packet);
if (uup_rev_packet==0) { //第一条数据保存其crc校验码
/*if (uup_file_type == UPFILE_TYPE_WHOLE) {
UpFileHeader *header = (UpFileHeader*)&buf[1];
if (header->magic != MKTAG('U', 'P', 'D', 'F')) {
printf("Wrong whole file magic.\n");
uup_send_ack(uap, frametype, UUP_ACK_FAIL);
break;
}
checksum = header->checksum;
sysinfo->app_size = header->files[0].size;
printf("sysinfo->appsize = 0x%x", sysinfo->app_size);
}else if (uup_file_type == UPFILE_TYPE_RESOURCE) {
RomHeader *header = (RomHeader *)&buf[1];
if (header->magic != MKTAG('R', 'O', 'M', 'A')) {
printf("Wrong resource file magic.\n");
uup_send_ack(uap, frametype, UUP_ACK_FAIL);
break;
}
checksum = header->checksum;
} else if (uup_file_type == UPFILE_TYPE_ANIMATION) {
BANIHEADER *header = (BANIHEADER *)&buf[1];
if (header->magic != MKTAG('B', 'A', 'N', 'I')) {
printf("Wrong animation file magic.\n");
uup_send_ack(uap, frametype, UUP_ACK_FAIL);
break;
}
checksum = header->checksum;
} else */
if (uup_file_type == UPFILE_TYPE_APP) {//代码文件
unsigned int magic = buf[1] | (buf[2] << 8) | (buf[3] << 16) | (buf[4] << 24);
if (magic != UPFILE_APP_MAGIC) {
printf("Wrong app file magic.\n");
uup_send_ack(uap, frametype, UUP_ACK_FAIL);
break;
}
unsigned char *tmp = buf + 1 + NEW_APPLDR_CHECKSUM_OFFSET;
checksum = tmp[0] | (tmp[1] <<8) | (tmp[2] << 16) | (tmp[3] << 24);
}else if (uup_file_type == UPFILE_TYPE_ANIMATION) {//动画文件
BANIHEADER *header = (BANIHEADER *)&buf[1];
if (header->magic != MKTAG('B', 'A', 'N', 'I')) {
printf("Wrong animation file magic.\n");
uup_send_ack(uap, frametype, UUP_ACK_FAIL);
break;
}
checksum = header->checksum;
}else if (uup_file_type == UPFILE_TYPE_RESOURCE) {//资源文件
RomHeader *header = (RomHeader *)&buf[1];
if (header->magic != MKTAG('R', 'O', 'M', 'A')) {
printf("Wrong resource file magic.\n");
uup_send_ack(uap, frametype, UUP_ACK_FAIL);
break;
}
checksum = header->checksum;
}
printf(" file_type = %d ,No1.checksum = 0x%x\n",uup_file_type,checksum);
}
framelen = len - 2;
//printf("framelen = %d ,uup_packet_num =%d ,uup_rev_packet = %d \n",framelen,uup_packet_num,uup_rev_packet);
/* only last frame size is less than UUP_PACKET_SIZE */
if (framelen > UUP_PACKET_A27_SIZE ||
(framelen < UUP_PACKET_A27_SIZE && uup_rev_packet < (uup_packet_num-1))) { //UUP_PACKET_A27_SIZE
printf("Wrong packet len.\n");
printf("uup_rev_packet = %d, uup_packet_num = %d \n",uup_rev_packet,(uup_packet_num-1));
uup_send_ack(uap, frametype, UUP_ACK_FAIL);
break;
}
memcpy(uup_buf + uup_buf_len, buf+1, framelen);
uup_buf_len += framelen;
uup_rev_packet++;
//uup_send_ack(uap, frametype, UUP_ACK_OK);
if (uup_buf_len == UUP_BUF_SIZE) {
printf("uup_rev_packet = %d , save_data.\n",uup_rev_packet);
uup_send_ack(uap, frametype, UUP_ACK_OK);
Set_sys_pace(uup_rev_packet);
//printf("addr=0x%x,size=%x\n",uup_burn_offset,framelen);
//sfud_erase_write(sflash, uup_burn_offset, UUP_BUF_SIZE, uup_buf);
sfud_write(sflash, uup_burn_offset, UUP_BUF_SIZE, uup_buf);
if (uup_rev_packet == 1){//UUP_BUF_SIZE/UUP_PACKET_SIZE) {
//printf("enter1 uup_rev_packet = %d \n",uup_rev_packet);
/*if (uup_file_type == UPFILE_TYPE_WHOLE) {
UpFileHeader *pheader = (UpFileHeader *)uup_buf;
pheader->checksum = 0;
} else if (uup_file_type == UPFILE_TYPE_RESOURCE) {
RomHeader *pheader = (RomHeader *)uup_buf;
pheader->checksum = 0;
} else if (uup_file_type == UPFILE_TYPE_ANIMATION) {
BANIHEADER *pheader = (BANIHEADER *)uup_buf;
pheader->checksum = 0;
} else if (uup_file_type == UPFILE_TYPE_APP) {*/
if (uup_file_type == UPFILE_TYPE_APP) {//代码文件
unsigned int *tmp = (unsigned int *)(uup_buf + NEW_APPLDR_CHECKSUM_OFFSET);
*tmp = 0;
}else if (uup_file_type == UPFILE_TYPE_ANIMATION) {//动画文件
BANIHEADER *pheader = (BANIHEADER *)uup_buf;
pheader->checksum = 0;
}else if (uup_file_type == UPFILE_TYPE_RESOURCE) {//资源文件
RomHeader *pheader = (RomHeader *)uup_buf;
pheader->checksum = 0;
}
//}
}
calc_checksum = xcrc32(uup_buf, UUP_BUF_SIZE, calc_checksum);//计算校验和
uup_buf_len =0;
uup_burn_offset += UUP_BUF_SIZE;
}else if (uup_buf_len > UUP_BUF_SIZE) {
printf("loader file is too large.\n");
uup_send_ack(uap, frametype, UUP_ACK_FAIL);
break;
}
/*memcpy(&uup_sysinfo, &buf[2], sizeof(SysInfo));
sfud_erase_write(sflash, uup_burn_offset, framelen, &buf[1]);//128字节写一次
uup_burn_offset += framelen;*/
uup_status = UUP_STATE_FILE_TFR;
break;
case UART_FRAME_FINISH:
if (uup_status != UUP_STATE_FILE_TFR && uup_status != UART_FRAME_FINISH) {
uup_send_ack(uap, frametype, UUP_ACK_FAIL);
break;
}
if (!buf[0]) {
printf("update end with error!\n");
uup_send_ack(uap, frametype, UUP_ACK_FAIL);
uup_status = UUP_STATE_END;
break;
}
framelen = len - 2;
//printf("finish calc_checksum =%x\n",calc_checksum);
if(uup_buf_len){//若最后一包数据不为0 则存数据并且继续计算校验和
//sfud_erase_write(sflash, uup_burn_offset, uup_buf_len, uup_buf);
sfud_write(sflash, uup_burn_offset, uup_buf_len, uup_buf);
//若数据为32 即首次的4k 那么将其置为0
if (uup_rev_packet <= 1){//< UUP_BUF_SIZE / UUP_PACKET_SIZE) {
printf("enter2 uup_rev_packet = %d \n",uup_rev_packet);
/*if (uup_file_type == UPFILE_TYPE_WHOLE) {
UpFileHeader *pheader = (UpFileHeader *)uup_buf;
pheader->checksum = 0;
} else if (uup_file_type == UPFILE_TYPE_RESOURCE) {
RomHeader *pheader = (RomHeader *)uup_buf;
pheader->checksum = 0;
} else if (uup_file_type == UPFILE_TYPE_ANIMATION) {
BANIHEADER *pheader = (BANIHEADER *)uup_buf;
pheader->checksum = 0;
} else if (uup_file_type == UPFILE_TYPE_APP) {*/
if (uup_file_type == UPFILE_TYPE_APP) {
unsigned int *checksum = (unsigned int *)(uup_buf + NEW_APPLDR_CHECKSUM_OFFSET);
*checksum = 0;
}else if (uup_file_type == UPFILE_TYPE_ANIMATION) {
BANIHEADER *pheader = (BANIHEADER *)uup_buf;
pheader->checksum = 0;
}else if (uup_file_type == UPFILE_TYPE_RESOURCE) {
RomHeader *pheader = (RomHeader *)uup_buf;
pheader->checksum = 0;
}
}
printf("enter2 uup_buf_len =%d calc_checksum================0x%x\n",uup_buf_len,calc_checksum);
calc_checksum = xcrc32(uup_buf, uup_buf_len, calc_checksum);
Set_sys_pace(0);
Set_sys_upgrade(1);
}
/*if (calc_checksum != checksum) {
printf("checksum error ! ! ! .\r\n");
}else{
printf("checksum ok .\r\n");
}*/
if (calc_checksum != checksum) {
printf("calc_checksum = 0x%02x,checksum = 0x%02x.\n",calc_checksum,checksum);
printf("whole crc check after burn fail!\n");
uup_send_ack(uap, frametype, UUP_ACK_FAIL);
uup_rev_packet = 0;
checksum = 0;
calc_checksum = 0xffffffff;
uup_buf_len = 0;
framelen = 0;
break;
} else {
uup_send_ack(uap, frametype, UUP_ACK_OK);
vTaskDelay(1000);
UART3_Modification_Type();
printf("uap close .\r\n");
printf("test amt630h update ok!\n");
sysinfo->image_offset=0x40000;
sysinfo->reserved[9] = uup_file_type;
sysinfo->upgrade_flag=uup_buf_len;
sysinfo->upgrade_appsize=uup_file_size;
SaveSysInfo();
vTaskDelay(500);
printf("TaskDelay 500ms SaveSysInfo .\n");
flash_copy_demo();
wdt_cpu_reboot();
}
uup_rev_packet = 0;
checksum = 0;
calc_checksum = 0xffffffff;
uup_buf_len = 0;
framelen = 0;
uup_status = UUP_STATE_END;
break;
}
}
int flash_copy_demo(void)
{
uint32_t calchecksum,appchecksum,imageoff,new_appoffset,new_appsize;
int i;
uint8_t *buf;
sfud_flash *sflash = sfud_get_device(0);
printf("enter copy flash .\n");
new_appsize=uup_file_size; //根据串口升级的协议获取
new_appoffset = NEW_APPFOOSET; //升级的程序可以固定写在这个地址预留3M
if(uup_file_type == UPFILE_TYPE_APP){
imageoff = AMT630_BIN_OFFSET; //固定的 运行区固定地址
}else if(uup_file_type == UPFILE_TYPE_ANIMATION){
imageoff = BOOTANIM_BIN_OFFSET; //固定的 运行区固定地址
}else if(uup_file_type == UPFILE_TYPE_RESOURCE){
imageoff = ROM_BIN_OFFSET;
}
//imageoff = AMT630_BIN_OFFSET; //固定的 运行区固定地址
printf("copy flash init ok.\n");
Set_sys_plan((new_appsize/IMAGE_RW_SIZE)+1);
printf("new_appsize = %x ,start flash copy .\n",new_appsize);
// sfud_qspi_fast_read_enable(sfud_get_device(0), 1);
// printf("sfud_qspi_fast_read_enable ok.\n");
buf = pvPortMalloc(IMAGE_RW_SIZE);
if (!buf) {
printf("%s %d malloc %d bytes fail.\n", __FUNCTION__, __LINE__, IMAGE_RW_SIZE);
return -1;
}
printf("start copy flash ok.\n");
for(i=0;i<new_appsize/IMAGE_RW_SIZE;i++)
{
printf("i = %d start read .\r\n",i);
sfud_read(sflash, new_appoffset+IMAGE_RW_SIZE*i, IMAGE_RW_SIZE, buf);
printf("start erase write .\r\n");
sfud_erase_write(sflash, imageoff+IMAGE_RW_SIZE*i, IMAGE_RW_SIZE, buf);
printf("start erase write ok.\r\n");
Set_sys_pace(i+1);
if(i==0)
{
if (uup_file_type == UPFILE_TYPE_APP) {//代码文件
unsigned int *tmp = (unsigned int *)(buf + NEW_APPLDR_CHECKSUM_OFFSET);
appchecksum = *tmp;
*tmp = 0;
}else if (uup_file_type == UPFILE_TYPE_ANIMATION) {//动画文件
BANIHEADER *pheader = (BANIHEADER *)buf;
appchecksum = pheader->checksum;
pheader->checksum = 0;
}else if (uup_file_type == UPFILE_TYPE_RESOURCE) {//资源文件
RomHeader *pheader = (RomHeader *)buf;
appchecksum = pheader->checksum;
pheader->checksum = 0;
}
printf("file_type = %d. %X\r\n",uup_file_type,appchecksum);
calchecksum = xcrc32(buf, IMAGE_RW_SIZE, 0xffffffff);
printf("i=0 calchecksum = 0x%X.\n",calchecksum);
}
else
{
calchecksum = xcrc32(buf, IMAGE_RW_SIZE, calchecksum);
printf("i=%d ,r_add = 0x%X ,w_add = 0x%X , calchecksum = 0x%X.\n",i,new_appoffset+IMAGE_RW_SIZE*i,imageoff+IMAGE_RW_SIZE*i,calchecksum);
}
}
if(new_appsize%IMAGE_RW_SIZE)
{
uint32_t red_add,wri_add,size,count;
int k;
count = (new_appsize%IMAGE_RW_SIZE )/0x1000;
red_add = new_appoffset+new_appsize- new_appsize%IMAGE_RW_SIZE;
wri_add = imageoff+new_appsize- new_appsize%IMAGE_RW_SIZE;
size = 0x1000;
printf("count = %d .\n",count);
for(k=0;k<count;k++){
sfud_read(sflash, red_add, size, buf);
sfud_erase_write(sflash, wri_add, size, buf);
calchecksum = xcrc32(buf, size, calchecksum);
printf("k=%d ,calchecksum = 0x%X.\n",k,calchecksum);
red_add +=size;
wri_add +=size;
}
if(uup_buf_len){//若最后一包数据不满0x1000 则存数据并且继续计算校验和
sfud_read(sflash, red_add, uup_buf_len, buf);
sfud_erase_write(sflash, wri_add, uup_buf_len, buf);
calchecksum = xcrc32(buf, uup_buf_len, calchecksum);
printf("end calchecksum = 0x%X.\n",calchecksum);
}
}
printf("end flash copy.\n");
vPortFree(buf);
printf("calchecksum is 0x%X\r\n",calchecksum);
printf("appchecksum is 0x%X\r\n",appchecksum);
if(calchecksum==appchecksum)
{
printf("crc32 OK\r\n");
SysInfo *sysinfo = GetSysInfo();
if(uup_file_type == UPFILE_TYPE_APP)
sysinfo->app_size = new_appsize;
sysinfo->image_offset=0x40000;
sysinfo->upgrade_flag = 0;
sysinfo->upgrade_appsize =0;
sysinfo->reserved[9] = 0;
SaveSysInfo();
vTaskDelay(500);
wdt_cpu_reboot();
return 0;
}
else
{
SysInfo *sysinfo = GetSysInfo();
if(uup_file_type == UPFILE_TYPE_APP)
sysinfo->app_size = new_appsize;
sysinfo->image_offset=0x40000;
sysinfo->upgrade_flag = 0;
sysinfo->upgrade_appsize =0;
sysinfo->reserved[9] = 0;
SaveSysInfo();
vTaskDelay(500);
printf("crc32 ERROR\r\n");
bt_upgrade_flag = 0;
return -1;
}
}