金牌会员
 
- 积分
- 2008
- 金钱
- 2008
- 注册时间
- 2014-7-1
- 在线时间
- 189 小时
|

楼主 |
发表于 2019-6-5 16:26:18
|
显示全部楼层
问题解决了,采用2个数组,都是20K大小,轮流接收APP程序,一个满了就写入另一个,轮流写入Flash保存。用这种方法,原子哥的程序不匹配,不能一边擦除一边写入又一边接收数据,数据会不全。
确认要下载APP程序之前,先把预留的程序空间都擦除了。
原子哥原来的函数修改,去掉了擦除功能。
[mw_shl_code=c,true]void STMFLASH_Write_NoCheck(u32 WriteAddr,u16 *pBuffer,u16 NumToWrite)
{
u16 i;
for(i=0;i<NumToWrite;i++)
{
STMFLASH_WriteHalfWord(WriteAddr,pBuffer);
WriteAddr+=2;//地址增加2.
}
}
//从指定地址开始写入指定长度的数据
//WriteAddr:起始地址(此地址必须为2的倍数!!)
//pBuffer:数据指针
//NumToWrite:半字(16位)数(就是要写入的16位数据的个数.)
u16 STMFLASH_BUF[STM_SECTOR_SIZE/2];//最多是2K字节
void STMFLASH_Write(u32 WriteAddr,u16 *pBuffer,u16 NumToWrite)
{
u32 secpos; //扇区地址
u16 secoff; //扇区内偏移地址(16位字计算)
u16 secremain; //扇区内剩余地址(16位字计算)
u32 offaddr; //去掉0X08000000后的地址
if(WriteAddr<STM32_FLASH_BASE||(WriteAddr>=(STM32_FLASH_BASE+1024*STM32_FLASH_SIZE)))return;//非法地址
STMFLASH_Unlock(); //解锁
offaddr=WriteAddr-STM32_FLASH_BASE; //实际偏移地址.
secpos=offaddr/STM_SECTOR_SIZE; //扇区地址 0~127 for STM32F103RBT6
secoff=(offaddr%STM_SECTOR_SIZE)/2; //在扇区内的偏移(2个字节为基本单位.)
secremain=STM_SECTOR_SIZE/2-secoff; //扇区剩余空间大小
if(NumToWrite<=secremain)secremain=NumToWrite;//不大于该扇区范围
while(1)
{
// STMFLASH_Read(secpos*STM_SECTOR_SIZE+STM32_FLASH_BASE,STMFLASH_BUF,STM_SECTOR_SIZE/2);//读出整个扇区的内容
// for(i=0;i<secremain;i++)//校验数据
// {
// if(STMFLASH_BUF[secoff+i]!=0XFFFF)break;//需要擦除
// }
// if(i<secremain)//需要擦除
// {
// STMFLASH_ErasePage(secpos*STM_SECTOR_SIZE+STM32_FLASH_BASE);//擦除这个扇区
// for(i=0;i<secremain;i++)//复制
// {
// STMFLASH_BUF[i+secoff]=pBuffer;
// }
// STMFLASH_Write_NoCheck(secpos*STM_SECTOR_SIZE+STM32_FLASH_BASE,STMFLASH_BUF,STM_SECTOR_SIZE/2);//写入整个扇区
// }
// else
// {
STMFLASH_Write_NoCheck(WriteAddr,pBuffer,secremain);//写已经擦除了的,直接写入扇区剩余区间.
// }
if(NumToWrite==secremain)break;//写入结束了
else//写入未结束
{
secpos++; //扇区地址增1
secoff=0; //偏移位置为0
pBuffer+=secremain; //指针偏移
WriteAddr+=secremain*2; //写地址偏移(16位数据地址,需要*2)
NumToWrite-=secremain; //字节(16位)数递减
if(NumToWrite>(STM_SECTOR_SIZE/2))secremain=STM_SECTOR_SIZE/2;//下一个扇区还是写不完
else secremain=NumToWrite;//下一个扇区可以写完了
}
};
STMFLASH_Lock();//上锁
}[/mw_shl_code]
烧写APP之前的整片擦除程序
[mw_shl_code=c,true]//擦除函数
void iap_EraseFlashAPP(void)
{
u16 i=0;
STMFLASH_Unlock(); //解锁
while(1)//擦除整片程序区
{
if((FLASH_APP1_ADDR+i*STM_SECTOR_SIZE)>=FLASH_STORAGE_ADDR)//预留的变量断电保存区域,不能擦除
{
break;
}
STMFLASH_ErasePage(FLASH_APP1_ADDR+i*STM_SECTOR_SIZE);
i++;
}
STMFLASH_Lock();//上锁
}[/mw_shl_code]
数组的定义与申明
[mw_shl_code=applescript,true]u8 USART_RX_BUF1[USART_REC_LEN] __attribute__ ((at(0X20001000)));//接收缓冲,最大USART_REC_LEN个字节,起始地址为0X20001000.
u8 USART_RX_BUF2[USART_REC_LEN] __attribute__ ((at(0X20006000)));//接收缓冲,最大USART_REC_LEN个字节,起始地址为0X20006000.
#define USART_REC_LEN (20*1024) //定义最大接收字节数 20K
extern u8 USART_RX_BUF1[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符
extern u8 USART_RX_BUF2[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符
[/mw_shl_code]
接收数据
[mw_shl_code=applescript,true]u8 IAP_EN1=0;//IAP使能标志位1
u8 IAP_EN2=0;//IAP使能标志位2
u8 IAP_Receive_EN=0;//IAP接收使能标志位
u8 IAP_Receive_done=0;//IAP接收结束标志位
u32 IAP_RX_CNT=0; //接收的字节数
u16 IAP_RX_CNT1=0; //数组1接收的字节数
u16 IAP_RX_CNT2=0; //数组2接收的字节数
u8 IAPUpdataNum=0;//更新次数
//串口4中断函数
void UART4_IRQHandler(void)
{
u8 res;
if(UART4->SR&(1<<5))//接收到数据
{
res=UART4->DR;
if(IAP_Receive_EN==1)//IAP接收使能
{
if((IAP_RX_CNT-USART_REC_LEN*IAPUpdataNum)==USART_REC_LEN)//
{
if(IAPUpdataNum%2==0)
{
IAP_Receive_done=1;
IAP_RX_CNT1=0;
}
else
{
IAP_Receive_done=2;
IAP_RX_CNT2=0;
}
IAPUpdataNum++;
}
if(IAPUpdataNum%2==0)
{
USART_RX_BUF1[IAP_RX_CNT1++]=res;
}
else
{
USART_RX_BUF2[IAP_RX_CNT2++]=res;
}
IAP_RX_CNT++;
}
}
}[/mw_shl_code]
主函数中的处理代码
[mw_shl_code=c,true] if(IAP_RX_CNT)//允许更新
{
if(oldcount==IAP_RX_CNT)//新周期内,没有收到任何数据,认为本次数据接收完成.
{
applenth=IAP_RX_CNT;
oldcount=0;
IAP_RX_CNT=0;
IAP_EN1=0;
IAP_EN2=0;
IAP_Receive_EN=0;
if(((*(vu32*)(0X20001000+4))&0xFF000000)==0x08000000)//判断是否为0X08XXXXXX.
{
if(IAPUpdataNum%2==0)
{
iap_write_appbin(FLASH_APP1_ADDR+(USART_REC_LEN*IAPUpdataNum),USART_RX_BUF1,applenth-(USART_REC_LEN*IAPUpdataNum));//更新FLASH代码
}
else
{
iap_write_appbin(FLASH_APP1_ADDR+(USART_REC_LEN*IAPUpdataNum),USART_RX_BUF2,applenth-(USART_REC_LEN*IAPUpdataNum));//更新FLASH代码
}
send_uart4_string("User program reception completed!\r\n");
send_uart4_string("Firmware update completed!\r\n");
send_uart4_string("APP Length: ");
send_uart4_string(DataChangeNumberToString(applenth));
send_uart4_string("!\r\n ");
}
else
{
send_uart4_string("No APP!\r\n");
}
}
else
{
oldcount=IAP_RX_CNT;
}
if(IAP_Receive_done==1)//更新第一数组FLASH代码
{
iap_write_appbin(FLASH_APP1_ADDR+((IAPUpdataNum-1)*USART_REC_LEN),USART_RX_BUF1,USART_REC_LEN);
IAP_Receive_done=0;
send_uart4_string("Updata 1 Array!\r\n");
}
if(IAP_Receive_done==2)//更新第二数组FLASH代码
{
iap_write_appbin(FLASH_APP1_ADDR+((IAPUpdataNum-1)*USART_REC_LEN),USART_RX_BUF2,USART_REC_LEN);
IAP_Receive_done=0;
send_uart4_string("Updata 2 Array!\r\n");
send_uart4_string("APP Length: ");
send_uart4_string(DataChangeNumberToString(applenth));
send_uart4_string("!\r\n ");
}
}[/mw_shl_code]
|
|