[应用相关] 关于STM32 IAP

[复制链接]
2417|53
 楼主| susceptibility 发表于 2020-5-17 11:11 | 显示全部楼层
自己呢就是用的环形队列一边接收,一边写入,,,关于环形队列可以看我的环形队列的**,,,

http://www.cnblogs.com/yangfengwu/p/6822984.html
 楼主| susceptibility 发表于 2020-5-17 11:12 | 显示全部楼层
就再说一下自己的程序的一些地方

串口接收的
  1. voidUSART1_IRQHandler(void)//串口1中断服务程序
  2. {
  3. u8 Res;
  4. if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)//接收中断(接收到的数据必须是0x0d 0x0a结尾)
  5. {
  6. Res=USART_ReceiveData(USART1);//读取接收到的数据
  7. PutData(&Res,1);//把数据存入队列
  8. Usart1RecCnt ++;//数据个数
  9. }

  10. }
 楼主| susceptibility 发表于 2020-5-17 11:13 | 显示全部楼层
用的系统定时器中断来检测的串口空闲,判断接没接收到一条完整的数据--方法呢是看到人家的一种方法,感觉比自己以前的好,所以直接拿过来用了

关于单片机空闲中断可以看一下自己以前的

http://www.cnblogs.com/yangfengwu/p/6746403.html
 楼主| susceptibility 发表于 2020-5-17 11:13 | 显示全部楼层
  1. /*系统定时器中断*/voidSysTick_Handler(void)

  2. {

  3. SysTickCnt++;

  4. SysTickCnt1++;

  5. SysTickCnt2++;if(SysTickCnt1>=10)//每隔10毫秒检测一次

  6. {

  7. SysTickCnt1=0;if(Usart1RecCnt)//如果接收到数据了

  8. {if(IdleCnt ==Usart1RecCnt)//10ms时间数据没了变化

  9. {

  10. Usart1RecCntCopy=Usart1RecCnt;//拷贝数据个数

  11. Usart1RecCnt=0;//清零数据个数

  12. IdleCnt=0;//清零

  13. Usart1Flage=1;//接收到一条数据//rbDelete(&pRb);测试的时候销毁//rbCreate(&pRb,ReceBuff,USART_REC_LEN);//创建接收环形队列}else{

  14. IdleCnt=Usart1RecCnt;

  15. }

  16. }

  17. }

  18. }
 楼主| susceptibility 发表于 2020-5-17 11:14 | 显示全部楼层
我的IAP的接收的数据往Flash里面写和用户程序的往Flash里面写有一点不同,其实用户程序的往Flash里面写的程序是后期的改进...

先看我的IAP的
  1. if(rbCanRead(&pRb)>1)//如果环形队列里面的数据个数大于1

  2. {

  3. rbRead(&pRb, &ReadDat,2);//读取两个数据ReadDat16 = (u16)ReadDat[1]<<8;

  4. ReadDat16= ReadDat16|ReadDat[0];

  5. STMFLASH_Write(addr2,&ReadDat16,1);

  6. addr2+=2;

  7. }
monitoring 发表于 2020-5-17 11:16 | 显示全部楼层
if(rbCanRead(&pRb)>1)

因为一次性要往Flash里面写16位数据,所以才会判断数据个数大于一个的时候再往里面写.

虽然现在程序没有问题,但是我还在想如果程序的个数是奇数个就完啦!但是好像程序的个数总是偶数个....其实可以在判断接收完成的里面

