MCU:STM32F407
RTOS: FreeRTOS
1. 情况说明
定义了两个结构体全局变量power_down_info
和coordinate_ee
。这两个全局变量会被保存到AT24C64中。power_down_info
和coordinate_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_info
和coordinate_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()
网友评论