H7双核调试
1、stm32H747有两个内核使用,都可以跑freertos操作系统,如果用这个芯片做电机控制,一个内核跑算法,一个内核跑通信逻辑,借助M7核的mpu配置D3区域的地址0x38000000地址开始配置成共享区域,mpu控制共享区域要注意4字节对齐,非对齐读写都有问题,受mpu保护的访问不对齐的直接进入硬件错误,
在 STM32H7 系列中,内存是分域(Domain)管理的。SRAM4 位于 D3 域(或称 SRD 域)。即使你配置了 MPU,如果没给这个内存区域供电/开时钟,CPU 访问该地址会立即触发 Bus Fault(进而导致 HardFault)
#define RCC_AHB4ENR_SRDSRAMEN_Pos (28U) #define RCC_AHB4ENR_SRDSRAMEN_Msk (0x1UL << RCC_AHB4ENR_SRDSRAMEN_Pos) /*!< 0x10000000 */ #define RCC_AHB4ENR_SRDSRAMEN RCC_AHB4ENR_SRDSRAMEN_Msk
开启这个时钟的代码这个需要手动补齐
STM32H747 的 D3 域(Smart Run Domain)是一个非常特殊的区域:
-
地址范围:
0x38000000-0x3800FFFF(64KB)。 -
特性:它是唯一一个在 CPU 核心处于深度睡眠时还能保持运行的内存域。
-
总线访问:M7 和 M4 访问它都要通过 AHB4 总线。由于它不在 D1/D2 域,所以时钟必须手动开启,否则任何对该地址的读写(包括
memset或MotorObject[i].motor_param_info->...)都会导致总线错误(Bus Fault) - 这个遇见访问错误就是遇见硬件错误,或者写uint8_t 能写进去,uint32_t写不进去硬件错误,如果遇见写0x38000000这个地址写不进去就要看看0x38000000这个地址有没有内容,这两个可以当做一个问题去看代
-
既然你能“看到”内容(说明时钟已经开启,地址总线通了),但“不能写”(一写就进 HardFault),这说明你碰到了 ARM MPU 最经典的“内存类型限制”陷阱。
在 STM32H7 中,当 MPU 配置为
IsCacheable = NO且IsBufferable = NO时,该内存会被识别为 强顺序内存(Strongly Ordered Memory) 或 设备内存(Device Memory)。1. 核心原因:非对齐访问限制
这是导致“能读不能写”最常见的凶手:
-
规则:ARM 架构规定,访问“设备内存”或“强顺序内存”时,指令必须是对齐的。
-
你的情况:你使用了
#pragma pack(1)。这意味着结构体里的SetFrequency(32位)可能落在了一个类似0x38000013这种不能被 4 整除的地址上。 -
结果:当你尝试往这个不对齐的地址写一个 32 位数据时,CPU 硬件会直接拦截并抛出 Alignment Fault(在 H7 中表现为 HardFault)。
- // 尝试写一个字节,字节访问永远是对齐的 *(volatile uint8_t *)0x38000000 = 0xAA;可以使用这个代码写一下看能不能写进去
-
方案 A:修改 MPU 属性
将 M7 和 M4 的 MPU 配置中,SRAM4 对应的 Region 属性修改为
Bufferable。这允许 CPU 进行非对齐操作。C/* 修改 MPU 配置 */ MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE; // 必须设置为 ENABLE -
方案 B:优化结构体布局
去掉
#pragma pack(1),改为手动对齐。这样既能保证 M7 和 M4 看到的偏移量一致,又能获得最高的访问性能,且不会触发 Fault。调整原则:按成员长度从大到小排列。
Ctypedef struct _share_motor_param { /* --- 4字节对齐区 --- */ volatile int32_t SetMax_Move_Step; volatile int32_t SetMax_Speed; volatile int32_t Target_Move_Step; volatile int32_t Cur_Move_Step; volatile uint32_t SetFrequency; // 现在它一定落在 4 字节边界上 volatile float SetSpeed; /* --- 2字节对齐区 --- */ volatile uint16_t subdivision; /* --- 1字节对齐区 --- */ volatile uint8_t SetMotorDir; volatile uint8_t MotorDirState; volatile uint8_t UseEncoder; /* 补齐到 4 字节边界,方便数组计算地址 */ uint8_t reserved[1]; } share_motor_param;
在调试是不能初始化外设时钟啥的最好在一个内核,调试的时候要选择调试模式,现在m7或者m4内核不能Reset
-
浙公网安备 33010602011771号