做一下判断,如果数据还残留一个,那就写进去....
monitoring 发表于 2020-5-17 11:16 | 显示全部楼层
好,那就看一下判断接收完程序

  1. if(Usart1Flage ==1)//数据接收完成{

  2. addr2= FLASH_APP2_ADDR;//存储数据的地址Usart1Flage =0;//清零if(((*(vu32*)(FLASH_APP2_ADDR+4))&0xFF000000)==0x08000000)//判断是否为0X08XXXXXX.{

  3. printf("准备执行APP代码!!\r\n");

  4. UserDataAddr= FLASH_DATA_ADDR;//存储其余的数据地址ReadDat16 =0x55;//写入标志告诉IAP程序有可更新的用户程序STMFLASH_Write(UserDataAddr,&ReadDat16,1);

  5. UserDataAddr+=2;

  6. printf("写入0x55标志!!\r\n");

  7. ReadDat16= (u16)((Usart1RecCntCopy>>16)&0xffff);//存储接收到多少数据高位STMFLASH_Write(UserDataAddr,&ReadDat16,1);

  8. UserDataAddr+=2;

  9. ReadDat16= (u16)(Usart1RecCntCopy&0xffff);//存储接收到多少数据低位STMFLASH_Write(UserDataAddr,&ReadDat16,1);

  10. UserDataAddr+=2;

  11. Usart1RecCntCopy=0;

  12. printf("开始复位重启!!\r\n");

  13. Reset_MCU();

  14. }else{

  15. printf("非FLASH应用程序,无法执行!\r\n");

  16. }//printf("Cnt=%d\r\n",Usart1RecCntCopy);//for(i=0;i>8)<=15)//{//printf("0%x ",ReadDat16>>8);//}//else//{//printf("%x ",ReadDat16>>8);//}//}//addr1 = FLASH_APP1_ADDR;//for(i=0;i<40;i++)//{//STMFLASH_Erase(addr1,1024);//擦除FLASH_APP1_ADDR地址以及以上40页//addr1 +=2048;//}//addr1 = FLASH_APP1_ADDR;}
monitoring 发表于 2020-5-17 11:17 | 显示全部楼层
后边屏蔽的是测试的时候,看一下写入的数据,然后和源数据对比一下,看一下写入的对不对

if(((*(vu32*)(FLASH_APP2_ADDR+4))&0xFF000000)==0x08000000)

这句话

先问一个问题,怎么知道接收过来的是用户程序呢????要是别的数据怎么办???,,必须有一个判断依据才行对吧!!

就必须找到用户程序中永恒不变的变量....
monitoring 发表于 2020-5-17 11:18 | 显示全部楼层
然后呢,我是看别人的程序说,数据的第一个4个字节为栈顶地址,数据的第二个4字节为复位中断向量的入口地址
371995ec0acde1326f.png
monitoring 发表于 2020-5-17 11:18 | 显示全部楼层
FLASH_APP2_ADDR+4指针就移动到了IAP升级程序的E9或者说电压电流采集程序的D5上

(*(vu32*)(FLASH_APP2_ADDR+4))然后强制型的转成32位的,然后取出来,就是IAP升级程序的E9 20 00 08

或者说电压电流采集程序的D5 7E 00 08

还有一件事就是STM32是小端模式,,,,所谓小端模式就是低位在低地址,高位在高地址
monitoring 发表于 2020-5-17 11:19 | 显示全部楼层
举个例子

把60000存到STM32的Flash的,60000转换成16进制是EA60  EA是高8位,60是低八位,,存到Flash里面就是60EA这样存的

60存到了低地址,EA存到了高地址,,,,,当然有小端模式就有大端模式,,,大端模式就是低位在高地址,高位在低地址,电脑就是这样...
monitoring 发表于 2020-5-17 11:20 | 显示全部楼层
说到这里就要说一下共用体
  1. typedef union Resolver_I{longData;charData_Table[4];

  2. }Resolver_iData;

  3. typedef union Resolver_f{floatData;charData_Table[4];}Resolver_fData;

  4. Resolver_iData Resolver_7758;  //解析7758数据

  5. Resolver_fData Resolver_Usart; //解析串口数据
monitoring 发表于 2020-5-17 11:20 | 显示全部楼层
一个整形数据快速的转换成16进制存到数组里面

Resolver_7758.Data = 60000;

那么Resolver_7758.Data_Table[0] = 0x60;

