金牌会员
 
- 积分
- 1141
- 金钱
- 1141
- 注册时间
- 2015-11-29
- 在线时间
- 149 小时
|
20金钱
目前已经写好iap和app,程序写入后app不执行。不知道问题出在哪里?其中iap程序以串口收到kkkkkk为开始升级,收到kk为数据接收完成,iap部分代码帮忙分析一下
// ==================== Flash 分区定义 ====================
#define FLASH_PAGE_SIZE 1024 // STM32F1 每页1KB
#define IAP_ADDRESS 0x08000000 // IAP程序起始地址APP_ADDRESS
#define APP_ADDRESS 0x08004000 // App程序起始地址
#define FLASH_END_ADDRESS 0x08010000 // F103C8T6 Flash结束地址(64KB)
#define APP_MAX_SIZE 0x0000C000 // App区最大48KB
// ==================== 串口接收相关 ====================
#define UART_BUF_SIZE 51200
uint8_t UART_RxBuffer[UART_BUF_SIZE]; // 串口接收缓冲区
uint16_t UART_RxLen = 0; // 接收数据长度APP_ADDRESS
uint8_t UART_UpgradeFlag = 0; // 升级标志
//#define UART_BUF_SIZE 51200 // 缓冲区50KB(大于App最大48KB)
#define FINISH_FLAG "kk" // 接收完成标志(小写kk)
#define FLAG_LEN 2 // 标志长度
while(waitTime--)
{
Delay_1ms(1);
// 接收串口数据(非阻塞)
rxByte = USART1_ReceiveByte(1); // 1ms超时
if(rxByte != 0xFF) // 接收到有效数据
{
UART_RxBuffer[UART_RxLen++] = rxByte;
// 检测升级指令 "UPDATE"(长度6)
if(UART_RxLen >= 6)
{
if(memcmp(UART_RxBuffer, "kkkkkk", 6) == 0)
{
UART_UpgradeFlag = 1;
USART1_SendString((uint8_t*)"Upgrade start...\r\n");
UART_RxLen = 0; // 清空缓冲区,准备接收固件
break;
}
// 指令不匹配,清空缓冲区(防止脏数据)
// else
{
// UART_RxLen = 0;
}
}
}
}
if(UART_UpgradeFlag)
{
// 持续接收数据(30秒超时,适配大文件)
uint64_t recvTimeout = 300000000000;
char len_str[10];
while(recvTimeout--)
{
uint8_t rxByte = USART1_ReceiveByte(1);
if(rxByte != 0xFF)
{
// 防止缓冲区溢出
if(UART_RxLen < UART_BUF_SIZE)
{
UART_RxBuffer[UART_RxLen++] = rxByte;
recvTimeout = 300000000000; // 收到数据重置超时
}
else
{
USART1_SendString((uint8_t*)"\r\nBuffer full!\r\n");
break;
}
// 检测完成标志"kk"
if(UART_RxLen >= FLAG_LEN)
{
if(Check_FinishFlag() == 1)
{
UART_RecvComplete = 1;
break;
}
}
}
}
// 接收完成,开始写入Flash
if(UART_RecvComplete)
{
// 剔除末尾的"kk"标志,得到实际固件长度
uint16_t firmware_len = UART_RxLen - FLAG_LEN;
USART1_SendString((uint8_t*)"\r\nRecv complete! Firmware size: ");
sprintf(len_str, "%d bytes\r\n", firmware_len);
USART1_SendString((uint8_t*)len_str);
// 校验固件长度是否合法
if(firmware_len == 0 || firmware_len > APP_MAX_SIZE)
{
USART1_SendString((uint8_t*)"Firmware size error!\r\n");
}
else
{
// 批量写入App区(按页写入)
uint32_t appAddr = APP_ADDRESS;
uint16_t write_len = 0;
USART1_SendString((uint8_t*)"Writing to Flash...\r\n");
while(write_len < firmware_len)
{
// 每次写入1页,最后一次写剩余字节
uint16_t current_write = (firmware_len - write_len) > FLASH_PAGE_SIZE ?
FLASH_PAGE_SIZE : (firmware_len - write_len);
// 写入Flash
if(FLASH_Write(appAddr, &UART_RxBuffer[write_len], current_write) == 0)
{
appAddr += current_write;
write_len += current_write;
USART1_SendString((uint8_t*)"."); // 进度提示
}
else
{
USART1_SendString((uint8_t*)"\r\nWrite Flash failed!\r\n");
break;
}
}
// 写入完成提示
if(write_len == firmware_len)
{
USART1_SendString((uint8_t*)"\r\nUpgrade success!\r\n");
}
}
}
else
{
USART1_SendString((uint8_t*)"\r\nRecv timeout or no finish flag!\r\n");
}
}
// 跳转到App程序
IAP_JumpToApp();
uint8_t FLASH_Write(uint32_t addr, uint8_t *pData, uint16_t len)
{
uint32_t pageAddr=0;
uint16_t i = 0;
uint16_t *pHalfWord=NULL;
uint16_t data=0;
// 1. 检查地址合法性
if(addr < APP_ADDRESS || (addr + len) > FLASH_END_ADDRESS)
{
return 1; // 地址越界
}
// 2. 解锁Flash
FLASH_Unlock();
// 3. 擦除需要写入的Flash页
pageAddr = addr;
while(pageAddr < (addr + len))
{
// 等待上一次擦除完成
while(FLASH_GetStatus() != FLASH_COMPLETE);
// 擦除一页
if(FLASH_ErasePage(pageAddr) != FLASH_COMPLETE)
{
FLASH_Lock();
return 2; // 擦除失败
}
pageAddr += FLASH_PAGE_SIZE;
}
// 4. 逐半字写入(STM32F1仅支持16位写入)
pHalfWord = (uint16_t*)pData;
while(i < len)
{
// 等待Flash就绪
while(FLASH_GetStatus() != FLASH_COMPLETE);
data = 0;
if(i+1 < len)
{
data = (pData[i+1] << 8) | pData[i]; // 小端模式
}
else
{
data = pData[i]; // 剩余1字节,高位补0
}
// 写入半字
if(FLASH_ProgramHalfWord(addr + i, data) != FLASH_COMPLETE)
{
FLASH_Lock();
return 3; // 写入失败
}
i += 2;
}
// 5. 锁定Flash
FLASH_Lock();
return 0; // 成功
}
void IAP_JumpToApp(void)
{
// 函数指针类型定义
typedef void (*pFunction)(void);
pFunction JumpToApplication;
uint32_t JumpAddress;
// 1. 检查App区栈地址是否合法(F103C8T6 SRAM: 0x20000000-0x20005000)
// if(((uint32_t*)APP_ADDRESS)[0] > 0x20000000 && ((uint32_t*)APP_ADDRESS)[0] < 0x20005000)
{
// 2. 关闭所有中断
__disable_irq();
// 3. 关闭串口和外设时钟
USART_Cmd(USART2, DISABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, DISABLE);
// 4. 重置SysTick
SysTick->CTRL = 0;
SysTick->LOAD = 0;
SysTick->VAL = 0;
// 5. 获取App入口地址(中断向量表第1项:栈地址,第2项:复位函数)
JumpAddress = *(__IO uint32_t*)(APP_ADDRESS + 4);
JumpToApplication = (pFunction)JumpAddress;
// 6. 设置主栈指针(MSP)
__set_MSP(*(__IO uint32_t*)APP_ADDRESS);
// 7. 跳转到App程序
JumpToApplication();
}
}
显示写入成功倒是跳转就没有反应了。
|
|