美文网首页
结构体必须字节对齐的一种情况

结构体必须字节对齐的一种情况

作者: xEndLess | 来源:发表于2023-12-27 12:59 被阅读0次

    MCU:STM32F407
    RTOS: FreeRTOS

    1. 情况说明

    定义了两个结构体全局变量power_down_infocoordinate_ee。这两个全局变量会被保存到AT24C64中。power_down_infocoordinate_ee的定义如下:

    typedef struct {
        uint16_t valid_flag;
        uint32_t storage[1][2];
        uint32_t get[1][2];
        uint32_t rfid1[1][2];
        uint32_t rfid2[1][2];
    } coordinate_ee_t;
    
    // typedef enum { NO_CARD, HAVE_CARD } feed_card_box_status_e;
    typedef struct {
        uint16_t card_amount[FEED_CARD_BOX_NUM]; /* 投卡仓卡片数量 */
        int8_t   sequence[FEED_CARD_BOX_NUM];    /* 喂卡顺序,负数的话不考虑顺序 */
        int8_t   current_card_box_num;           /* 当前走卡的投卡仓编号,根据该值,确认是否 */
    } feed_card_info_t;
    
    typedef struct {
        uint8_t rfid[STORAGE_CARD_BOX_NUM][RFID_BYTE_LEN]; /* RFID编号 */
        int16_t card_amount[STORAGE_CARD_BOX_NUM];         /* 卡片数量 */
        uint8_t cur_box_num;                               /* 当前卡箱号, 0 - 5 */
    } storage_card_info_t;
    
    /* 掉电保存数据结构体 */
    typedef struct power_down_info {
        uint16_t            init_flag;
        int8_t              current_feed_card_box_num; /* 0-3正常卡仓号,其他异常 */
        feed_card_info_t    feed_card_info;            /* 投卡口信息 */
        int8_t              slot_card_amount;          /* 衔接槽中卡片数量 */
        storage_card_info_t storage_card_info;         /* 存卡箱内卡片数量 */
    } power_down_info_t;
    
    extern power_down_info_t power_down_info;
    extern coordinate_ee_t   coordinate_ee;
    

    查看MAP文件中可以power_down_infocoordinate_ee的地址是连续的。

     .bss.coordinate_ee
                    0x200001bc       0x22 build/main.o
                    0x200001bc                coordinate_ee
     *fill*         0x200001de        0x2 
     .bss.power_down_info
                    0x200001e0       0x36 build/main.o
                    0x200001e0                power_down_info
     *fill*         0x20000216        0x2 
    

    2. 问题

    当从AT24C64中读出coordinate_ee时,在读取coordinate_ee的最后一个字节时,会导致power_down_info的第一个字节变化。power_down_info.init_flag的值从0x5A5A 变为0x5AFF。

    EEPROM_IIC_ReadBuffer(EEPROM_COORDINATE_ADDRESS, (uint8_t *)&coordinate_ee, sizeof(coordinate_ee));
    

    3. 分析

    产生上述问题的原因是sizeof(coordinate_ee)是按照4字节对齐计算长度的。从AT24C64中读出coordinate_ee时,如果coordinate_ee的实际长度不是4的倍数,会占用power_down_info的头部地址空间。导致power_down_info的成员变量的值变化。

    4. 结论

    在执行AT24C64的读写操作时,涉及的变量必须按字节对齐。gcc下按字节对齐的方法时增加#pragma pack(1)和#pragma pack()。如下所示:

    #pragma pack(1)
    typedef struct {
        uint16_t valid_flag;
        uint32_t storage[1][2];
        uint32_t get[1][2];
        uint32_t rfid1[1][2];
        uint32_t rfid2[1][2];
    } coordinate_ee_t;
    
    // typedef enum { NO_CARD, HAVE_CARD } feed_card_box_status_e;
    typedef struct {
        uint16_t card_amount[FEED_CARD_BOX_NUM]; /* 投卡仓卡片数量 */
        int8_t   sequence[FEED_CARD_BOX_NUM];    /* 喂卡顺序,负数的话不考虑顺序 */
        int8_t   current_card_box_num;           /* 当前走卡的投卡仓编号,根据该值,确认是否 */
    } feed_card_info_t;
    
    typedef struct {
        uint8_t rfid[STORAGE_CARD_BOX_NUM][RFID_BYTE_LEN]; /* RFID编号 */
        int16_t card_amount[STORAGE_CARD_BOX_NUM];         /* 卡片数量 */
        uint8_t cur_box_num;                               /* 当前卡箱号, 0 - 5 */
    } storage_card_info_t;
    
    /* 掉电保存数据结构体 */
    typedef struct power_down_info {
        uint16_t            init_flag;
        int8_t              current_feed_card_box_num; /* 0-3正常卡仓号,其他异常 */
        feed_card_info_t    feed_card_info;            /* 投卡口信息 */
        int8_t              slot_card_amount;          /* 衔接槽中卡片数量 */
        storage_card_info_t storage_card_info;         /* 存卡箱内卡片数量 */
    } power_down_info_t;
    #pragma pack()
    

    相关文章

      网友评论

          本文标题:结构体必须字节对齐的一种情况

          本文链接:https://www.haomeiwen.com/subject/mnmrndtx.html