rtthread 字节对齐问题 int指针访问非对齐地址崩溃
环境:
SOC: i.MX RT1050
底板: 野火 RT1052
Kernel: rt-thread

背景:
我正在实现解析udp包, 而udp包的结构不是字节对齐的, 这个时候我使用__packed来说明按照1字节对齐, 在解析udp包数据的地方, 取udp->srcaddr这个成员的值的时候, 出现 UNALIGN(未对齐) 错误. 我将该问题用以下代码来复现. 如果有更好的网络协议数据结构体定义方式, 还请告知, 谢谢

现象:
使用rtthread master版 生成的工程运行后会出现以下问题, 但使用裸机程序, 或者 rtthread nano版 运行后不会出现以下问题. 这个问题还未有答案, 如果有哪位道友, 遇到了, 一起学习探讨

/*1.内存 堆区a.uint32_t* 类型, 所指向的地址必须是四字节对齐b.uint16_t* 类型, 所指向的地址必须是两字节对齐2.内存 RW/ZI 区a.uint32_t* 类型, 所指向的地址必须是四字节对齐b.uint16_t* 类型, 所指向的地址必须是两字节对齐3.DTCMa.uint32_t* 类型, 非四字节对齐地址任然可以访问b.uint16_t* 类型, 非两字节对齐地址任然可以访问4.内存 栈区定义一字节对齐结构体, 任意成员可以访问5.内存 栈区 char数组a.uint32_t* 类型, 非四字节对齐地址无法访问a.uint16_t* 类型, 非两字节对齐地址无法访问*//* 内存 栈区 char数组 __packed char data[128];rt_kprintf("&data[0]: %p\n", &data[0]);__packed uint32_t* p = (__packed uint32_t*)(&data[0]);rt_kprintf("*p: %x\n", *p);p = (__packed uint32_t*)(&data[0]+1);rt_kprintf("p: %p\n", p);rt_kprintf("*p: %x\n", *p);__packed uint16_t* p2 = (__packed uint16_t*)(data);rt_kprintf("*p2: %x\n", *p2);p2 = (__packed uint16_t*)(data+1);rt_kprintf("*p2: %x\n", *p2);p2 = (__packed uint16_t*)(data+3);rt_kprintf("*p2: %x\n", *p2);*/rt_kprintf("sizeof(eth_hdr): %d; sizeof(ip_hdr): %d\n",sizeof(eth_hdr),sizeof(ip_hdr));uint8_t* tpoint = (uint8_t*)malloc(60);rt_kprintf("tpoint: %p\n", tpoint);eth_hdr* ethhdr = (eth_hdr*)tpoint;tpoint += sizeof(eth_hdr);ip_hdr* iphdr = (ip_hdr*)tpoint;rt_kprintf("tpoint: %p\n", tpoint);rt_kprintf("iphdr: %p\n", iphdr);iphdr->tlen = 0x10;rt_kprintf("iphdr->tlen: %x\n", iphdr->tlen);rt_kprintf("&iphdr->srcaddr: %p\n", &iphdr->srcaddr);iphdr->srcaddr = 0x1111;rt_kprintf("iphdr->srcaddr: %x\n", iphdr->srcaddr);/* 内存 栈区 一字节对齐结构体访问 ip_hdr iphdr;iphdr.srcaddr = 0x1111;rt_kprintf("sizeof(iphdr): %d\n", sizeof(iphdr));rt_kprintf("iphdr.srcaddr: %d\n", iphdr.srcaddr);*//* DTCM 0x20000000 uint32_t* p = (uint32_t*)0x20000000;rt_kprintf("*p: %x\n", *p);p = (uint32_t*)0x20000004;rt_kprintf("*p: %x\n", *p);p = (uint32_t*)0x20000008;rt_kprintf("*p: %x\n", *p);uint16_t* p2 = (uint16_t*)0x20000000;rt_kprintf("*p2: %x\n", *p2);p2 = (uint16_t*)0x20000002;rt_kprintf("*p2: %x\n", *p2);p2 = (uint16_t*)0x20000004;rt_kprintf("*p2: %x\n", *p2);p = (uint32_t*)0x20000001;rt_kprintf("*p: %x\n", *p);p2 = (uint16_t*)0x20000001;rt_kprintf("*p2: %x\n", *p2);p2 = (uint16_t*)0x20000003;rt_kprintf("*p2: %x\n", *p2);*//* 内存 RW/ZI 区, 字节对齐测试 uint32_t* p = (uint32_t*)0x80200000;rt_kprintf("*p: %x\n", *p);p = (uint32_t*)0x80200004;rt_kprintf("*p: %x\n", *p);p = (uint32_t*)0x80200008;rt_kprintf("*p: %x\n", *p);uint16_t* p2 = (uint16_t*)0x80200000;rt_kprintf("*p2: %x\n", *p2);p2 = (uint16_t*)0x80200002;rt_kprintf("*p2: %x\n", *p2);p2 = (uint16_t*)0x80200004;rt_kprintf("*p2: %x\n", *p2);p = (uint32_t*)0x80200001;rt_kprintf("*p: %x\n", *p);p2 = (uint16_t*)0x80200001;rt_kprintf("*p2: %x\n", *p2);p2 = (uint16_t*)0x80200003;rt_kprintf("*p2: %x\n", *p2);*//* 堆区, 字节对齐测试uint32_t* p = (uint32_t*)0x802059a0;rt_kprintf("*p: %x\n", *p);p = (uint32_t*)0x802059a4;rt_kprintf("*p: %x\n", *p);p = (uint32_t*)0x802059a8;rt_kprintf("*p: %x\n", *p);uint16_t* p2 = (uint16_t*)0x802059a0;rt_kprintf("*p2: %x\n", *p2);p2 = (uint16_t*)0x802059a2;rt_kprintf("*p2: %x\n", *p2);p2 = (uint16_t*)0x802059a4;rt_kprintf("*p2: %x\n", *p2);p = (uint32_t*)0x802059a1;rt_kprintf("*p: %x\n", *p);p2 = (uint16_t*)0x802059a1;rt_kprintf("*p2: %x\n", *p2);p2 = (uint16_t*)0x802059a3;rt_kprintf("*p2: %x\n", *p2);*/

