搜索
bottom↓
回复: 23

求助,用STM32开浮点单元后,使用类似fpX=*(FP32*)&cY;后出的问题

[复制链接]

出0入0汤圆

发表于 2012-11-12 23:01:16 | 显示全部楼层 |阅读模式
是这样,正在使用上届学长做的一个STM32F103做的电机驱动,用CAN总线来连接主机驱动器,其中电机驱动器将电机速度(浮点)通过CAN总线发来,然后STM32F407接收。在F407的接收函数中用到了这么一条语句:

然后只要运行到画红线的那一行就会HardFault,看汇编发现是运行到VLDR这条指令的时候挂,不知道为什么。
整个F407的工程是ucOS2.91的,按照论坛的帖子提示改好了ucOS在F407下用不了FPU的问题,在程序中其他地方使用浮点运算没有问题,就是这里不行,注释掉就没问题。
于是为了绕过VLDR指令就把程序临时改正这样了:

这样程序就能正常跑,但转换成的浮点数似乎不太对头...

于是我想问问为什么运行到VLDR这里就会挂呢? 是不是RCC那边还有某个寄存器没配置好?

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

 楼主| 发表于 2012-11-13 00:01:11 | 显示全部楼层
睡前顶一顶...

出0入0汤圆

发表于 2012-11-13 02:17:27 来自手机 | 显示全部楼层
从汇编看是地址对齐的问题,浮点地址没有四字节对齐,结构体具体什么样子的?

出0入0汤圆

 楼主| 发表于 2012-11-13 07:37:09 | 显示全部楼层
jisaowang 发表于 2012-11-13 02:17
从汇编看是地址对齐的问题,浮点地址没有四字节对齐,结构体具体什么样子的? ...

啊,果然没对齐!那为什么会有没对齐的时候? 编译器傻冒了么..= =

结构体就是stm32f10x_can.h里的那个:
/**
  * @brief  CAN Rx message structure definition  
  */

typedef struct
{
  uint32_t StdId;
  uint32_t ExtId;
  uint8_t IDE;
  uint8_t RTR;
  uint8_t DLC;
  uint8_t Data[8];
  uint8_t FMI;
} CanRxMsg;

出0入0汤圆

 楼主| 发表于 2012-11-13 07:39:55 | 显示全部楼层
jisaowang 发表于 2012-11-13 02:17
从汇编看是地址对齐的问题,浮点地址没有四字节对齐,结构体具体什么样子的? ...

还有switch里的unCanIdExt是一个联合体,把can扩展帧的标识符当参数来用:

typedef struct
{
        u32 Property      :8;
        u32 Channel       :8;
        u32 DeviceID        :8;
        u32 Priority                :4;
        u32 Reserve       :1;
}ST_CAN_ID_EXT;

typedef union
{
        u32 uiExtID;
        ST_CAN_ID_EXT stExtID;
}UN_CAN_ID_EXT;

出0入0汤圆

发表于 2012-11-13 08:21:23 | 显示全部楼层
楼主不要反抗了,直接换一种形式做吧,我也遇到了这样的问题
void GPS_Distance_Heading(float lat1,float lon1,float lat2,float lon2,float *Dist,float *Head){
}
只要是给指针 *Dist  *Head  赋值,都会产生错误。搞了好久,最后只好不用指针。这个问题应该只是浮点数才有的

出0入0汤圆

发表于 2012-11-13 08:27:24 | 显示全部楼层
F407没有启用FPU单元吧?所以一碰到V开头的指令就挂了。

出0入0汤圆

 楼主| 发表于 2012-11-13 09:17:04 来自手机 | 显示全部楼层
