关于调试STM32F030系列单片机遇到的硬件错误中断问题

一.问题环境

最近在调试STM32F030K6单片机,用的STM32F0xx_StdPeriph_Lib_V1.5.0标准外设固件库。搭建了BSP+SYSTEM+HARDWARE+APP框架,同样的框架在STM32F103单片机及其BSP下,APP正常流畅运行,可更换为配置好的STM32F030K6的BSP及单片机板后,总是出现各种各样的问题。具体问题如下:

二.问题现象

  • 1.程序没有进入while循环就卡死,跑飞,进入硬件错误中断(HardFault_Handler)。

  • 开启仿真调试,发现程序卡在含有结构体变量的初始化部分。结构体通过传递指针地址作为参数,并传递给HARDWARE层

  • 在进入HARDWARE的函数后,将结构体指针的BSP配置部分继续传递给BSP的时候,还没有进入BSP层的函数的调用前,程序就跑飞了。进入了硬件错误中断。

  • 单片机采用8MHz的外部晶振,并通过采用6倍频的方式,使时钟频率达到48MHz,并且配置FLASH_SetLatency(FLASH_Latency_1)仍没有效果。

  • 2.将APP的结构体包含的成员结构体变量调下位置,可以运行到下一个语句,但仍然卡死。

  • APP的HARDWARE结构体成员定义方式由变量改为指针,并为每个HARDWARE结构体单独创建实例,把其地址传给APP的HARDWARE结构体成员指针。
  • 能够进入while循环。
  • 当运行while循环到达一定周期后,再次跑飞卡死,进入HardFault_Handler
  • 发现问题仍然是访问了结构体某个成员造成错误
  • 三.原因分析

  • 通过以上的结构体问题,我发现问题多半是由于结构体的大小不确定造成的。而结构体的大小通常由其对齐方式决定。

  • 编译器通常对结构体按默认的4字节对齐,并填充相应的字节。

  • 结构体的对齐是指在内存中为结构体的成员分配存储位置时,按照特定规则调整其地址,以确保每个成员都在满足其对齐要求的地址上。这种对齐要求通常基于数据类型的大小。例如:

  • char 类型的对齐为 1 字节
  • short 类型的对齐为 2 字节
  • intfloat 类型的对齐为 4 字节
  • double 类型的对齐为 8 字节
  • 为什么使用F0系列的单片机,需要对结构体进行单字节对齐

  • F0系列的单片机可能会对内存访问有更严格的对齐要求,尤其是在访问某些外设寄存器或特定内存区域时。如果结构体中的数据成员没有按照其对齐要求存放,可能会导致以下问题:

  • 硬件异常:某些寄存器在读取时,如果地址未对齐,可能导致硬件异常,甚至系统崩溃。
  • 性能影响:未对齐访问可能导致CPU执行多次内存读取操作,降低性能。
  • 因此,在F0系列中,为了确保数据访问的正确性和高效性,通常需要对结构体进行单字节对齐。

  • 为什么使用F1系列的单片机,同样的程序没有跑飞呢?
  • F1系列的单片机对内存访问的要求可能较为宽松,允许未对齐访问,因此在相同的程序中,虽然结构体未严格遵循对齐规则,仍能正常运行。原因可能包括:

  • 容忍度更高:F1系列的处理器可能对未对齐访问有更好的容错能力,能在一定程度上自动处理未对齐的数据访问。
  • 软件优化:可能在编译器或程序设计上进行了优化,能够避免因未对齐访问导致的问题。
  • 四.问题解决

  • 对所有结构体进行单字节对齐。

    结构体代码统一加入:

    #pragma pack(1)							//1字节对齐
    #pragma anon_unions						//开启匿名结构、联合
    
    union Frame 
    {
        uint32_t buf[FRAME_BUF_SIZE];
        struct 
        {
            uint8_t head;
            uint8_t length;
            uint8_t cmd;
            uint8_t data[FRAME_BUF_SIZE - 4];
            uint8_t check;
        };
    };
    
    #pragma no_anon_unions					//关闭匿名结构、联合
    #pragma pack()							//取消字节对齐
    
  • 加入对齐后,程序稳定运行。

  • 作者:fancyang

    物联沃分享整理
    物联沃-IOTWORD物联网 » 关于调试STM32F030系列单片机遇到的硬件错误中断问题

    发表回复