[STM32F4] 这样定义union有什么问题昵

[复制链接]
2320|26
 楼主| luoengineer 发表于 2020-10-11 12:23 | 显示全部楼层 |阅读模式
ni, IO, ui, ge, pd
如下定义,使用的时候读flash的数据会直接跳到hardware fault里面去,这样定义有什么问题呢?

typedef union __UN_ONE_PAGE_
{   
    uint64_t       pddwBuf[2048/8];
    uint32_t       pdwBuf[2048/4];
    uint16_t       pwBuf[2048/2];
    uint8_t        pbyBuf[2048];
}  unOnePage, *punOnePage;

john_lee 发表于 2020-10-11 13:47 | 显示全部楼层
定义看不出有问题,要看怎么读的。
 楼主| luoengineer 发表于 2020-10-11 14:29 | 显示全部楼层
john_lee 发表于 2020-10-11 13:47
定义看不出有问题,要看怎么读的。

这样读:
DATA_FLASH_Read(FLASH_ADDR_ONE_PAGE, (uint64_t *)m_OnePageBuf, (sizeof(m_OnePageBuf))/8);
下面函数是公共代码
static void DATA_FLASH_Read(uint32_t ReadAddr, uint64_t *pBuffer, uint16_t NumToRead)          
{
        uint32_t i1;
        for(i1 = 0; i1 < NumToRead; i1++)
        {
                pBuffer[i1] = *(uint64_t*)ReadAddr;
                ReadAddr+=8;
        }
}

如果定义成uint64_t m_OnePageBuf[FLASH_PAGE_SIZE/sizeof(uint64_t)]调用DATA_FLASH_Read是可以正常读的
john_lee 发表于 2020-10-11 15:01 | 显示全部楼层
m_OnePageBuf怎么定义的?
 楼主| luoengineer 发表于 2020-10-11 15:28 | 显示全部楼层
john_lee 发表于 2020-10-11 15:01
m_OnePageBuf怎么定义的?

定义成这样
unOnePage  m_OnePageBuf;
axbin 发表于 2020-10-11 17:19 | 显示全部楼层
本帖最后由 axbin 于 2020-10-11 17:21 编辑

我猜是对齐的问题,m_OnePageBuf指向的位置要在32位*N(或64位*N)处,就像停车要停到车位里,不能这边占半个那边占半个
hamstar 发表于 2020-10-11 18:51 | 显示全部楼层
本帖最后由 hamstar 于 2020-10-11 19:07 编辑

可能是数据对齐的问题,试一下这样定义

typedef __packed union __UN_ONE_PAGE_
{   
    uint64_t       pddwBuf[2048/8];
    uint32_t       pdwBuf[2048/4];
    uint16_t       pwBuf[2048/2];
    uint8_t        pbyBuf[2048];
}  unOnePage, *punOnePage;


但是应该是你调用联合体时出错了

unOnePage  m_OnePageBuf;
DATA_FLASH_Read(FLASH_ADDR_ONE_PAGE, (uint64_t *)m_OnePageBuf, (sizeof(m_OnePageBuf))/8);


应该这样调用吧,传递的应该是联合体的指针,而不是联合体的名称(编译器难道没有报警?)
DATA_FLASH_Read(FLASH_ADDR_ONE_PAGE, (uint64_t *)&m_OnePageBuf, (sizeof(m_OnePageBuf))/8);



至于你用数组是正常的,是因为数组名本身就是数组的指针


 楼主| luoengineer 发表于 2020-10-11 20:56 | 显示全部楼层
hamstar 发表于 2020-10-11 18:51
可能是数据对齐的问题,试一下这样定义

typedef __packed union __UN_ONE_PAGE_

typedef __packed  union __UN_ONE_PAGE_
{   
    uint64_t       pddwBuf[2048/8];
    uint32_t       pdwBuf[2048/4];
    uint16_t       pwBuf[2048/2];
    uint8_t        pbyBuf[2048];
}  unOnePage, *punOnePage

unOnePage  m_OnePageBuf;

DATA_FLASH_Read(FLASH_ADDR_A0H_LOWER, (uint64_t *)&m_OnePageBuf.pddwBuf[0], (sizeof(m_OnePageBuf))/8);


还是会掉到void HardFault_Handler(void)中

