OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 3580|回复: 16

udp方式进行iap在线升级

[复制链接]

15

主题

59

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1400
金钱
1400
注册时间
2016-6-2
在线时间
166 小时
发表于 2016-9-21 14:23:07 | 显示全部楼层 |阅读模式
10金钱
本帖最后由 hyarcher25 于 2016-9-21 14:56 编辑

参考原子哥的udp通讯以及串口iap程序,已经写了一个上位机每次发1K的bin文件,发送和接收没有做校验,只为了实现最基础的,每隔200ms发送1K。app大概41K
IAP从0x8000000大小0xA000,40K  
APP从0x800A000大小0xF000,60K.APP程序已设置好SCB->VTOR = FLASH_BASE | 0xA000,IROM1也已经设置好;  

用的107的芯片,下载iap程序用jlink监控:
1.我用jlink监控iap程序里面的cishu接收计数为82次,意思是发了82*1024=82K的数据,但我实际bin文件也就41K,上位机也确实只发了41K。
2.每次在if(((*(vu32*)appxaddr)&0x2FFE0000)==0x20000000)处无法满足条件,0x0800A000是APP起始地址应该没错吧???

以下是iap程序里面的udp升级函数。
[mw_shl_code=cpp,true]#define FLASH_APP1_ADDR                0x0800A000 //APP地址
u8 udp_recvbuf[1024];
u16 recvlen;

u16 cishu;//接收计数

void udp_task(void)
{
err_t err;
struct udp_pcb *udppcb;
struct ip_addr rmtipaddr;

u8 res=0;

udp_demo_set_remoteip();//选择IP 192.168.1.106
udppcb=udp_new();
if(udppcb)//创建成功
{
  IP4_ADDR(&rmtipaddr,remoteip[0],remoteip[1],remoteip[2],remoteip[3]);
  err=udp_connect(udppcb,&rmtipaddr,UDP_PORT);
  if(err==ERR_OK)
  {
    err=udp_bind(udppcb,IP_ADDR_ANY,UDP_PORT);/绑定本地IP和端口号
    if(err==ERR_OK)        /绑定完成
    {
      udp_recv(udppcb,udp_demo_recv,NULL);//注册接收回调函数
    }else res=1;
  }else res=1;        
}else res=1;
while(res==0)
{
  if(recvlen==1024)//接收到1k数据
  {        
    iap_write_appbin((FLASH_APP1_ADDR+(cishu*1024)),udp_recvbuf,recvlen);//写flash
    cishu++;
  }
  if((recvlen<1024)&&(cishu>0))//接收数据小于1k,认为是最后一帧数据
  {
    iap_write_appbin((FLASH_APP1_ADDR+(cishu*1024)),udp_recvbuf,recvlen);//写flash
    recvlen=0;
    if(((*(vu32*)(FLASH_APP1_ADDR+4))&0xFF000000)==0x08000000)
    {        
      iap_load_app(FLASH_APP1_ADDR);//&#214;′DDFLASH APP′ú&#194;&#235;
    }
  }        
  if(udp_flag&1<<6)//是否接收到数据
  {
    udp_flag&=~(1<<6);//标记数据已经被处理
  }
  LwIP_Periodic_Handle(LocalTime);
  IWDG_Feed();
  }
}[/mw_shl_code]