程序崩溃报错图示:

在 rtthread nano版 中执行 “内存 RW/ZI 区” 测试, 测试结果如下

新的怀疑点

从图中第一行可以看出, 以太网协议数据头结构体大小为14个字节(不为4的整数倍), 而ARP协议数据头结构体, IP协议数据头结构体, UDP协议数据头结构体大小均为4的整数倍. 而保存数据的地址如图中的0x802114ac, 是可以被4整除的. 那么该地址偏移14个字节后地址为0x802114ba, 显然该地址不被4整除. 我在猜测问题是否出在这里呢? 如果数据偏移以太网协议数据头大小到达 ARP协议数据的初始位置. 该地址是4的整数倍, 情况有会是怎么样呢?
我尝试在循环前分别定义了

eth_hdr recv_eth_hdr;
ip_hdr recv_ip_hdr;
icmp_hdr recv_icmp_hdr;
arp_data recv_arp_data;

四个结构体, 然后在检测协议数据前, 从tpoint指针所指向的地址开始, 将接头体大小的数据拷贝到以上定义的结构体中, 然后再来做检测. 然而问题依旧存在, 但问题的范围更加小了, 那就是操作0x802114ba这个地址上的数据就会导致崩溃, 那为什么会这样呢? 我看后面只能通过看汇编源代码, 才能找到问题的症结所在啊.

最后对照代码发现跟以下代码有关系, 具体原因后面在研究

#if defined(BSP_USING_SDRAM)/* Region 7 setting */MPU->RBAR = ARM_MPU_RBAR(7, 0x80000000U);MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 1, 0, ARM_MPU_REGION_SIZE_32MB);/* Region 8 setting */MPU->RBAR = ARM_MPU_RBAR(8, 0x81E00000U);MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 1, 1, 0, 0, 0, ARM_MPU_REGION_SIZE_2MB);
#endif

搜索到的相关信息
1
mpu内存保护单元寄存器种类及相关编程
ARM存储器之:存储保护单元MPU
M=0: 禁止MPU
M=1: 使能MPU
A(bit[1])选择是否支持内存访问地址对齐检查
B=0: 禁止地址对齐检查
B=1: 使能地址对齐检查

2
【安富莱STM32F407之uCOS-III教程】第6章 内存保护单元MPU
SCB->CCR |= SCB_CCR_STKALIGN_Msk; // 使能堆栈的双字对齐模式

3
访问未对齐的内存引起硬件异常的解决方法
该代码初始化MPU,使得SDRAM存储器区域被认为是Normal Memory type,而不是Device Memory type。 这将禁用访问对齐限制。