lisn3188 发表于 2012-11-13 08:21
楼主不要反抗了,直接换一种形式做吧,我也遇到了这样的问题
void GPS_Distance_Heading(float lat1,float  ...

不了个是吧...那该换成啥样啊? 现在替代的办法似乎不对头,读出的浮点数是十亿多= =
而且绕过去也不是个办法呀,现在这个隐患不解除以后又出问题就不好找了

出0入0汤圆

 楼主| 发表于 2012-11-13 09:24:16 来自手机 | 显示全部楼层
XA144F 发表于 2012-11-13 08:27
F407没有启用FPU单元吧?所以一碰到V开头的指令就挂了。

别的浮点指令都没问题,就是这个vldr不好使...

出0入0汤圆

发表于 2012-11-13 10:48:05 | 显示全部楼层
XA144F 发表于 2012-11-13 08:27
F407没有启用FPU单元吧?所以一碰到V开头的指令就挂了。

我的处理器是F105的,一样是不得。应该和 有没有启用FPU单元 没有关系。

出0入0汤圆

 楼主| 发表于 2012-11-13 11:25:00 | 显示全部楼层
问题找到点头绪了,执行到
0x08001AF8 ED908A02  VLDR          s16,[r0,#0x08]
时,此时r0的值是0x200005c7,加上0x08后就是0x200005cf,不是4字节对齐,执行后看Usage Fault里的UNALIGNED就被置位了,也就是说VLDR指令取目标地址应该是4字节对齐的。
为了验证,我把fpVelt=*(FP32*)&pRxMessage->Data[0];改成了....Data[1];
此时取到的目标地址就会对齐。试验后果然不出错了。于是应该就是目标地址的4字节对齐问题。
那现在问题就是该怎么从非4字节对齐的地址里取出浮点数的问题了= =....

出0入0汤圆

 楼主| 发表于 2012-11-13 15:08:37 | 显示全部楼层
jisaowang 发表于 2012-11-13 02:17
从汇编看是地址对齐的问题,浮点地址没有四字节对齐,结构体具体什么样子的? ...

现在好啦,这么写:
case 0x01://读取速度
  wtmp=*(SINT32*)&pRxMessage->Data[0];
  fpVelt=*(FP32*)&wtmp;
就没问题了,看汇编,编译器把fpVelt放在了r4,这样就没用到vldr指令了:

  185:                                                         wtmp=*(SINT32*)&pRxMessage->Data[0];
0x08001AF2 F8D7800B  LDR           r8,[r7,#0x0B]
   186:                                                         fpVelt=*(FP32*)&wtmp;
   187:                                                         //fpVelt=*(FP32*)&pRxMessage->Data[0];
0x08001AF6 4644      MOV           r4,r8
   188:                                                 break;
   189:                                         }

出0入0汤圆

发表于 2012-11-13 15:23:55 来自手机 | 显示全部楼层
编译器又不知道你需要对8bit的对象四字节对齐。。还是改改结构体,插个dummy的字节进去对齐。。。

出0入0汤圆

发表于 2012-11-13 15:25:19 来自手机 | 显示全部楼层
bigallium 发表于 2012-11-13 15:08
现在好啦,这么写:
case 0x01://读取速度
  wtmp=*(SINT32*)&pRxMessage->Data[0];

没看到vmov指令,你确定对了?

出0入0汤圆

 楼主| 发表于 2012-11-13 16:28:29 | 显示全部楼层
jisaowang 发表于 2012-11-13 15:23
编译器又不知道你需要对8bit的对象四字节对齐。。还是改改结构体,插个dummy的字节进去对齐。。。 ...

编译器把fpVelt放到r4里就不用VMOV了,后来用fpVelt *= (FP32)1.3; 测试对不对,得到结果是对的

之前试了在stm32f40x_can.h里把CanRxMsg结构体定义中加入了一个uint8_t Reserve,的确就没问题了,但如果can消息队列首地址本身就没有对齐的话还是会出错...索性就直接先把数原样传到int32中再放到fp32里了,就是比较麻烦= =

出0入0汤圆

发表于 2012-11-13 16:46:27 | 显示全部楼层
你的ucos的移植代码里 有保护浮点寄存器么....
vldmiaeq r0!, {s16-s31}  
类似这样的语句....

出0入0汤圆

 楼主| 发表于 2012-11-13 17:06:08 | 显示全部楼层
adce 发表于 2012-11-13 16:46
你的ucos的移植代码里 有保护浮点寄存器么....
vldmiaeq r0!, {s16-s31}  
类似这样的语句.... ...

当然有啦 要不然hardfault伺候的...

出0入24汤圆

发表于 2012-11-13 20:13:48 | 显示全部楼层
bigallium 发表于 2012-11-13 07:37
啊,果然没对齐!那为什么会有没对齐的时候? 编译器傻冒了么..= =

结构体就是stm32f10x_can.h里的那个: ...

查了M4的资料,有奖指令地址对齐的问题,如下

只有这几条可以不对齐访问,其余的指令统统不行,犯规都是fault伺候。
对比M3也是只有这几条指令可以不对齐访问。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

 楼主| 发表于 2012-11-13 20:30:15 | 显示全部楼层
20061002838 发表于 2012-11-13 20:13
查了M4的资料,有奖指令地址对齐的问题,如下

只有这几条可以不对齐访问,其余的指令统统不行,犯规都是 ...


嗯对,stm32f4编程手册也说了关于vldr的指令

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2013-9-30 16:30:51 | 显示全部楼层
bigallium 发表于 2012-11-13 20:30
嗯对,stm32f4编程手册也说了关于vldr的指令

楼主你好。
我个新手搞不明白什么是对齐,谁跟谁对齐啊?这是怎么一回事呢?
可否大概说下?先谢了!

出0入0汤圆

 楼主| 发表于 2013-9-30 19:36:12 | 显示全部楼层
kmani 发表于 2013-9-30 16:30
楼主你好。
我个新手搞不明白什么是对齐,谁跟谁对齐啊?这是怎么一回事呢?
可否大概说下?先谢了! ...

所谓对齐说白了就是变量地址是多少的倍数, 比如2字节对齐就是地址是2的倍数, 4字节对齐就是地址是4的倍数...

出0入0汤圆

发表于 2013-9-30 19:45:20 | 显示全部楼层
学习学习

出0入0汤圆

发表于 2013-9-30 21:06:33 | 显示全部楼层
bigallium 发表于 2013-9-30 19:36
所谓对齐说白了就是变量地址是多少的倍数, 比如2字节对齐就是地址是2的倍数, 4字节对齐就是地址是4的倍数 ...

也就说是 变量在内存中所在的地址吗?

出0入24汤圆

发表于 2013-9-30 22:21:35 | 显示全部楼层
kmani 发表于 2013-9-30 21:06
也就说是 变量在内存中所在的地址吗?

是的,就是这样子
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-6-16 23:16

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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