打印
[STM32F4]

这样定义union有什么问题昵

[复制链接]
1763|26
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
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怎么定义的?

使用特权

评论回复
5
luoengineer|  楼主 | 2020-10-11 15:28 | 只看该作者
john_lee 发表于 2020-10-11 15:01
m_OnePageBuf怎么定义的?

定义成这样
unOnePage  m_OnePageBuf;

使用特权

评论回复
6
axbin| | 2020-10-11 17:19 | 只看该作者
本帖最后由 axbin 于 2020-10-11 17:21 编辑

我猜是对齐的问题,m_OnePageBuf指向的位置要在32位*N(或64位*N)处,就像停车要停到车位里,不能这边占半个那边占半个

使用特权

评论回复
7
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);



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


使用特权

评论回复
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)中

不过从你分析来看,多半是数据对齐的问题

使用特权

评论回复
9
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 (205.03 KB )

无标题.png

使用特权

评论回复
10
小明的同学| | 2020-10-11 22:56 | 只看该作者
看到高级的用法,我就蒙圈。

使用特权

评论回复
11
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

使用特权

评论回复
12
john_lee| | 2020-10-12 12:06 | 只看该作者
调试,在hardfault入口打个断点,运行进入hardfault后,可以根据CPU寄存器的数据来判断故障点,如果你不会判断,也可以把CPU寄存器的内容贴出来大家看看。

使用特权

评论回复
13
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);
           }
}



使用特权

评论回复
评论
sjnh 2020-10-12 13:44 回复TA
出错应该是对齐上,uint64_t*必须是8字节对齐,但可能ReadAddr传过去的值不是8的倍数,例如xxxxxxx4 
sjnh 2020-10-12 13:42 回复TA
ReadAddr是值,不是指针,就应该是+8,如果是uint64_t*的话是++; 
14
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

使用特权

评论回复
15
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)


使用特权

评论回复
16
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;

使用特权

评论回复
17
luoengineer|  楼主 | 2020-10-12 18:34 | 只看该作者
john_lee 发表于 2020-10-12 12:06
调试,在hardfault入口打个断点,运行进入hardfault后,可以根据CPU寄存器的数据来判断故障点,如果你不会 ...

读到数据后掉到hardfault

使用特权

评论回复
18
john_lee| | 2020-10-13 09:50 | 只看该作者
R0应该是源地址,目标地址呢?是R3或R6?R3/R6没有对齐。

使用特权

评论回复
19
kingkits| | 2020-10-13 14:18 | 只看该作者
DATA_FLASH_Read(FLASH_ADDR_ONE_PAGE, (uint64_t *)m_OnePageBuf.pddwBuf,2048);

使用特权

评论回复
20
香水城| | 2020-10-13 15:06 | 只看该作者
一是对齐方面的问题 ;
另外 注意栈溢出方面的问题, 你可以尝试将数据大小缩下点验证下;

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

19

主题

80

帖子

1

粉丝