rtthread 字节对齐问题 int指针访问非对齐地址崩溃相关推荐

  1. ARM非对齐访问和Alignment Fault

    转载自ARM非对齐访问和Alignment Fault - 者旨於陽 - 博客园 (cnblogs.com) 1.指令对齐 A64指令必须word对齐.尝试在非对齐地址取值会触发PC alignmen ...

  2. 结构体成员非对齐访问所带来的思考

    [摘要]本文介绍了内存访问时为什么需要对齐及不对齐时带来的影响.接着介绍了如何改变对齐规则来保证CPU能够访问非对齐内存.最后介绍了结构体设计时需要注意的问题,如何调整成员顺序或者填充特定单元来避免平 ...

  3. c语言 怎么访问64位地址_大神用10000字总结了嵌入式C语言必学知识点……

    导读:怎么做好嵌入式?相信这个问题无论问谁你都会得到一句学好C语言!今天推荐一篇大佬写的嵌入式C语言知识点总结,非常值得一读. 从语法上来说C语言并不复杂, 但编写优质可靠的嵌入式C程序并非易事,不仅 ...

  4. [转]MIPS 下非对齐访问的问题

    1.问题 MIPS 下使用访存指令读取或写入数据单元时,目标地址必须是所访问之数据单元字节数的整数倍,这个叫做地址对齐. 比如在 MIPS 平台上,lh 读取一个半字时,存储器的地址必须是 2 的整数 ...

  5. Axi:名词解释、乱序、间插、卷绕、窄带访问、非对齐访问、OST

    信号说明: AWBURST.ARBURST: 指示burst type,有3种burst类型. Fixed:固定地址模式,每次burst传输首地址固定,用于访问FIFO INC:递增递增模式,每次传输 ...

  6. ARMv8-A非对齐数据访问支持(Alignment support)

    目录 1,对齐传输和非对齐传输 2,AArch32 Alignment support 2.1 Instruction alignment 指令对齐 2.2 Unaligned data access ...

  7. TIA博途中如何使用符号方式按位,字节,字访问非结构数据类型

    TIA博途中如何使用符号方式按位,字节,字访问非结构数据类型? 对于S7-1200 和 S7-1500,可以按1位,8位,16位和32位的长度访问已经声明的变量. 前提条件: • 对于S7-1200( ...

  8. 2万字 + 50 张图,细说 JVM 内存分布、内存对齐、压缩指针

    今天为大家带来一篇 2 万字的硬核技术文章. 本文我们将从计算机组成原理的角度详细阐述对象在JVM内存中是如何布局的,以及什么是内存对齐,如果我们头比较铁,就是不进行内存对齐会造成什么样的后果,最后引 ...

  9. 7. 重磅硬核 | 一文聊透对象在JVM中的内存布局,以及内存对齐和压缩指针的原理及应用

    重磅硬核 | 一文聊透对象在JVM中的内存布局,以及内存对齐和压缩指针的原理及应用 大家好,我是bin,又到了每周我们见面的时刻了,我的公众号在1月10号那天发布了第一篇文章?<从内核角度看IO ...

最新文章

  1. 一个常用的表单文本框input输入提示
  2. 解微分方程_matlab
  3. 常见设备分辨率大小,响应式必备啊
  4. 最大似然估计和最大后验概率
  5. 二次规划的一个很好的课件网站
  6. html隐藏块元素过度动画,CSS3实现DIV图层隐藏到显示的过渡效果
  7. 数据可视化【十四】交互式过滤地区分布图
  8. --save 和--save-dev的区别
  9. 论文浅尝 | SPARQL 语言的 ASK 查询表达性研究进展
  10. Windows下使用taskkill 命令批量结束进程
  11. 你画我猜游戏html源代码,微信小程序你画我猜demo完整源码
  12. 一个查英语缩写的网站
  13. ewb交通灯报告和文件_数字电路基础红绿灯实验报告.docx
  14. 重返设计模式--状态模式
  15. 3.4.1 在物理层扩展以太网
  16. 全局钩子(hook鼠标键盘消息)
  17. php curl exec 返回值,php curl_exec()函数 CURL获取返回值的方法
  18. 使用网云穿内网穿透 实现外网访问内网金蝶(ERP)系统
  19. 如何做一个“完美”的业余游戏策划(zt)
  20. 秋叶喻死亡,是用诗来

热门文章

  1. 解压玩具出口欧盟CE认证具体要求
  2. java编程手机gps定位_GPS 获取Gps定位信息的Android源码实例,通过这个JAVA 目,你可能学会GPS在 手机 238万源代码下载- www.pudn.com...
  3. hadoop eclipse 插件 EP2
  4. 主成分分析matlab代码实现
  5. 诺基亚x6怎么打开位置服务器,数码教程资讯:诺基亚x6怎么更换导航栏位置
  6. python中偏函数的应用
  7. python模拟足球射门_Python玩个球,如何用PyQt5实现足球射门动画?
  8. Dell戴尔笔记本电脑G7 17 7700原装出厂系统恢复原厂系统2004
  9. ubuntu安装方案(联想P52,P2000显卡)
  10. EXCEL round()roundup() rounddowm()使用