我是按照网友寒寒的例子,改写了上位机软件,IAP,和APP。我把APP用JTAG下载到Flash,然后再下载IAP(JTAG下载设置清除扇区),下载后在IAP中使用IAP_LOAD()可以跳转到APP运行(因为APP没有擦除)。但是使用IAP_WRITE(),每次发送512字节固件包。更新完成后,发现程序没有运行,不知道是什么原因?麻烦大家帮忙分析一下。
原帖地址:http://www.openedv.com/posts/list/38799.htm#top
1.IAP设置:
2.上位机软件,自定协议,每次发送512字节固件包:
3.APP设置:
4.IAP代码:
[mw_shl_code=c,true]// 从addr起烧录程序
void Iap_Write(uint32_t addr)
{
u16 temp = 0;
// u16 data_size = 0; //烧录大小
u16 data_len = 512; //数据长度
u16 index = 0; //数据块索引
// u32 crc_val = 0;
u32 addr_now = addr; //写入地址
u8 data_write[DATA_SIZE] = {0}; //数据缓冲
u8 w_flag = 0; //收到数据校验正确,需要写入
U3_RS485_ACK(0x01); //应答强制升级
//准备烧录,数据大小为1K
while(1)
{
delay_ms(10);
U3_RS485_Rcvd_Data(RBuf,&lenlen);
// while(lenlen<530); //等待数据接收完毕
if(U3_ISR_OK == 1) //如果U3收到了数据
{
U4_RS485_Send_Data(RBuf,lenlen);
U3_ISR_OK = 0;
if(RBuf[0] == dizhi)
{
// crc_val = RBuf[526] << 24 | RBuf[527] << 16 |RBuf[528] << 8 | RBuf[529] ;
// if(crc_val == CRC_GetVal((u32 *)RBuf,3))
// {
data_len = (u16)RBuf[9] << 16 | RBuf[10] << 8 | RBuf[11]; //获取data有效长度
index = RBuf[524] << 8 | RBuf[525]; //获取索引
addr_now = addr + 512 * index; //准备写入地址
for(temp = 0; temp < 512; temp++) //从第12位开始拷贝数据
{
data_write[temp] = RBuf[temp+12];
}
w_flag = 1;
// }
// else //CRC校验错误
// {
// U3_RS485_ACK(0x03); //本包固件接收失败,请求再次发送本包固件。
// continue;
// }
}//End 如果是本机地址
}//End 如果U3收到了数据
if(w_flag == 0)
{
continue;
}
//开始写数据
if(data_len < 512) //写入不足512字节的数据
{
if(data_len % 2 != 0)data_len += 1;
__disable_irq(); //关闭总中断
STMFLASH_Write(addr_now, (uint16_t *)data_write, data_len / 2);
__enable_irq();
// data_size += 1;
STMFLASH_Write(IAP_INFO, &data_len, 1); //从指定地址开始写入指定长度的数据
U3_RS485_ACK(0x04); //所有固件接收完成,本次更新完成。
w_flag = 0;
break;
}
else //写入512字节数据
{
LED1 = ~LED1;
__disable_irq(); //关闭总中断
STMFLASH_Write(addr_now, (uint16_t*)data_write, data_len / 2);
__enable_irq();
// data_size += 1;
for(temp = 0; temp < 530; temp++)
{
RBuf[temp] = 0;
}
U4_RS485_Send_Data(Test,2);
U3_RS485_ACK(0x02); //本包固件接收完成,请求发送下一包固件。
w_flag = 0;
}
}//End while(1) 烧录完成
//清空串口缓存
for(temp = 0; temp < 530; temp++)
{
RBuf[temp] = 0;
}
IAP_LOAD();
}
//设置栈顶地址
//addr:栈顶地址
__asm void MSR_MSP(u32 addr)
{
MSR MSP, r0 //set Main Stack value
BX r14
}
void Iap_load(uint32_t addr)
{
if(((*(vu32*)addr) & 0x2FFE0000) == 0x20000000)
{
jump = (iapfun) *(vu32*)(addr + 4); //强制转化为函数
MSR_MSP(*(vu32*)addr);
jump();
}
else
{
// U3_RS485_Send_String("Error\n");
// LED1 = 1;
while(1);
}
}[/mw_shl_code]
其中的函数:
[mw_shl_code=c,true]/*1B地址 8B产品ID 1B功能码 2B版本号 4BCRC
00判断版本号升级。
01强制升级。
02本包固件接收完成,请求发送下一包固件。
03本包固件接收失败,请求再次发送本包固件。
04所有固件接收完成,本次更新完成。
*/
void U3_RS485_ACK(u8 ACK_type)
{
u32 CRC_Result;
u8 ACK_Buf[16];
// u16 len;
ACK_Buf[0] = dizhi;
ACK_Buf[1] = 0x00;
ACK_Buf[2] = 0x00;
ACK_Buf[3] = 0x00;
ACK_Buf[4] = 0x00;
ACK_Buf[5] = 0x00;
ACK_Buf[6] = 0x00;
ACK_Buf[7] = 0x00;
ACK_Buf[8] = 0x00;
ACK_Buf[9] = ACK_type; //1B功能码
ACK_Buf[10] = ver>>8; //2B版本号 高8位
ACK_Buf[11] = ver; //2B版本号 低8位
CRC_Result = CRC_GetVal((u32 *)ACK_Buf, 3);
ACK_Buf[12] = CRC_Result>>24; //4BCRC
ACK_Buf[13] = CRC_Result>>16;
ACK_Buf[14] = CRC_Result>>8;
ACK_Buf[15] = CRC_Result;
U3_RS485_Send_Data(ACK_Buf,16);
}[/mw_shl_code]
|