Files
2026-07-03 18:08:25 +08:00

411 lines
11 KiB
C

/*
* INCLUDE FILES
****************************************************************************************
*/
#include "Includes.h"
//#include "xinc_reg.h"
// #include "spi_flash.h"
#include "xc_drv_spi.h"
#define FLASH_PAGE_WORDS 64
#define FLASH_PAGE_SIZE 256
#define FLASH_BLOCK_SIZE 65536
#define FLASH_SECTOR_SIZE 4096
#define PAGES_SIZE 1024
volatile uint32_t param_backup_addr = ((8*1024)-256);
sboot_message *pms;
uint8_t burn_ser=0;
//sboot_message parambuffa1;
//sboot_message parambuffa2;
static uint8_t ALIGN(4) parambuffa[FLASH_PAGE_SIZE];
static uint8_t ALIGN(4) parambuffb[FLASH_PAGE_SIZE];
static uint8_t ALIGN(4) rwbuff[FLASH_PAGE_SIZE];
uint8_t spi_idx = SPI0_IDX;
uint8_t single_ota_flag=0;
typedef void (*iapfun)(void); // 定义一个函数类型的参数.
static iapfun jump2app;
//__RAM_CODE __asm void MSR_MSP(uint32_t addr) // 设置栈顶地址 addr:栈顶地址
//{
// MSR MSP, r0 // set Main Stack value
// BX r14
//}
void flash_init()
{
SPI_InitCfg_t spi_cfg = {0};
spi_cfg.Mode = SPI_MODE_MASTER;
spi_cfg.DataSize = SSI_CTRL0_DFS_LEN_8BIT;
spi_cfg.Direction = SSI_CTRL0_TMOD_WR;
spi_cfg.BaudRatePrescaler = SSI_BAUD_DIV_2;
spi_cfg.CLKPolarity = SSI_CTRL0_SCPOL_LOW;
spi_cfg.CLKPhase = SSI_CTRL0_SCPHA_LEAD;
spi_cfg.FirstBit = SPI_FirstBit_MSB;
xc_spi_init(spi_idx, &spi_cfg);
xc_spi_flash_wake_up(spi_idx);
}
static void param_overwrite(uint8_t to, uint8_t *buff,uint8_t flag)
{
uint8_t data[256];
if(flag)
{
for(int i=0; i<256; i+=2){
data[i] = buff[i+1];
data[i+1] = buff[i];
}
}
else
{
for(int i=0; i<256; i++){
data[i] = buff[i];
}
}
uint32_t addr = (to == TO_B) ? param_backup_addr : PARAM_ADDR;
xc_wdt_reload();
// SPI_WRITE_ENABLE();
FLASH_PAGE_ERASE(spi_idx, addr); // spi_flash_page_erase(addr);
FLASH_WAIT_READY;
/*write a page*/
// SPI_WRITE_ENABLE();
FLASH_WRITE_PAGE(spi_idx, addr, data);
FLASH_WAIT_READY;
}
/**
* Copyright (c) 2022 - 2025, XinChip
* All rights reserved.
* Author : D
*/
__RAM_CODE void bootapp(param_unit *bparam)
{
uart_printf("boot app=%x\n", bparam->aloadaddr);
if (bparam->aloadaddr < FLASH_VIR_AADDR)
{
// 4096 0 16 pagecnt=16
uint32_t words;
uint32_t remain = bparam->alen % FLASH_PAGE_SIZE;
uint32_t pagecnt = bparam->alen / FLASH_PAGE_SIZE;
pagecnt = (remain == 0) ? pagecnt : (pagecnt + 1);
for (uint32_t pageser = 0, buffser = 0, pdesser = 0; pageser < pagecnt; pageser++)
{
FLASH_READ_PAGE(spi_idx, bparam->aaddr + pageser * FLASH_PAGE_SIZE, rwbuff);
// i= (pageser==0) ? (CODES_OFFSET/4):0;
words = ((pagecnt - 1) == pageser) ? (((remain % 4) == 0) ? (remain / 4) : ((remain / 4) + 1)) : FLASH_PAGE_WORDS;
for (buffser = 0; buffser < words; buffser++, pdesser++)
{
*(((uint32_t *)bparam->aloadaddr) + pdesser) = *(((uint32_t *)rwbuff) + buffser);
}
}
}
else
{
#ifdef QUAD_ENABLE
init_xip(QUAD_MODE);
#else
init_xip(DUAL_MODE);
#endif
}
jump2app = (iapfun) * (uint32_t *)(bparam->aloadaddr + 4); // 用户代码区第二个字为程序开始地址(复位地址)
MSR_MSP(*(uint32_t *)(bparam->aloadaddr)); // 设置栈顶地址 addr:栈顶地址 (用户代码区第一个字为程序的栈顶地址)
jump2app();
while (1)
;
}
/**
* Copyright (c) 2022 - 2025, XinChip
* All rights reserved.
* Author : D
*/
static void boot_backup(param_unit *bParam)
{
/*reserved*/
}
/**
* Copyright (c) 2022 - 2025, XinChip
* All rights reserved.
* Author : D
*/
static uint8_t eraseapp(param_unit *eparam)
{
uint32_t addrB = eparam->baddr;
uint32_t addr=0;
//set Loading_addr=0x11015000 //app bin startup address, The app bin is stored in the A region of the flash memory. //aaddr=Loading_addr-0x11000000
//set Back_addr=0x15000, // The address of the backup area corresponds to the address of Flash's B area. //baddr=Back_addr
//Loading_addr and Back_addr can be modified via parameters in the ge_ota.bat file.
//Zone A and Zone B share the same address for single-zone OTA wireless upgrades.
if(eparam->baddr==eparam->aaddr)
{
single_ota_flag=1;
}
uart_printf("ota_flag=%x ,%x, %x\n", single_ota_flag, eparam->baddr, eparam->aaddr);
if(!single_ota_flag)
{
addr = eparam->aaddr;
}
uint32_t era_sectorcnt = (eparam->blen) / FLASH_SECTOR_SIZE;
era_sectorcnt = (((eparam->blen) % FLASH_SECTOR_SIZE) == 0) ? era_sectorcnt : (era_sectorcnt + 1);
uint32_t crc = CRC32_INITIAL;
uint32_t remain = 0;
uint32_t pagecnt = (eparam->blen) / FLASH_PAGE_SIZE;
pagecnt = (((eparam->blen) % FLASH_PAGE_SIZE) == 0) ? pagecnt : (pagecnt + 1);
remain = ((eparam->blen) % FLASH_PAGE_SIZE);
if (remain == 0)
remain = FLASH_PAGE_SIZE;
for (uint32_t i = 0; i < pagecnt; i++)
{
FLASH_READ_PAGE(spi_idx, addrB + i * FLASH_PAGE_SIZE, rwbuff);
crc = ((pagecnt - 1) == i) ? (get_crc32(crc, rwbuff, FLASH_PAGE_SIZE)) : (get_crc32(crc, rwbuff, FLASH_PAGE_SIZE));
}
if (crc != (eparam->bcheck))
{
static uint8_t ErrCrcCNT = 0;
ErrCrcCNT++;
return 0;
}
for (uint32_t i = 0; i < era_sectorcnt; i++)
{
if(!single_ota_flag)
{
xc_wdt_reload();
FLASH_SECTOR_ERASE(spi_idx, addr + i * FLASH_SECTOR_SIZE); // spi_flash_page_erase(addr);
FLASH_WAIT_READY;
}
}
eparam->status = OVERWRITEASTAT;
return 1;
}
/**
* Copyright (c) 2022 - 2025, XinChip
* All rights reserved.
* Author : D
*/
static void erase_backup(param_unit *eparam)
{
uint32_t addr=0;
if(!single_ota_flag)
{
addr = eparam->baddr;
}
uint16_t era_sectorcnt = (eparam->blen) / FLASH_SECTOR_SIZE;
era_sectorcnt = (((eparam->blen) % FLASH_SECTOR_SIZE) == 0) ? era_sectorcnt : (era_sectorcnt + 1);
for (uint32_t i = 0; i < era_sectorcnt; i++)
{
if(!single_ota_flag){
FLASH_SECTOR_ERASE(spi_idx, addr + i * FLASH_SECTOR_SIZE); // spi_flash_page_erase(addr);
FLASH_WAIT_READY;
}
}
eparam->status = ACTIVEASTAT;
pms->paramcrc32 = get_crc32(CRC32_INITIAL, (uint8_t *)pms, PARAM_LENGTH);
param_overwrite(TO_A, (uint8_t *)pms,0);
param_overwrite(TO_B, (uint8_t *)pms,0);
}
/**
* Copyright (c) 2022 - 2025, XinChip
* All rights reserved.
* Author : D
*/
// void reverse_bytes(uint8_t *data, size_t length) {
// if (length % 2 != 0) {
// // printf("Error: Length of data must be even.\n");
// return;
// }
// for (size_t i = 0; i < length; i += 2) {
// // 交换每两个字节
// uint8_t temp = data[i];
// data[i] = data[i + 1];
// data[i + 1] = temp;
// }
//}
static void overwriteapp(param_unit *oparam)
{
if(!single_ota_flag)
{
uart_printf("overwriteapp\n");
uint32_t addrA = oparam->aaddr;
uint32_t addrB = oparam->baddr;
uint32_t remain = 0;
uint32_t pagecnt = (oparam->blen) / FLASH_PAGE_SIZE;
pagecnt = (((oparam->blen) % FLASH_PAGE_SIZE) == 0) ? pagecnt : (pagecnt + 1);
remain = ((oparam->blen) % FLASH_PAGE_SIZE);
if (remain == 0)
remain = FLASH_PAGE_SIZE;
for (uint32_t i = 0; i < pagecnt; i++)
{
xc_wdt_reload();
FLASH_READ_PAGE(spi_idx, addrB + i * FLASH_PAGE_SIZE, rwbuff);
FLASH_WAIT_READY;
// reverse_bytes(rwbuff,256);
FLASH_WRITE_PAGE(spi_idx, addrA + i * FLASH_PAGE_SIZE, rwbuff);
FLASH_WAIT_READY;
}
}
oparam->alen = oparam->blen;
oparam->acheck = oparam->bcheck;
oparam->status = ERASEBSTAT;
pms->paramcrc32 = get_crc32(CRC32_INITIAL, (uint8_t *)pms, PARAM_LENGTH);
param_overwrite(TO_A, (uint8_t *)pms,0);
}
/**
* Copyright (c) 2022 - 2025, XinChip
* All rights reserved.
* Author : D
*/
void overwrite_backup(param_unit *oparam)
{
/*reserved*/
}
/**
* Copyright (c) 2022 - 2025, XinChip
* All rights reserved.
* Author : D
*/
void param_analy(param_unit *sparam)
{
uart_printf("param_analy\n");
if(sparam->status==ERASEASTAT)
{
xc_wdt_reload();
uart_printf("eraseapp\n");
if(!eraseapp(sparam))
{
uart_printf("crc err\n");
param_overwrite(TO_A, parambuffb,0);
bootapp((param_unit *)parambuffa);
}
overwriteapp(sparam);
erase_backup(sparam);
xc_wdt_reload();
bootapp(sparam);
}
else if(sparam->status==ACTIVEBSTAT)
{
boot_backup(sparam);
}
else
{
uart_printf("status error:%d",sparam->status);
}
}
void param_backup_addr_set()
{
// uint8_t flash_sizeid = (uint8_t)spi_flash_read_identific();
uint8_t flash_sizeid = FLASH_SIZE_2M;
switch (flash_sizeid)
{
case FLASH_SIZE_4M: // 4M size
param_backup_addr = FLASH_4M_BACKUPADDR; // 4096 * 128 - 3 * 4096;
break;
case FLASH_SIZE_2M: // 2M
param_backup_addr = FLASH_2M_BACKUPADDR; // 4096 * 64 - 3 * 4096;
break;
case FLASH_SIZE_1M: // 1M
param_backup_addr = FLASH_1M_BACKUPADDR; // 4096 * 32 - 3 * 4096;
break;
default: // 4M
param_backup_addr = FLASH_4M_BACKUPADDR; // 4096 * 128 - 3 * 4096;
break;
}
}
int boot_get_status()
{
uint32_t crc32a, crc32b;
sboot_message *ptr_area = (sboot_message *)(&parambuffa[0]);
sboot_message *ptr_brea = (sboot_message *)(&parambuffb[0]);
FLASH_READ_PAGE(spi_idx, PARAM_ADDR, parambuffa);
FLASH_READ_PAGE(spi_idx, param_backup_addr, parambuffb);
crc32a = get_crc32(CRC32_INITIAL, parambuffa, PARAM_LENGTH);
crc32b = get_crc32(CRC32_INITIAL, parambuffb, PARAM_LENGTH);
if(ptr_area->paramcrc32==crc32a)
{
pms = ptr_area;
for(int param_no=0;param_no<PARAM_CNT;param_no++)
{
if(ptr_area->paramunit[param_no].status==ERASEASTAT)//OTA begin,select whitch app need updata
{
burn_ser=param_no;
return STATUS_APPUPDATA;
}
else if(ptr_area->paramunit[param_no].status==ACTIVEASTAT)//OTA begin
{
if(crc32a!=crc32b)
{
param_overwrite(TO_B, parambuffa,0);
}
burn_ser=param_no;
return STATUS_APPBOOT;
}
}
}
else
{
if(ptr_brea->paramcrc32==crc32b)
{
param_overwrite(TO_A, parambuffb,0);
}
}
return STATUS_APPERROR;
}
void boot_run_sec()
{
uint8_t status = boot_get_status();
switch (status)
{
case STATUS_APPBOOT:
bootapp(&(pms->paramunit[burn_ser]));
break;
case STATUS_APPUPDATA:
while (1)
{
param_analy(&(pms->paramunit[burn_ser]));
}
case STATUS_APPERROR:
uart_printf(" error_status\r\n");
boot_run_sec();
break;
}
}