udp接收回调函数
[mw_shl_code=cpp,true]
void udp_demo_recv(void *arg,struct udp_pcb *upcb,struct pbuf *p,struct ip_addr *addr,u16_t port)
{
        u32 data_len = 0;
        struct pbuf *q;
        if(p!=NULL)        //接收到不为空的数据时
        {
                memset(udp_recvbuf,0,UDP_RX_BUFSIZE);  //数据接收缓存清零
                for(q=p;q!=NULL;q=q->next)  //遍历完整个pbuf链表
                {
                        if(q->len > (UDP_RX_BUFSIZE-data_len))
                           memcpy(udp_recvbuf+data_len,q->payload,(UDP_RX_BUFSIZE-data_len));//拷贝数据
                        else
                          memcpy(udp_recvbuf+data_len,q->payload,q->len);
                          data_len += q->len;  
                        recvlen=q->len;
                        if(data_len > UDP_RX_BUFSIZE) break; //超出tcp客户端接收数组,跳出
                }
                upcb->remote_ip=*addr;                                 //记录远程主机IP地址
                upcb->remote_port=port;                          //记录远程主机端口
                remoteip[0]=upcb->remote_ip.addr&0xff;                 //IADDR4
                remoteip[1]=(upcb->remote_ip.addr>>8)&0xff; //IADDR3
                remoteip[2]=(upcb->remote_ip.addr>>16)&0xff;//IADDR2
                remoteip[3]=(upcb->remote_ip.addr>>24)&0xff;//IADDR1
                udp_flag|=1<<6;        //标记接收到数据了
                pbuf_free(p);//释放内存
        }else
        {
                udp_disconnect(upcb);
        }
} [/mw_shl_code]

iap.c的内容,我都没改直接用的例程的
[mw_shl_code=cpp,true]void iap_write_appbin(u32 appxaddr,u8 *appbuf,u32 appsize)
{
        u16 t;
        u16 i=0;
        u16 temp;
        u32 fwaddr=appxaddr;/当前写入的地址
        u8 *dfu=appbuf;
        for(t=0;t<appsize;t+=2)
        {                                                   
                temp=(u16)dfu[1]<<8;
                temp+=(u16)dfu[0];         
                dfu+=2;//偏移2个直接
                iapbuf[i++]=temp;            
                if(i==1024)
                {
                        i=0;
                        STMFLASH_Write(fwaddr,iapbuf,1024);        
                        fwaddr+=2048;//偏移2048
                }
        }
        if(i)STMFLASH_Write(fwaddr,iapbuf,i);//将最后的内容写进去
}

void iap_load_app(u32 appxaddr)
{
        if(((*(vu32*)appxaddr)&0x2FFE0000)==0x20000000) //检查栈顶地址是否合法
        {
                jump2app=(iapfun)*(vu32*)(appxaddr+4);
                MSR_MSP(*(vu32*)appxaddr);//初始化APP堆栈指针
                jump2app(); //跳转到APP
        }
}                 [/mw_shl_code]
求大神指点,gank!


IAP程序 - 副本.zip

11.56 MB, 下载次数: 254

最佳答案

