mirror of
https://github.com/armfly/H7-TOOL_STM32H7_App.git
synced 2024-08-09 10:05:34 +08:00
461 lines
15 KiB
C
461 lines
15 KiB
C
|
/*
|
|||
|
*********************************************************************************************************
|
|||
|
*
|
|||
|
* 模块名称 : N76E003芯片编程模块
|
|||
|
* 文件名称 : n76e_prog_file.c
|
|||
|
* 版 本 : V1.0
|
|||
|
* 说 明 : 烧写文件到N76E003芯片
|
|||
|
*
|
|||
|
* 修改记录 :
|
|||
|
* 版本号 日期 作者 说明
|
|||
|
* V1.0 2020-09-27 armfly 正式发布
|
|||
|
*
|
|||
|
* Copyright (C), 2019-2030, 安富莱电子 www.armfly.com
|
|||
|
*
|
|||
|
*********************************************************************************************************
|
|||
|
*/
|
|||
|
#include "bsp.h"
|
|||
|
#include "param.h"
|
|||
|
#include "file_lib.h"
|
|||
|
#include "lua_if.h"
|
|||
|
#include "prog_if.h"
|
|||
|
#include "swd_host.h"
|
|||
|
#include "swd_flash.h"
|
|||
|
#include "elf_file.h"
|
|||
|
#include "main.h"
|
|||
|
#include "stm8_flash.h"
|
|||
|
#include "SW_DP_Multi.h"
|
|||
|
#include "swd_host_multi.h"
|
|||
|
|
|||
|
extern const program_target_t flash_algo;
|
|||
|
|
|||
|
/*
|
|||
|
*********************************************************************************************************
|
|||
|
* 函 数 名: PG_N76E_ProgFile
|
|||
|
* 功能说明: 开始编程flash。 由lua程序调用。阻塞运行,只到编程结束。
|
|||
|
* 形 参: _Path : 文件名
|
|||
|
* _FlashAddr : flash起始地址
|
|||
|
* _EndAddr : flash结束地址
|
|||
|
* _CtrlByte : 控制字节,bit0 = 1表示 滚码UID加密在本次编程中写入
|
|||
|
* _FileIndex : 文件编号(1-10),用于滚码UID加密
|
|||
|
* _AlgoName : 算法名 : "APPROM", "LDPROM", "SPROM", ""CFG",
|
|||
|
* 返 回 值: 0 = ok, 其他表示错误
|
|||
|
*********************************************************************************************************
|
|||
|
*/
|
|||
|
uint16_t PG_N76E_ProgFile(const char *_Path, uint32_t _FlashAddr, uint32_t _EndAddr, uint32_t _CtrlByte,
|
|||
|
uint32_t _FileIndex, const char *_AlgoName)
|
|||
|
{
|
|||
|
char path[256];
|
|||
|
uint16_t name_len;
|
|||
|
uint8_t err = 0;
|
|||
|
char ext_name[5];
|
|||
|
uint32_t FileLen;
|
|||
|
uint8_t EraseMode = 0;
|
|||
|
uint8_t CheckBankMode = 0;
|
|||
|
// uint8_t fBlankChip = 0;
|
|||
|
// uint32_t BlockSize;
|
|||
|
uint32_t CheckLen; /* 实际扫描的空间大小 */
|
|||
|
|
|||
|
/* 传入的文件名是相对路径 */
|
|||
|
if (strlen(_Path) + strlen(PROG_USER_DIR) > sizeof(path))
|
|||
|
{
|
|||
|
PG_PrintText("文件路径太长");
|
|||
|
err = 1;
|
|||
|
goto quit;
|
|||
|
}
|
|||
|
|
|||
|
if (_Path[0] == '0' && _Path[1] == ':') /* 是绝对路径 */
|
|||
|
{
|
|||
|
strncpy(path, _Path, sizeof(path));
|
|||
|
}
|
|||
|
else /* 是相对路路径 */
|
|||
|
{
|
|||
|
GetDirOfFileName(g_tProg.FilePath, path); /* 从lua文件名、中获取目录 */
|
|||
|
strcat(path, "/");
|
|||
|
strcat(path, _Path);
|
|||
|
|
|||
|
FixFileName(path); /* 去掉路径中的..上级目录 */
|
|||
|
}
|
|||
|
|
|||
|
/* 解析文件名 */
|
|||
|
name_len = strlen(_Path);
|
|||
|
if (name_len < 5)
|
|||
|
{
|
|||
|
PG_PrintText("数据文件名过短 ");
|
|||
|
err = 1;
|
|||
|
goto quit;
|
|||
|
}
|
|||
|
|
|||
|
/* 文件支持 1.hex, 2.bin */
|
|||
|
memcpy(ext_name, &_Path[name_len - 4], 5);
|
|||
|
strlwr(ext_name); /* 转换为小写 */
|
|||
|
if (strcmp(ext_name, ".hex") == 0)
|
|||
|
{
|
|||
|
;
|
|||
|
}
|
|||
|
else if (strcmp(ext_name, ".bin") == 0)
|
|||
|
{
|
|||
|
;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
PG_PrintText("数据文件扩展名不正确");
|
|||
|
err = 1;
|
|||
|
goto quit;
|
|||
|
}
|
|||
|
|
|||
|
FileLen = GetFileSize(path);
|
|||
|
if (FileLen == 0)
|
|||
|
{
|
|||
|
PG_PrintText("读取数据文件失败");
|
|||
|
err = 1;
|
|||
|
goto quit;
|
|||
|
}
|
|||
|
|
|||
|
{
|
|||
|
uint32_t DevSize;
|
|||
|
|
|||
|
DevSize = PG_GetDeviceSize(_AlgoName);
|
|||
|
|
|||
|
if (FileLen > DevSize)
|
|||
|
{
|
|||
|
PG_PrintText("数据文件过大");
|
|||
|
err = 1;
|
|||
|
goto quit;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
低4bit表示擦除模式 0按扇区擦除 1按整片擦除 2不执行擦除
|
|||
|
高4bit表示查空 0查空 1不查空
|
|||
|
*/
|
|||
|
EraseMode = _CtrlByte & 0x03;
|
|||
|
CheckBankMode = (_CtrlByte >> 4) & 0x03;
|
|||
|
|
|||
|
if (EraseMode == 0 || EraseMode == 1)
|
|||
|
{
|
|||
|
if (lua_GetVarUint32("G_CHIP_ERASED", 0) == 1) /* 已经执行过解除读保护,整片已擦除 */
|
|||
|
{
|
|||
|
printf("The chip has been erased\r\n");
|
|||
|
}
|
|||
|
else /* 前面未执行整片擦除解除读保护 */
|
|||
|
{
|
|||
|
uint8_t MustEarse = 0; /* 1: 必须擦除 */
|
|||
|
|
|||
|
if (CheckBankMode == 0) /* 需要查空 */
|
|||
|
{
|
|||
|
PG_PrintText("正在查空...");
|
|||
|
PG_PrintPercent(0, 0xFFFFFFFF);
|
|||
|
if (PG_CheckBlank(_AlgoName, _FlashAddr, _EndAddr - _FlashAddr) == 0)
|
|||
|
{
|
|||
|
MustEarse = 1; /* 必须擦除 */
|
|||
|
}
|
|||
|
PG_PrintPercent(100.0, _FlashAddr); /* 显示100% */
|
|||
|
|
|||
|
if (MustEarse == 0)
|
|||
|
{
|
|||
|
printf("The chip is blank\r\n");
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
printf("The chip is not blank\r\n");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
PG_PrintText("正在擦除...");
|
|||
|
PG_PrintPercent(0, 0xFFFFFFFF);
|
|||
|
|
|||
|
if (EraseMode == 0) /* 0:按扇区擦除, 只擦除文件所在的扇区 */
|
|||
|
{
|
|||
|
uint32_t addr;
|
|||
|
uint32_t endAddr;
|
|||
|
|
|||
|
endAddr = _FlashAddr + FileLen;
|
|||
|
if (endAddr > _EndAddr)
|
|||
|
{
|
|||
|
endAddr = _EndAddr;
|
|||
|
}
|
|||
|
|
|||
|
addr = _FlashAddr;
|
|||
|
while (1)
|
|||
|
{
|
|||
|
if (addr >= endAddr)
|
|||
|
{
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
if (PG_EraseSector(_AlgoName, addr) == 0)
|
|||
|
{
|
|||
|
PG_PrintText("擦除扇区失败");
|
|||
|
err = 1;
|
|||
|
goto quit;
|
|||
|
}
|
|||
|
|
|||
|
/* 显示进度 */
|
|||
|
{
|
|||
|
float percent;
|
|||
|
|
|||
|
percent = addr - _FlashAddr; /* 已擦除大小 */
|
|||
|
percent = percent / (endAddr - _FlashAddr);
|
|||
|
PG_PrintPercent(percent, addr); /* 显示100% */
|
|||
|
}
|
|||
|
|
|||
|
addr += PG_GetSectorSize(_AlgoName, addr);
|
|||
|
}
|
|||
|
}
|
|||
|
else if (EraseMode == 1) /* 1:整片擦除 */
|
|||
|
{
|
|||
|
uint8_t re;
|
|||
|
|
|||
|
re = PG_EraseChip();
|
|||
|
PG_PrintPercent(100.0, _FlashAddr); /* 显示100% */
|
|||
|
|
|||
|
if (re == 0)
|
|||
|
{
|
|||
|
PG_PrintText("整片擦除失败");
|
|||
|
err = 1;
|
|||
|
goto quit;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/* 编程page */
|
|||
|
PG_PrintText("正在编程...");
|
|||
|
PG_PrintPercent(0, 0xFFFFFFFF);
|
|||
|
{
|
|||
|
uint32_t addr;
|
|||
|
uint32_t FileOffset = 0;
|
|||
|
uint16_t PageSize;
|
|||
|
uint32_t bytes;
|
|||
|
uint32_t i;
|
|||
|
uint32_t j;
|
|||
|
uint32_t FileBuffSize;
|
|||
|
uint32_t DeviceSize;
|
|||
|
|
|||
|
PageSize = PG_GetPageSize(_AlgoName);
|
|||
|
if (PageSize > sizeof(FsReadBuf))
|
|||
|
{
|
|||
|
PageSize = sizeof(FsReadBuf);
|
|||
|
}
|
|||
|
|
|||
|
/* 整定文件缓冲区大小为PageSize的整数倍 */
|
|||
|
FileBuffSize = sizeof(FsReadBuf);
|
|||
|
FileBuffSize = (FileBuffSize / PageSize) * PageSize;
|
|||
|
|
|||
|
/* 计算芯片最大地址 */
|
|||
|
addr = PG_GetDeviceAddr(_AlgoName); /* 芯片起始地址 */
|
|||
|
DeviceSize = PG_GetDeviceSize(_AlgoName); /* 芯片容量 */
|
|||
|
|
|||
|
/* 计算需要处理的存储器空间大小 */
|
|||
|
if (_EndAddr > (addr + DeviceSize))
|
|||
|
{
|
|||
|
CheckLen = addr + DeviceSize - _FlashAddr;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
CheckLen = _EndAddr - _FlashAddr;
|
|||
|
}
|
|||
|
|
|||
|
addr = _FlashAddr;
|
|||
|
for (j = 0; j < (CheckLen + sizeof(FsReadBuf) - 1) / sizeof(FsReadBuf); j++)
|
|||
|
{
|
|||
|
if (ProgCancelKey())
|
|||
|
{
|
|||
|
PG_PrintText("用户终止运行");
|
|||
|
err = 1;
|
|||
|
goto quit;
|
|||
|
}
|
|||
|
|
|||
|
/* 读文件, 按最大缓冲区读取到内存 */
|
|||
|
if (_FlashAddr + FileLen > addr && _FlashAddr < addr + sizeof(FsReadBuf))
|
|||
|
{
|
|||
|
bytes = ReadFileToMem(path, FileOffset, FsReadBuf, sizeof(FsReadBuf));
|
|||
|
|
|||
|
if (bytes != sizeof(FsReadBuf))
|
|||
|
{
|
|||
|
if (FileOffset + sizeof(FsReadBuf) < FileLen)
|
|||
|
{
|
|||
|
PG_PrintText("读取数据文件失败");
|
|||
|
err = 1;
|
|||
|
goto quit;
|
|||
|
}
|
|||
|
|
|||
|
/* V1.11 修正bug : 烧写非整数倍PageSize的文件失败 */
|
|||
|
if (bytes % PageSize)
|
|||
|
{
|
|||
|
memset(&FsReadBuf[bytes], 0x00 ,PageSize - (bytes % PageSize)); /* 填充空值 00 */
|
|||
|
|
|||
|
bytes = ((bytes + PageSize - 1) / PageSize) * PageSize;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/* 修改缓冲区,填充UID加密数据或产品序号 */
|
|||
|
PG_FixFlashMem(addr, FsReadBuf, bytes, _FileIndex, 0);
|
|||
|
|
|||
|
for (i = 0; i < bytes / PageSize; i++)
|
|||
|
{
|
|||
|
if (PG_ProgramBuf(_AlgoName, addr, (uint8_t *)&FsReadBuf[i * PageSize], PageSize) == 0)
|
|||
|
{
|
|||
|
PG_PrintText("编程失败");
|
|||
|
err = 1;
|
|||
|
goto quit;
|
|||
|
}
|
|||
|
|
|||
|
addr += PageSize;
|
|||
|
FileOffset += PageSize;
|
|||
|
|
|||
|
|
|||
|
/* 进度指示 - 每2KB刷新一次 */
|
|||
|
if ((FileOffset % 2048) == 0 || (bytes < 2048 && (FileOffset % 512) == 0))
|
|||
|
{
|
|||
|
float percent;
|
|||
|
|
|||
|
percent = ((float)FileOffset / FileLen) * 100;
|
|||
|
if (percent > 100)
|
|||
|
{
|
|||
|
percent = 100;
|
|||
|
}
|
|||
|
PG_PrintPercent(percent, addr);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/* 文件以外的page */
|
|||
|
/* 处理文件之后的flash空间,写入fix区数据 */
|
|||
|
{
|
|||
|
uint32_t RemLen;
|
|||
|
uint32_t bytes;
|
|||
|
|
|||
|
RemLen = _FlashAddr + CheckLen - addr; /* 剩余空间 */
|
|||
|
|
|||
|
/* 如果UID加密数据或产品序号在文件以外的空间 */
|
|||
|
if (PG_CheckFlashFix(addr, RemLen, _FileIndex))
|
|||
|
{
|
|||
|
FileBuffSize = sizeof(FsReadBuf); /* 16KB */
|
|||
|
|
|||
|
while(1)
|
|||
|
{
|
|||
|
bytes = FileBuffSize;
|
|||
|
if (bytes > RemLen)
|
|||
|
{
|
|||
|
bytes = RemLen;
|
|||
|
}
|
|||
|
|
|||
|
if (PG_CheckFlashFix(addr, bytes, _FileIndex))
|
|||
|
{
|
|||
|
memset(FsReadBuf, 0, bytes);
|
|||
|
|
|||
|
/* 修改缓冲区,填充UID加密数据或产品序号 */
|
|||
|
PG_FixFlashMem(addr, FsReadBuf, bytes, _FileIndex, 0);
|
|||
|
|
|||
|
if (PG_ProgramBuf(_AlgoName, addr, (uint8_t *)FsReadBuf, bytes) == 0)
|
|||
|
{
|
|||
|
{
|
|||
|
char buf[128];
|
|||
|
|
|||
|
sprintf(buf, "编程失败, 0x%08X", addr);
|
|||
|
PG_PrintText(buf);
|
|||
|
}
|
|||
|
err = 1;
|
|||
|
goto quit;
|
|||
|
}
|
|||
|
}
|
|||
|
addr += bytes;
|
|||
|
RemLen -= bytes;
|
|||
|
|
|||
|
if (addr >= _FlashAddr + CheckLen)
|
|||
|
{
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/* 校验 */
|
|||
|
PG_PrintText("正在校验...");
|
|||
|
PG_PrintPercent(0, 0xFFFFFFFF);
|
|||
|
{
|
|||
|
uint32_t addr;
|
|||
|
uint32_t FileOffset = 0;
|
|||
|
uint16_t PageSize;
|
|||
|
uint32_t bytes;
|
|||
|
uint32_t DeviceSize;
|
|||
|
|
|||
|
addr = _FlashAddr; /* 芯片起始地址 */
|
|||
|
DeviceSize = PG_GetDeviceSize(_AlgoName); /* 芯片容量 */
|
|||
|
|
|||
|
PageSize = sizeof(flash_buff);
|
|||
|
|
|||
|
if (PageSize >= sizeof(FsReadBuf))
|
|||
|
{
|
|||
|
PageSize = sizeof(FsReadBuf);
|
|||
|
}
|
|||
|
|
|||
|
if (PageSize >= DeviceSize)
|
|||
|
{
|
|||
|
PageSize = DeviceSize;
|
|||
|
}
|
|||
|
|
|||
|
for (; FileOffset < FileLen; )
|
|||
|
{
|
|||
|
if (ProgCancelKey())
|
|||
|
{
|
|||
|
PG_PrintText("用户终止运行");
|
|||
|
err = 1;
|
|||
|
goto quit;
|
|||
|
}
|
|||
|
|
|||
|
bytes = ReadFileToMem(path, FileOffset, FsReadBuf, PageSize);
|
|||
|
if (bytes != PageSize)
|
|||
|
{
|
|||
|
if (FileOffset + PageSize < FileLen)
|
|||
|
{
|
|||
|
PG_PrintText("读取数据文件失败");
|
|||
|
err = 1;
|
|||
|
goto quit;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/* 修改缓冲区,填充UID加密数据或产品序号 */
|
|||
|
PG_FixFlashMem(addr, FsReadBuf, PageSize, _FileIndex, 0);
|
|||
|
|
|||
|
{
|
|||
|
/* 读回进行校验 */
|
|||
|
PG_ReadBuf(_AlgoName, addr, flash_buff, bytes);
|
|||
|
|
|||
|
if (memcmp(FsReadBuf, flash_buff, bytes) != 0)
|
|||
|
{
|
|||
|
PG_PrintText("校验数据失败");
|
|||
|
err = 1;
|
|||
|
goto quit;
|
|||
|
}
|
|||
|
addr += PageSize;
|
|||
|
FileOffset += PageSize;
|
|||
|
}
|
|||
|
|
|||
|
/* 进度指示 */
|
|||
|
{
|
|||
|
float percent = -1;
|
|||
|
|
|||
|
percent = ((float)FileOffset / FileLen) * 100;
|
|||
|
if (percent > 100)
|
|||
|
{
|
|||
|
percent = 100;
|
|||
|
}
|
|||
|
PG_PrintPercent(percent, addr);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
quit:
|
|||
|
if (g_gMulSwd.MultiMode == 0)
|
|||
|
{
|
|||
|
g_gMulSwd.Error[0] = err; /* 单路模式,借用该变量用于机台信号lua程序用 */
|
|||
|
}
|
|||
|
return err;
|
|||
|
}
|
|||
|
|
|||
|
/***************************** 安富莱电子 www.armfly.com (END OF FILE) *********************************/
|