硬汉嵌入式论坛

 找回密码
 立即注册
12
返回列表 发新帖
楼主: eric2013
收起左侧

[STM32H7] 【烧脑技术贴】无法回避的字节对齐问题,从八个方向深入探讨(变量对齐,栈对齐,DMA对齐,结构体成对齐,Cache, RTOS双堆栈等)

  [复制链接]

6

主题

26

回帖

44

积分

新手上路

积分
44
发表于 2024-1-16 07:58:00 | 显示全部楼层
留下脚印,以备后用
回复

使用道具 举报

81

主题

1362

回帖

1605

积分

至尊会员

积分
1605
发表于 2024-1-16 08:59:57 | 显示全部楼层
eric2013 发表于 2024-1-16 00:03
这个是M4权威指南上的。

Cortex-M4,M3,M0权威指南(中英文版)

好的谢谢
回复

使用道具 举报

1

主题

3

回帖

6

积分

新手上路

积分
6
发表于 2024-5-28 14:29:48 | 显示全部楼层
本帖最后由 zw_zheng 于 2024-5-28 15:43 编辑

我目前遇到了freertos情况下,使用snprintfFloat进入hardfault的情况 想请问 是freertos没有设置8字节对齐的原因吗 还是什么其它原因。
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117512
QQ
 楼主| 发表于 2024-5-29 08:57:44 | 显示全部楼层
zw_zheng 发表于 2024-5-28 14:29
我目前遇到了freertos情况下,使用snprintfFloat进入hardfault的情况 想请问 是freertos没有设置8字节对齐 ...

先看下硬件溢出的错误类型,是不是对齐问题
回复

使用道具 举报

0

主题

1

回帖

1

积分

新手上路

积分
1
发表于 2024-6-12 17:05:47 | 显示全部楼层
mark学习学习
回复

使用道具 举报

0

主题

1

回帖

1

积分

新手上路

积分
1
发表于 2024-7-16 13:37:05 | 显示全部楼层
牛逼,做个标记多学习学习
回复

使用道具 举报

0

主题

2

回帖

2

积分

新手上路

积分
2
发表于 2024-8-2 18:31:23 | 显示全部楼层

硬汉哥,问个问题,我这边使用MPU配置成这个模式-----大概率是与你上述的第10点相关

{
   SCB_DisableICache();
    SCB_DisableDCache();
    //内存空间保护
    MPU_InitStruct.enable = 1;//使能MPU保护,启用region,
    MPU_InitStruct.baseAddress = 0x30100000U;//基地址能被32整除
    MPU_InitStruct.size = ARM_MPU_REGION_SIZE_128KB;//
    MPU_InitStruct.accessPermission = ARM_MPU_AP_FULL;//允许全访问
    MPU_InitStruct.typeExtField = 2;//普通内存类型  TEX
    MPU_InitStruct.isCacheable = 0;//bu允许缓存     C
    MPU_InitStruct.isBufferable = 0;//bu允许缓冲    B
    MPU_InitStruct.isShareable = 1;//不允许共享     S
    MPU_InitStruct.number = 1;//区域编号0~15
    MPU_InitStruct.subRegionDisable = 0;//允许所有子域,禁用子域mpu
    MPU_InitStruct.disableExec = 0;//允许取指

    MPU_ConfigRegion(&MPU_InitStruct);


ARM_MPU_Enable(MPU_CTRL_PRIVDEFENA_Msk);
    // 确保配置生效
         __DSB();
         __ISB();
}



#pragma pack(1)
typedef struct
{
    uint8_t flag;       // 0x68
    uint8_t Result;     // 数据订阅结果
    uint8_t Mode;       // 订阅模式,1:计数模式,2:频率模式,单位hz
    uint16_t frequency; // 频率
    uint16_t count;     // 次数,在计数模式下才有效
    uint16_t cmd;
} SDK_Message_REP;
#pragma pack()
大概是使用下面空间分配的模式。

__align(32) uint8_t mem1base[96*1024] __attribute__((at(0x30100000)));
SDK_Message_REP rep = {1,2,3,4,5,6};
SDK_Message_REP *req = (SDK_Message_REP *)mem1base;