Resolver_7758.Data_Table[1] = 0xEA;

Resolver_7758.Data_Table[2] = 0x00;

Resolver_7758.Data_Table[3] = 0x00;
monitoring 发表于 2020-5-17 11:21 | 显示全部楼层
一个浮点型的数据转换成16进制存到数组里面--其实也是按照IEEE754规约来计算的

Resolver_Usart.Data = 220.5;

那么Resolver_Usart.Data_Table[0] = 0x00;

Resolver_Usart.Data_Table[1] = 0x80;

Resolver_Usart.Data_Table[2] = 0x5C;

Resolver_Usart.Data_Table[3] = 0x43;
monitoring 发表于 2020-5-17 11:21 | 显示全部楼层
所以说上面的数据取出来就是08 00 20 E9然后&0xFF000000 肯定就等于 0x08000000啦

其实这样还有一个原因是因为32的地址是从08000000开始的,复位中断向量的地址的最高两位肯定是08啦!!!!

然后还有个if(((*(vu32*)appxaddr)&0x2FFE0000)==0x20000000) //检查栈顶地址是否合法.

这个......难道栈顶地址的最高位就是20......以后等看到相关的资料再说吧
monitoring 发表于 2020-5-17 11:22 | 显示全部楼层
有人这样介绍的--仔细看,细细品味....

http://blog.csdn.net/yx_l128125/article/details/12992773
monitoring 发表于 2020-5-17 11:23 | 显示全部楼层
对了说一下中断向量表

就从我的MSP430的**中摘抄过来
470385ec0ae0f1c897.png
128335ec0ae171e619.png
原文地址

http://www.cnblogs.com/yangfengwu/p/6064129.html
monitoring 发表于 2020-5-17 11:24 | 显示全部楼层
突然想起来一句话,知识是相通的....

32也有中断向量表,就像上面的430的似的,

只不过呢!32的中断函数的入口地址是可以改变的!!!(F0好像固定,但是看过一篇**好像也能通过某种方式改改)

我们写入IAP程序后单片机内部就有了一个中断向量表,这个呢是其内部一开始的固定的,
monitoring 发表于 2020-5-17 11:25 | 显示全部楼层
如果跳转到用户程序,用户程序肯定会有自己的中断函数吧!如串口,,定时器,,等等,,,,如果不改变中断向量表的话!!!产生的中断

岂不是跑到了IAP那边去了,IAP那边有自己的中断函数,,,乱了,彻底乱了,,,,,所以必须得让中断向量表改变改变,好让自己产生的

中断,执行自己的中断函数......

那就加一句话,或者修改一个地方

845155ec0ae8367790.png
172765ec0ae8a4c93e.png
monitoring 发表于 2020-5-17 11:25 | 显示全部楼层
再看我的用户程序的一个地方,,感觉自己罗嗦了
  1. if(AppFlage ==1)//接收到更新程序{if(rbCanRead(&pRb)>1)

  2. {

  3. rbRead(&pRb, &ReadDat,2);//读取两个数据ReadDat16 = (u16)ReadDat[1]<<8;

  4. ReadDat16= ReadDat16|ReadDat[0];

  5. STMFLASH_Write(addr2,&ReadDat16,1);

  6. addr2+=2;

  7. }

  8. }elseif(AppFlage ==0)

  9. {if(rbCanRead(&pRb)==8)

  10. {

  11. rbRead(&pRb, &TestData,8);//读取数据if(TestData[3] ==0x20&& TestData[7] ==0x08)//判断是否是更新程序{

  12. AppFlage=1;//要更新程序for(i=0;i<4;i++)//先写入这八位数据{

  13. ReadDat16= (u16)TestData[(i<<1)+1]<<8;

  14. ReadDat16= ReadDat16|TestData[i<<1];

  15. STMFLASH_Write(addr2,&ReadDat16,1);

  16. addr2+=2;

  17. }

  18. }

  19. }

  20. }
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 在线客服 返回列表 返回顶部