BUG——imx6u开发_结构体导致的死机问题(未解决)

简介:

最近在做imx6u的linux下裸机驱动开发,由于是学习的初级阶段,既没有现成的IDE可以使用,也没有GDB等在线调试工具,只能把代码烧写在SD卡上再反复插拔,仅靠卑微的亮灯来判断程序死在哪一步。

至于没有使用串口的原因是,我现在就是卡在了这个串口的开发上。我的感受和这位老兄大抵是相同的

问题为:对下面结构体局部变量的定义前面加上volatile关键字,结果程序运行到这步时,直接卡死。理论上,并不应该会出现这种情况

cpp 复制代码
typedef struct
 {
     uint8_t HYS;   // 迟滞
     uint8_t PULL;  // 上拉/下拉
     uint8_t ODE;   // 开漏
     uint8_t SPEED; // 速度
     uint8_t DSE;   // 驱动强度
     uint8_t SRE;   // 转换速率
     uint8_t SION; // 软件输入             
 } MyStruct;


/*------------在某个函数内部---------------*/

//定义一个局部变量时会卡死
volatile MyStruct my2 = {0};

尝试

对此,我做了一些尝试,但仍未能找到根本原因:

1,猜测是成员变量导致的问题

于是,我对成员变量的类型做了一些改变,发现,只要不都是uint8_t或者char类型就不会卡死

cpp 复制代码
typedef struct
 {
     uint16_t HYS;   // 迟滞
     uint8_t PULL;  // 上拉/下拉
     uint8_t ODE;   // 开漏
     uint8_t SPEED; // 速度
     uint8_t DSE;   // 驱动强度
     uint8_t SRE;   // 转换速率
     uint8_t SION; // 软件输入             
 } MyStruct;

typedef struct
 {
     uint8_t HYS;   // 迟滞
     uint8_t PULL;  // 上拉/下拉
     uint8_t ODE;   // 开漏
     uint8_t SPEED; // 速度
     uint8_t DSE;   // 驱动强度
     uint8_t SRE;   // 转换速率
     uint32_t SION; // 软件输入             
 } MyStruct;

同时,对成员变量的数量做了一些改变,只要不是7个uint8_t或char类型,就不会卡死

cpp 复制代码
typedef struct
{
    uint16_t HYS ;   // 迟滞
    uint16_t PULL ;  // 上拉/下拉
    uint16_t ODE ;   // 开漏
    uint16_t SPEED ; // 速度
    uint16_t DSE ;   // 驱动强度
    uint16_t SRE ;   // 转换速率
    uint16_t SION ;  // 软件输入

} MyStruct;

typedef struct
 {
     uint8_t HYS;   // 迟滞
     uint8_t PULL;  // 上拉/下拉
     uint8_t ODE;   // 开漏
     uint8_t SPEED; // 速度
     uint8_t DSE;   // 驱动强度
     uint8_t SRE;   // 转换速率
     uint8_t SION; // 软件输入   
     uint8_t SIO; // 软件输入             
 } MyStruct;

此外,改变了结构体名也仍会出现上面问题

2,怀疑是优化级别导致的问题

由于我默认开的是-O2级别优化,为此,对上述代码进行了-Og、-O0、-O1、-O2、-O3优化(没少被-O2坑过),结果仍会出现相同的问题。此外也怀疑过是堆栈溢出,但是栈大小足足设置了2MB,并且通过增加不优化的无关变量数组排除掉了这个可能。

3,怀疑是变量定义导致的

于是尝试了下面几种形式,只要最后一种会出现这种问题。奇怪的是第三种竟然没出现问题(这可能是个伏笔)

cpp 复制代码
   MyStruct my1;

   MyStruct my1 = {0};

   volatile MyStruct my1;

   volatile MyStruct my1 = {0};

4,怀疑是内存排列导致的问题(最有可能)

对此,使用了__attribute__((aligned(4/6/8/16/32)));进行测试,仍然不能解决问题,改变了成员变量排列顺序(像是无用功)仍未解决

后来使用了位域来测试,如果是uint32_t、uint16_t等组成的位域,哪怕都是8位位宽也不会出现问题。如果是7个uint8_t类型,倘若位宽不尽相同的话,那么也可能不会出现问题。

cpp 复制代码
typedef struct
{
    uint16_t HYS : 8;   // 迟滞
    uint16_t PULL : 8;  // 上拉/下拉
    uint16_t ODE : 8;   // 开漏
    uint16_t SPEED : 8; // 速度
    uint16_t DSE : 8;   // 驱动强度
    uint16_t SRE : 8;   // 转换速率
    uint16_t SION : 8;  // 软件输入

} MyStruct;