//然后使用这样赋值,直接报字节未对齐【usage fault:SCB_CFSR_UFSR:0x100 UNALIGNED】
req->frequency = rep.frequency ;
//之后,我使用这样的形式,就正常,或者不设置0x30100000的MPU就正常,但是不配置0x30100000地址的MPU,使用这一部分空间的话,会出现赋值异常的现象,例如调用arm_scale_f32函数,赋值出来竟然有0值,配置MPU后就正常了。
uint8_t mem1base[1024] = { 0 };

SDK_Message_REP rep = {1,2,3,4,5,6};
SDK_Message_REP *req = (SDK_Message_REP *)mem1base;
//我看下图的说法,进行MPU的配置,0x30100000该起始地址的128k,配置成强排序,不缓存、不加速、不缓冲。是我这里配置有问题麽?








回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117512
QQ
 楼主| 发表于 2024-8-3 08:02:54 | 显示全部楼层
ShineY 发表于 2024-8-2 18:31
硬汉哥,问个问题,我这边使用MPU配置成这个模式-----大概率是与你上述的第10点相关

{

H7的对齐要注意这个问题,实际上楼主位的这个帖子里面也整理了。

石锤内存访问不支持非对齐是否STM32H7的硬件bug
https://forum.anfulai.cn/forum.p ... 4562&fromuid=58
(出处: 硬汉嵌入式论坛)
回复

使用道具 举报

1

主题

21

回帖

24

积分

新手上路

积分
24
发表于 2024-8-3 15:08:04 | 显示全部楼层
对于老大所说的七、硬件浮点对齐我有异议,实测double不需要8字节对齐!之所以有该异议是我在看threadx中tx_byte_allocate代码的时候发现默认按4字节对齐申请的,那如果申请完一个4字节对齐但是8字节不对的内存区域我直接在开头放double值不就崩溃了,threadx应该不会范这种低级错误。
我在STM32G0B1和STM32H723都测试了该代码,可以正确运行,并且打印正确的运算值
#if defined ( __ICCARM__ )
#pragma data_alignment=4
#endif
__ALIGN_BEGIN uint8_t testBuf[128] __ALIGN_END;//保证testBuf是四字节对齐,是不是8字节对齐没关系,后面的测试代码会保证有的double变量肯定是非4字节对齐的
double inputD[4] = {1.239, 123.45, 45.67, 67.78};
double testD[8] = {0};

//该函数放到一个线程中循环调用
void Test(void) {
    //下面的代码可以保证有2个double放到了非8字节对齐的地址处!

    memcpy(testBuf,      &inputD[0], sizeof(double));
    memcpy(&testBuf[12], &inputD[1], sizeof(double));
    memcpy(&testBuf[24], &inputD[2], sizeof(double));
    memcpy(&testBuf[36], &inputD[3], sizeof(double));
   
    //直接强转运算,如果按老大说的double必须8字节对齐,那么这里应该会导致hardfault,而实际并没有!STM32G0B1和STM32H723都没有问题
    testD[0] = (*((double*)&testBuf[0] )) * (*((double*)&testBuf[12]));
    testD[1] = (*((double*)&testBuf[24])) * (*((double*)&testBuf[36]));
    LiteTrace("testD = %d.%04d, %d.%04d\n\n", (int)testD[0], (int)(testD[0]*10000.0)%10000, (int)testD[1], (int)(testD[1]*10000.0)%10000);
}


最后,做技术唯怕认真二字
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117512
QQ
 楼主| 发表于 2024-8-4 00:34:32 | 显示全部楼层
dzc0426 发表于 2024-8-3 15:08
对于老大所说的七、硬件浮点对齐我有异议,实测double不需要8字节对齐!之所以有该异议是我在看threadx中tx ...

这个问题探讨过。

关于非对齐内存访问异常的问题
https://forum.anfulai.cn/forum.p ... 5867&fromuid=58
(出处: 硬汉嵌入式论坛)
回复

使用道具 举报

1

主题

21

回帖

24

积分

新手上路

积分
24
发表于 2024-8-5 16:20:41 | 显示全部楼层
本帖最后由 dzc0426 于 2024-8-5 16:47 编辑
eric2013 发表于 2024-8-4 00:34
这个问题探讨过。

关于非对齐内存访问异常的问题

看完了,受益匪浅,但是我发现double只要4字节对齐访问就不会hardfault,不需要8字节。
采用STM32H723ZGT6测试


#warning "test"
#if defined ( __ICCARM__ )
#pragma data_alignment=4
#endif
__attribute__((section(".DMA1_DMA2"))) __ALIGN_BEGIN uint8_t testBuf[128] __ALIGN_END;
double inputD[4] = {2.239, 123.45, 45.67, 67.78};
double testD[8] = {0};

void Test(void)
{


#if 1
        //double *pDouble[4] = {(double*)&testBuf[0], (double*)&testBuf[11], (double*)&testBuf[24], (double*)&testBuf[36]};//使用该行代码,会死机,
        double *pDouble[4] = {(double*)&testBuf[0], (double*)&testBuf[12], (double*)&testBuf[24], (double*)&testBuf[36]};//使用该行代码不会死机,所以可以证明double可以四字节对齐访问?
        for(int i = 0; i < 4; ++i) {
            *(pDouble) = inputD;
        }
        testD[0] = (*(pDouble[0])) * (*(pDouble[1]));
        testD[1] = (*(pDouble[2])) * (*(pDouble[3]));
        LiteTrace("testD = %d.%04d, %d.%04d, ULONG size:%d\n\n", (int)testD[0], (int)(testD[0]*10000.0)%10000, (int)testD[1], (int)(testD[1]*10000.0)%10000,(int)sizeof(unsigned long));
#else
        memcpy(testBuf,      &inputD[0], sizeof(double));
        memcpy(&testBuf[11], &inputD[1], sizeof(double));//赋值采用了memcpy方式
        memcpy(&testBuf[24], &inputD[2], sizeof(double));
        memcpy(&testBuf[36], &inputD[3], sizeof(double));

        testD[0] = (*((double*)&testBuf[0] )) * (*((double*)&testBuf[11]));//这里不会死机!虽然&testBuf[11]不是四字节对齐,
        testD[1] = (*((double*)&testBuf[24])) * (*((double*)&testBuf[36]));
        LiteTrace("testD = %d.%04d, %d.%04d, ULONG size:%d\n\n", (int)testD[0], (int)(testD[0]*10000.0)%10000, (int)testD[1], (int)(testD[1]*10000.0)%10000,(int)sizeof(unsigned long));
#endif


}
回复

使用道具 举报

0

主题

2

回帖

2

积分

新手上路

积分
2
发表于 2024-8-22 08:32:20 | 显示全部楼层
eric2013 发表于 2024-8-3 08:02
H7的对齐要注意这个问题,实际上楼主位的这个帖子里面也整理了。

石锤内存访问不支持非对齐是否STM32H ...

感谢,
回复

使用道具 举报

22

主题

196

回帖

262

积分

高级会员

积分
262
发表于 2024-12-31 10:24:35 | 显示全部楼层
MPU设置为device,我看除了固定地址直接赋值之类的,其余的编译器应该都帮忙处理好了吧
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117512
QQ
 楼主| 发表于 2025-1-2 06:13:46 | 显示全部楼层
yuanzhongda 发表于 2024-12-31 10:24
MPU设置为device,我看除了固定地址直接赋值之类的,其余的编译器应该都帮忙处理好了吧

使用Strongly或者Device模式,特别注意字节对齐问题。
回复

使用道具 举报

22

主题

196

回帖

262

积分

高级会员

积分
262
发表于 2025-1-17 22:43:48 | 显示全部楼层
DMA的数据地址必须要跟其数据类型对齐 在哪个手册里有写
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117512
QQ
 楼主| 发表于 2025-1-18 08:47:59 | 显示全部楼层
yuanzhongda 发表于 2025-1-17 22:43
DMA的数据地址必须要跟其数据类型对齐 在哪个手册里有写

参考手册
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2025-8-12 06:52 , Processed in 0.121313 second(s), 23 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表