不过从你分析来看,多半是数据对齐的问题
hamstar 发表于 2020-10-11 22:33 | 显示全部楼层
本帖最后由 hamstar 于 2020-10-11 22:34 编辑
luoengineer 发表于 2020-10-11 20:56
typedef __packed  union __UN_ONE_PAGE_
{   
    uint64_t       pddwBuf[2048/8];

是你调用联合体方法不对造成的
应该这样调用 DATA_FLASH_Read(FLASH_ADDR_A0H_LOWER, (uint64_t *)&m_OnePageBuf, (sizeof(m_OnePageBuf))/8);
无标题.png
小明的同学 发表于 2020-10-11 22:56 | 显示全部楼层
看到高级的用法,我就蒙圈。
 楼主| luoengineer 发表于 2020-10-12 09:34 | 显示全部楼层
hamstar 发表于 2020-10-11 22:33
是你调用联合体方法不对造成的
应该这样调用 DATA_FLASH_Read(FLASH_ADDR_A0H_LOWER, (uint64_t *)&m_OneP ...

应该是一样的,试了一下这2种不同的写法,编译不会报错,运行都会掉到hardfault
john_lee 发表于 2020-10-12 12:06 | 显示全部楼层
调试,在hardfault入口打个断点,运行进入hardfault后,可以根据CPU寄存器的数据来判断故障点,如果你不会判断,也可以把CPU寄存器的内容贴出来大家看看。
dami 发表于 2020-10-12 12:24 | 显示全部楼层
本帖最后由 dami 于 2020-10-13 09:23 编辑

static void DATA_FLASH_Read(uint32_t ReadAddr, uint64_t *pBuffer, uint16_t NumToRead)         
既然是uint64_t *pBuffer, pBuffer+1就过去8个字节了吧。
for(uint32_t i1 = 0; i1 < NumToRead; i1++)
{
            for(uint8_t i=0;i<8;i++)
           {
                   pBuffer[i1] <<=8;
                   pBuffer[i1] +=*(ReadAddr+i);
           }
}



评论

出错应该是对齐上,uint64_t*必须是8字节对齐,但可能ReadAddr传过去的值不是8的倍数,例如xxxxxxx4  发表于 2020-10-12 13:44
ReadAddr是值,不是指针,就应该是+8,如果是uint64_t*的话是++;  发表于 2020-10-12 13:42
sjnh 发表于 2020-10-12 13:40 | 显示全部楼层
本帖最后由 sjnh 于 2020-10-12 14:02 编辑

static void DATA_FLASH_Read(uint32_t ReadAddr, uint64_t *pBuffer, uint16_t NumToRead)         
{
        uint32_t i1;
        for(i1 = 0; i1 < NumToRead; i1++)
        {
                pBuffer[i1] = *(uint64_t*)ReadAddr;
                ReadAddr+=8;
        }
}
这个强制转换,如果ReadAddr值是xxxxxxx4/c的情况下(只要ReadAddr传过来的值不是8的倍数),执行就会出现halt
dami 发表于 2020-10-12 16:08 | 显示全部楼层
本帖最后由 dami 于 2020-10-13 16:04 编辑
sjnh 发表于 2020-10-12 13:40
static void DATA_FLASH_Read(uint32_t ReadAddr, uint64_t *pBuffer, uint16_t NumToRead)         
{
   ...

哦  看错了。把 pBuffer和ReadAddr混了。
static void DATA_FLASH_ReadByte(uint32_t ReadAddr, uint8_t *pBuffer, uint16_t NumToRead)      
{
    for(i1 = 0; i1 < NumToRead; i1++) {       pBuffer[i1] =*(ReadAddr+i1);    }
}
static void DATA_FLASH_ReadUint64(uint32_t ReadAddr, uint64_t *pBuffer, uint16_t NumToRead)      

        DATA_FLASH_ReadByte(ReadAddr,(uint8_t*) pBuffer, NumToRead*8)


xiaofei558008 发表于 2020-10-12 17:41 | 显示全部楼层
typedef union
{   
    uint64_t       pddwBuf[2048/8];
    uint32_t       pdwBuf[2048/4];
    uint16_t       pwBuf[2048/2];
    uint8_t        pbyBuf[2048];
}  __UN_ONE_PAGE_;

__UN_ONE_PAGE_ unOnePage, *punOnePage;
 楼主| luoengineer 发表于 2020-10-12 18:34 | 显示全部楼层
john_lee 发表于 2020-10-12 12:06
调试,在hardfault入口打个断点,运行进入hardfault后,可以根据CPU寄存器的数据来判断故障点,如果你不会 ...

微信图片_20201012183219.png 读到数据后掉到hardfault
john_lee 发表于 2020-10-13 09:50 | 显示全部楼层
R0应该是源地址,目标地址呢?是R3或R6?R3/R6没有对齐。
kingkits 发表于 2020-10-13 14:18 | 显示全部楼层
DATA_FLASH_Read(FLASH_ADDR_ONE_PAGE, (uint64_t *)m_OnePageBuf.pddwBuf,2048);
香水城 发表于 2020-10-13 15:06 | 显示全部楼层
一是对齐方面的问题 ;
另外 注意栈溢出方面的问题, 你可以尝试将数据大小缩下点验证下;
您需要登录后才可以回帖 登录 | 注册

本版积分规则

19

主题

80

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部