OpenEdv-开源电子网

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

帮忙看看,结构体赋值引起HardFault异常怎么解决

[复制链接]

1

主题

5

帖子

0

精华

新手入门

积分
18
金钱
18
注册时间
2016-8-11
在线时间
2 小时
发表于 2016-8-11 17:35:52 | 显示全部楼层 |阅读模式
1金钱
现在有一个项目,使用STM32F030R8单片机,外挂W5500 TCP/IP协议栈,开发环境使用MDK5.14;单片机已更换过,或者单独运行有异常的代码,问题还是存在的;
单片机ROM为64K,内存8K,MDK使用默认设置;

项目编译后,调试运行到结构体赋值时产生了HardFault异常,找不到原因!
############MAP文件的信息#######################
==============================================================================


      Code (inc. data)   RO Data    RW Data    ZI Data      Debug   

     28704       1750       4984        172       3580     367126   Grand Totals
     28704       1750       4984        172       3580     367126   ELF Image Totals
     28704       1750       4984        172          0          0   ROM Totals

==============================================================================

    Total RO  Size (Code + RO Data)                33688 (  32.90kB)
    Total RW  Size (RW Data + ZI Data)              3752 (   3.66kB)
    Total ROM Size (Code + RO Data + RW Data)      33860 (  33.07kB)

==============================================================================

######################代码#########################
下面是代码:
  头文件中的结构体定义:
typedef struct _RIP_MSG
{
uint32 xid;    <----------------------------向这个元素赋值就会异常!!!
   uint8  op;
   uint8  htype;
   uint8  hlen;
   uint8  hops;
   uint16 secs;
   uint16 flags;
   uint8  ciaddr[4];
   uint8  yiaddr[4];
   uint8  siaddr[4];
   uint8  giaddr[4];
   uint8  chaddr[16];
   uint8  sname[64];
   uint8  file[128];
   uint8  OPT[312];

}RIP_MSG;
---------------------------------------------------------------------------------------------------------------------
C文件中的代码:
uint8 EXTERN_DHCPBUF[1024];//定义数组
RIP_MSG * pRIPMSG = (RIP_MSG*)EXTERN_DHCPBUF;                        //定义结构体指针
---------------------------------------------------------------------------------------------------------------------
产生异常的代码(如果注释掉这些代码,整个工程就可以正常运行):
        memset((void*)pRIPMSG,0,sizeof(RIP_MSG));                        //  发生异常  将结构体初始化为0 ,
或:
        pRIPMSG->op = DHCP_BOOTREQUEST;//没异常
        pRIPMSG->htype = DHCP_HTYPE10MB;//没异常
        pRIPMSG->hlen = DHCP_HLENETHERNET;//没异常
        pRIPMSG->hops = DHCP_HOPS;//没异常
        temp= (unsigned int *)pRIPMSG->xid; //没异常
  *temp=  htonl(DHCP_XID);  //发生异常  这里htonl(DHCP_XID)的数值=0x78563412;



调试时的汇编代码:
    99:         temp= (unsigned int *)pRIPMSG->xid;