typedef struct
{
    uint8_t HYS : 5;   // 迟滞
    uint8_t PULL : 5;  // 上拉/下拉
    uint8_t ODE : 5;   // 开漏
    uint8_t SPEED : 5; // 速度
    uint8_t DSE : 5;   // 驱动强度
    uint8_t SRE : 5;   // 转换速率
    uint8_t SION : 5;  // 软件输入

} MyStruct1;

typedef struct
{
    uint8_t HYS : 8;   // 迟滞
    uint8_t PULL : 8;  // 上拉/下拉
    uint8_t ODE : 8;   // 开漏
    uint8_t SPEED : 8; // 速度
    uint8_t DSE : 8;   // 驱动强度
    uint8_t SRE : 8;   // 转换速率
    uint8_t SION : 8;  // 软件输入

} MyStruct2;

进一步测试中发现,在选用7个uint8_t的情况下,如果位宽都为1、2、3、4就不会出现问题,如果是其余数字(包括8)就会出现问题。也就是说位宽都低于4(包括4),就不会发生问题。

更进一步测试,如果7个uint8_t成员里,有至少两个位宽低于4(包括4),并且它们可以不连续排列,那么也不会发生问题

由此观之,很大程度上与结构体在内存中的排列有关,这现象着实诡异,也可能与imx6u这块板有关,总之原因暂时不明

cpp 复制代码
typedef struct
{
    uint8_t HYS : 1;   // 迟滞
    uint8_t PULL : 1;  // 上拉/下拉
    uint8_t ODE : 1;   // 开漏
    uint8_t SPEED : 1; // 速度
    uint8_t DSE : 1;   // 驱动强度
    uint8_t SRE : 1;   // 转换速率
    uint8_t SION : 1;  // 软件输入

} MyStruct;

typedef struct
{
    uint8_t HYS : 2;   // 迟滞
    uint8_t PULL : 2;  // 上拉/下拉
    uint8_t ODE : 2;   // 开漏
    uint8_t SPEED : 2; // 速度
    uint8_t DSE : 2;   // 驱动强度
    uint8_t SRE : 2;   // 转换速率
    uint8_t SION : 2;  // 软件输入

} MyStruct1;

typedef struct
{
    uint8_t HYS : 6;   // 迟滞
    uint8_t PULL : 6;  // 上拉/下拉
    uint8_t ODE : 6;   // 开漏
    uint8_t SPEED : 6; // 速度
    uint8_t DSE : 6;   // 驱动强度
    uint8_t SRE : 6;   // 转换速率
    uint8_t SION : 6;  // 软件输入

} MyStruct2;

点灯调试:

cpp 复制代码
    /*初始化串口IO*/
    volatile MyStruct my1 = {0};
    _Debug_LED;//卑微点灯宏
    volatile MyStruct1 my2 = {0};
    _Debug_LED;
    volatile MyStruct2 my3 = {0};
    _Debug_LED;
    volatile IOMUXC_ConfigTypeDef uart_config = {0}; // 卡死在这里,与结构体有关
    _Debug_LED;
相关推荐
_upupup8 小时前
Linux的调试工具——gdb/cgdb
linux·服务器
JeJe同学9 小时前
Docker镜像导入、容器启动
linux·运维·docker
Jason_zhao_MR9 小时前
Linux与实时控制如何兼得
linux·嵌入式硬件·机器人·工业控制
闲云野鹤在人间10 小时前
MySQL|从理论、安装、备份到主从复制、MHA高可用详解
linux·运维·数据库·mysql·云计算
BSD_CGQ10 小时前
FSR传感器STM32 DMA高速采样工程实现(高精度、低CPU占用)
stm32·单片机·嵌入式硬件·压力传感器·源头工厂·柔性薄膜压力传感器·可变电阻压力传感器
Escalating_xu10 小时前
【C 语言】数据在内存中的存储:补码、大小端、整型陷阱与 IEEE 754 全解析
java·c语言·网络
一个风轻云淡11 小时前
GCC 和 GDB命令简单解读
java·linux·前端
H.莓飛11 小时前
【数据结构】二叉树_OJ题
linux·开发语言·数据结构·算法
资料库0111 小时前
Linux 8个常见运维故障排查
java·linux·运维
零基础12312 小时前
Ubuntu 常用命令汇总
linux·运维·开发语言