查看完整内容[请看2#楼]

你考虑把接受的数据输出一下,或者断点调试看看数据内容。跟bin的数据比较看看对不对。
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

19

主题

430

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1341
金钱
1341
注册时间
2016-4-22
在线时间
187 小时
发表于 2016-9-21 14:23:08 | 显示全部楼层
你考虑把接受的数据输出一下,或者断点调试看看数据内容。跟bin的数据比较看看对不对。
伤情最是晚凉天,憔悴斯人不堪怜。
邀酒摧肠三杯醉,寻香惊梦五更寒。
钗头凤斜卿有泪,荼蘼花了我无缘。
小楼寂寞新雨月,也难如钩也难圆。
回复

使用道具 举报

21

主题

387

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1043
金钱
1043
注册时间
2016-9-8
在线时间
213 小时
发表于 2016-9-21 14:41:35 | 显示全部楼层
先不管数据处理,,,你把这两处发上来看看。
1.png
2.png
shop60994719.taobao.com
回复

使用道具 举报

15

主题

59

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1400
金钱
1400
注册时间
2016-6-2
在线时间
166 小时
 楼主| 发表于 2016-9-21 14:48:42 | 显示全部楼层
本帖最后由 hyarcher25 于 2016-9-21 14:53 编辑
密耳 发表于 2016-9-21 14:41
先不管数据处理,,,你把这两处发上来看看。

好的。这是app和iap的设置。
492032224327081156.jpg
784448462879793097.jpg
回复

使用道具 举报

21

主题

387

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1043
金钱
1043
注册时间
2016-9-8
在线时间
213 小时
发表于 2016-9-21 15:01:08 | 显示全部楼层
你IAP和app1写在一起啦??那IAP容量大小是多少知道吗??IAP要跳转到的是APP1的起始地址
shop60994719.taobao.com
回复

使用道具 举报

15

主题

59

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1400
金钱
1400
注册时间
2016-6-2
在线时间
166 小时
 楼主| 发表于 2016-9-21 15:08:16 | 显示全部楼层
密耳 发表于 2016-9-21 15:01
你IAP和app1写在一起啦??那IAP容量大小是多少知道吗??IAP要跳转到的是APP1的起始地址

没写一起吧??    IAP编译出来大概20多K。APP编译出来大概41K。
IAP从0x8000000开始,大小0xA000,40K  
APP从0x800A000开始,大小0xF000,60K
回复

使用道具 举报

15

主题

59

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1400
金钱
1400
注册时间
2016-6-2
在线时间
166 小时
 楼主| 发表于 2016-9-21 15:10:19 | 显示全部楼层
密耳 发表于 2016-9-21 15:01
你IAP和app1写在一起啦??那IAP容量大小是多少知道吗??IAP要跳转到的是APP1的起始地址

#define FLASH_APP1_ADDR                0x0800A000 //APP地址
已经在iap程序里面定义了app的起始地址了。
回复

使用道具 举报

21

主题

387

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1043
金钱
1043
注册时间
2016-9-8
在线时间
213 小时
发表于 2016-9-21 15:18:09 | 显示全部楼层
本帖最后由 密耳 于 2016-9-21 15:22 编辑

一般分成IAP APP1 APP2吧,IAP也就几K的代码。比如6K,则6K开始是程序APP1的入口,如果APP1有20K,则APP2的为26K开始,,STM32启动时有0000的IAP开始检测时要跳到6K开始的app1,还是26K地址的APP2,我是这么做的。。。当然你固件更新也可以覆盖APP1,一直从6K开始。。如果还不行,,你去我店里拍一个吧。。。
shop60994719.taobao.com
回复

使用道具 举报

15

主题

59

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1400
金钱
1400
注册时间
2016-6-2
在线时间
166 小时
 楼主| 发表于 2016-9-21 15:22:59 | 显示全部楼层
密耳 发表于 2016-9-21 15:18
一般分成IAP APP1 APP2吧,IAP也就几K的代码。比如6K,则6K开始是程序APP1的入口,如果APP1有20K,则APP2的 ...

好吧。。。我就一个APP。
我看原子哥例程用串口进行iap,里面的地址也是0x8000000,iap留了64k,跟着app地址0x8010000;感觉地址应该没什么问题。
回复

使用道具 举报

19

主题

430

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1341
金钱
1341
注册时间
2016-4-22
在线时间
187 小时
发表于 2016-9-21 15:46:05 | 显示全部楼层
hyarcher25 发表于 2016-9-21 15:22
好吧。。。我就一个APP。
我看原子哥例程用串口进行iap,里面的地址也是0x8000000,iap留了64k,跟着app ...

每个人都有自己的需求,参考就好。
我的iap预留96k,目前大概70k。
伤情最是晚凉天,憔悴斯人不堪怜。
邀酒摧肠三杯醉,寻香惊梦五更寒。
钗头凤斜卿有泪,荼蘼花了我无缘。
小楼寂寞新雨月,也难如钩也难圆。
回复

使用道具 举报

15

主题

59

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1400
金钱
1400
注册时间
2016-6-2
在线时间
166 小时
 楼主| 发表于 2016-9-21 15:47:55 | 显示全部楼层
ysq7120 发表于 2016-9-21 15:46
每个人都有自己的需求,参考就好。
我的iap预留96k,目前大概70k。

嗯嗯,这个大小应该是看需求,没有特定要求的。
回复

使用道具 举报

19

主题

430

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1341
金钱
1341
注册时间
2016-4-22
在线时间
187 小时
发表于 2016-9-21 15:54:03 | 显示全部楼层
1.最后一个包判断有错误。
2.udp数据无法保证正确性和顺序性,最好有数据校验,并且带应答,不然你还是用tcp吧。
伤情最是晚凉天,憔悴斯人不堪怜。
邀酒摧肠三杯醉,寻香惊梦五更寒。
钗头凤斜卿有泪,荼蘼花了我无缘。
小楼寂寞新雨月,也难如钩也难圆。
回复

使用道具 举报

15

主题

59

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1400
金钱
1400
注册时间
2016-6-2
在线时间
166 小时
 楼主| 发表于 2016-9-21 16:05:55 | 显示全部楼层
ysq7120 发表于 2016-9-21 15:54
1.最后一个包判断有错误。
2.udp数据无法保证正确性和顺序性,最好有数据校验,并且带应答,不然你还是用t ...

那。。。大神,请问最后一个包应该怎么判断呢~?
回复

使用道具 举报

21

主题

387

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1043
金钱
1043
注册时间
2016-9-8
在线时间
213 小时
发表于 2016-9-21 17:25:31 | 显示全部楼层
hyarcher25 发表于 2016-9-21 16:05
那。。。大神,请问最后一个包应该怎么判断呢~?

我们就用UDP做的,,没什么问题,,你能保证数据错误重发就行,,最后一个包也不用怎么处理,接收多少字节,写入FLASH多少自己就行,,怕的是你在整个传输过程中不能保证BIN文件接收的正确性,,那就成砖头了。。。
shop60994719.taobao.com
回复

使用道具 举报

19

主题

430

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1341
金钱
1341
注册时间
2016-4-22
在线时间
187 小时
发表于 2016-9-21 17:41:13 | 显示全部楼层
hyarcher25 发表于 2016-9-21 16:05
那。。。大神,请问最后一个包应该怎么判断呢~?


最后一个包按照你的代码如果你的bin刚好是1024的整数倍,你判断不到最后一个包的。如果是应答试的话你可以先发个包说明你的bin总共多大。当然udp数据部分不要全部bin的数据,弄几个字节出来附带一些必要的信息,那么也可以做到。
最好是应答式的,这样能保证数据不会错,丢包也能重复,不然一出问题就砖头了。
伤情最是晚凉天,憔悴斯人不堪怜。
邀酒摧肠三杯醉,寻香惊梦五更寒。
钗头凤斜卿有泪,荼蘼花了我无缘。
小楼寂寞新雨月,也难如钩也难圆。
回复

使用道具 举报

15

主题

59

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1400
金钱
1400
注册时间
2016-6-2
在线时间
166 小时
 楼主| 发表于 2016-9-21 18:06:24 | 显示全部楼层
ysq7120 发表于 2016-9-21 17:41
最后一个包按照你的代码如果你的bin刚好是1024的整数倍,你判断不到最后一个包的。如果是应答试的话你 ...

是的,这个我考虑过了,只是因为现在为了实现基本功能,而且我确定这个不是1024的整数倍,所以没进行处理,也没进行校验。
但是为啥现在每次判断if(((*(vu32*)(FLASH_APP1_ADDR+4))&0xFF000000)==0x08000000)都不正确呢。好奇怪哦头疼。
回复

使用道具 举报

15

主题

59

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1400
金钱
1400
注册时间
2016-6-2
在线时间
166 小时
 楼主| 发表于 2016-9-21 18:08:34 | 显示全部楼层
密耳 发表于 2016-9-21 17:25
我们就用UDP做的,,没什么问题,,你能保证数据错误重发就行,,最后一个包也不用怎么处理,接收多少字 ...

我也是接收多少个写多少个。但是问题大大的。。。头疼啊
或者您那边可以给个代码参考下不~
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-5-25 02:30

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表