0x08005FB6 489F      LDR      r0,[pc,#636]  ; @0x08006234
0x08005FB8 6800      LDR      r0,[r0,#0x00]
0x08005FBA 6805      LDR      r5,[r0,#0x00]
   100:   *temp=  htonl(DHCP_XID);
0x08005FBC 489E      LDR      r0,[pc,#632]  ; @0x08006238
0x08005FBE 6800      LDR      r0,[r0,#0x00]
0x08005FC0 F7FFFBFC  BL.W     htonl (0x080057BC)
0x08005FC4 6028      STR      r0,[r5,#0x00]  //在这里发生异常

---------------------------------------------------------------------------------------------------------------------
麻烦各位,帮忙看看哪里有问题?





最佳答案

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

已经解决这个问题了,所有的uint32/或uint8/16都换成unsigned int /unsigned char /unsigned short; 然后所有的定义都加上_paked typedef ****
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

1

主题

5

帖子

0

精华

新手入门

积分
18
金钱
18
注册时间
2016-8-11
在线时间
2 小时
 楼主| 发表于 2016-8-11 17:35:53 | 显示全部楼层
止天 发表于 2016-8-15 08:07
RIP_MSG  里面的东西好像没有不对齐的

已经解决这个问题了,所有的uint32/或uint8/16都换成unsigned int /unsigned char /unsigned short;
然后所有的定义都加上_paked  typedef ****  
回复

使用道具 举报

9

主题

538

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3371
金钱
3371
注册时间
2015-1-7
在线时间
794 小时
发表于 2016-8-11 22:20:42 | 显示全部楼层
EXTERN_DHCPBUF[1024]这个数组在flash里吗?
回复

使用道具 举报

22

主题

751

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1605
金钱
1605
注册时间
2015-6-10
在线时间
222 小时
发表于 2016-8-12 08:05:35 | 显示全部楼层
ianhom 发表于 2016-8-11 22:20
EXTERN_DHCPBUF[1024]这个数组在flash里吗?

不是 在内存里

  只是类似共用体的东西
回复

使用道具 举报

22

主题

751

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1605
金钱
1605
注册时间
2015-6-10
在线时间
222 小时
发表于 2016-8-12 08:10:29 | 显示全部楼层
temp= (unsigned int *)pRIPMSG->xid; 这是把数值强制转化为指针

temp= (unsigned int *)(&pRIPMSG->xid);改成这样也是很诡异

你要是想向xid赋值为什么不直接给
pRIPMSG->xid =  htonl(DHCP_XID);
回复

使用道具 举报

19

主题

430

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1341
金钱
1341
注册时间
2016-4-22
在线时间
187 小时
发表于 2016-8-12 08:35:31 | 显示全部楼层
temp= (unsigned int *)pRIPMSG->xid;
这个转的不对吧。要加&
不过 memset((void*)pRIPMSG,0,sizeof(RIP_MSG));  错误就没看出来什么问题
伤情最是晚凉天,憔悴斯人不堪怜。
邀酒摧肠三杯醉,寻香惊梦五更寒。
钗头凤斜卿有泪,荼蘼花了我无缘。
小楼寂寞新雨月,也难如钩也难圆。
回复

使用道具 举报

1

主题

5

帖子

0

精华

新手入门

积分
18
金钱
18
注册时间
2016-8-11
在线时间
2 小时
 楼主| 发表于 2016-8-12 14:26:17 | 显示全部楼层
止天 发表于 2016-8-12 08:10
temp= (unsigned int *)pRIPMSG->xid; 这是把数值强制转化为指针

temp= (unsigned int *)(&pRIPMSG-> ...

pRIPMSG->xid =  htonl(DHCP_XID);

直接赋值是出现异常的
回复

使用道具 举报

22

主题

751

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1605
金钱
1605
注册时间
2015-6-10
在线时间
222 小时
发表于 2016-8-12 16:56:26 | 显示全部楼层
sunnyhgh 发表于 2016-8-12 14:26
pRIPMSG->xid =  htonl(DHCP_XID);

直接赋值是出现异常的

怎么异常
回复

使用道具 举报

25

主题

683

帖子

0

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
1351
金钱
1351
注册时间
2012-4-25
在线时间
195 小时
发表于 2016-8-12 17:10:54 | 显示全部楼层
1 。首先 要对这指针进行个初始
RIP_MSG * pRIPMSG = (RIP_MSG*)EXTERN_DHCPBUF;                        //定义结构体指针

2. 然后你才能这样用,void*也不用转了
memset(pRIPMSG,0,sizeof(RIP_MSG));                        //  发生异常  将结构体初始化为0 ,

3. 你后面的赋值基础 都是首先这  pRIPMSG !=0 为基础。
4.为什么 你前几个赋值没问题,最后个pRIPMSG->xid  就异常了,自己想想看你指针 对 0地址操作了
1-1
回复

使用道具 举报

1

主题

5

帖子

0

精华

新手入门

积分
18
金钱
18
注册时间
2016-8-11
在线时间
2 小时
 楼主| 发表于 2016-8-13 08:16:43 | 显示全部楼层

赋值就会HardFault异常,后来我将程序里面所有的uint8或uint16/uint32全部换成unsigned char,unsigned short 和unsigned int ,这种赋值就没有异常了。
比如下面的结构体指针定义:
#pragma pack(1)
typedef struct _RIP_MSG
{
       
   unsigned char   op;
   unsigned char   htype;
   unsigned char   hlen;
   unsigned char   hops;
         unsigned long xid;
   unsigned short secs;
   unsigned short flags;
   unsigned char   ciaddr[4];
   unsigned char   yiaddr[4];
   unsigned char   siaddr[4];
   unsigned char   giaddr[4];
   unsigned char   chaddr[16];
   unsigned char   sname[64];
   unsigned char   file[128];
   unsigned char   OPT[312];

}RIP_MSG ;
定义结构体的时候还必须使用#pragma pack(1);
其他的#pragma pack(2)或#pragma pack(4)都不行;
不过这样修改还会存在一个问题,就是读内存地址的问题,比如:

unsigned int * temp;
unsigned char  * p;

temp=((unsigned int*)p);
dhcp_lease_time = ntohl(*temp);//ntohl大端转小端

只要进行*temp的读操作,就会HardFault异常,因为tem的地址=0x20000571,地址不是对齐的;
回复

使用道具 举报

1

主题

5

帖子

0

精华

新手入门

积分
18
金钱
18
注册时间
2016-8-11
在线时间
2 小时
 楼主| 发表于 2016-8-13 08:19:23 | 显示全部楼层
mygod 发表于 2016-8-12 17:10
1 。首先 要对这指针进行个初始
RIP_MSG * pRIPMSG = (RIP_MSG*)EXTERN_DHCPBUF;                       ...

这个指针是上电就会赋值的
RIP_MSG * pRIPMSG = (RIP_MSG*)EXTERN_DHCPBUF;        
pRIPMSG->xid这个操作是,赋值到不是4字节对齐的地址,导致异常;
回复

使用道具 举报

25

主题

683

帖子

0

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
1351
金钱
1351
注册时间
2012-4-25
在线时间
195 小时
发表于 2016-8-13 10:40:33 | 显示全部楼层
sunnyhgh 发表于 2016-8-13 08:19
这个指针是上电就会赋值的
RIP_MSG * pRIPMSG = (RIP_MSG*)EXTERN_DHCPBUF;        
pRIPMSG->xid这个 ...

就算不是4字节对齐也是错误 错误 不是引会 异常 的,你会用调试吗,一下子就明白了

  temp= (unsigned int *)pRIPMSG->xid; //没异常
读 0 时候 肯定 可以了

*temp=  htonl(DHCP_XID);
temp =0 时候,往 0地址写数据当然会异常了

1-1
回复

使用道具 举报

22

主题

751

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1605
金钱
1605
注册时间
2015-6-10
在线时间
222 小时
发表于 2016-8-15 08:07:07 | 显示全部楼层
RIP_MSG  里面的东西好像没有不对齐的


这么玩试试
uint32 EXTERN_DHCPBUF1[256];
uint8* EXTERN_DHCPBUF = (uint8 *)EXTERN_DHCPBUF1;//定义数组
RIP_MSG * pRIPMSG = (RIP_MSG*)EXTERN_DHCPBUF;                        //定义结构体指针
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-6-6 21:40

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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