RT-Thread论坛
直播中

vinww特烦恼

9年用户 1220经验值
擅长:存储技术
私信 关注
[问答]

gd32h737 开启cache程序跑飞是哪里的问题?

gd32h737 在rtthread 4.1.1版本上运行,开启cache功能,程序跑飞,JLink连接失败的。错误信息没有。配置方式的说明吗?

  • /*!
  •     brief      enable the CPU cache
  •     param[in]  none
  •     param[out] none
  •     retval     none
  • */
  • void cache_enable(void)
  • {
  •     /* Enable I-Cache */
  •     SCB_EnableICache();

  •     /* Enable D-Cache */
  •     SCB_EnableDCache();

  •     //SCB->CACR |= 1 << 2;    /* 强制D-Cache透写,如不开启透写,实际使用中可能遇到各种问题 */
  • }

  • /*!
  •     brief      configure the MPU
  •     param[in]  none
  •     param[out] none
  •     retval     none
  • */
  • void mpu_config(void)
  • {
  •     mpu_region_init_struct mpu_init_struct;
  •     mpu_region_struct_para_init(&mpu_init_struct);

  •     /* disable the MPU */
  •     ARM_MPU_Disable();
  •     //ARM_MPU_SetRegion(0U, 0U);
  •     /* ITCM  64K*/
  •     mpu_init_struct.region_base_address = 0x00000000;
  •     mpu_init_struct.region_size = MPU_REGION_SIZE_64KB;
  •     mpu_init_struct.access_permission = MPU_AP_FULL_ACCESS;
  •     mpu_init_struct.access_bufferable = MPU_ACCESS_BUFFERABLE;
  •     mpu_init_struct.access_cacheable = MPU_ACCESS_CACHEABLE;
  •     mpu_init_struct.access_shareable = MPU_ACCESS_NON_SHAREABLE;
  •     mpu_init_struct.region_number = MPU_REGION_NUMBER0;
  •     mpu_init_struct.subregion_disable = MPU_SUBREGION_ENABLE;
  •     mpu_init_struct.instruction_exec = MPU_INSTRUCTION_EXEC_PERMIT;
  •     mpu_init_struct.tex_type = MPU_TEX_TYPE0;
  •     mpu_region_config(&mpu_init_struct);
  •     mpu_region_enable();

  •     /*  DTCM 128K*/
  •     mpu_init_struct.region_base_address = 0x20000000;
  •     mpu_init_struct.region_size = MPU_REGION_SIZE_128KB;
  •     mpu_init_struct.access_permission = MPU_AP_FULL_ACCESS;
  •     mpu_init_struct.access_bufferable = MPU_ACCESS_BUFFERABLE;
  •     mpu_init_struct.access_cacheable = MPU_ACCESS_CACHEABLE;
  •     mpu_init_struct.access_shareable = MPU_ACCESS_NON_SHAREABLE;
  •     mpu_init_struct.region_number = MPU_REGION_NUMBER1;
  •     mpu_init_struct.subregion_disable = MPU_SUBREGION_ENABLE;
  •     mpu_init_struct.instruction_exec = MPU_INSTRUCTION_EXEC_PERMIT;
  •     mpu_init_struct.tex_type = MPU_TEX_TYPE0;
  •     mpu_region_config(&mpu_init_struct);
  •     mpu_region_enable();

  •     /*  axi 512k*/
  •     mpu_init_struct.region_base_address = 0x24000000;
  •     mpu_init_struct.region_size = MPU_REGION_SIZE_512KB;
  •     mpu_init_struct.access_permission = MPU_AP_FULL_ACCESS;
  •     mpu_init_struct.access_bufferable = MPU_ACCESS_NON_BUFFERABLE;
  •     mpu_init_struct.access_cacheable = MPU_ACCESS_NON_CACHEABLE;
  •     mpu_init_struct.access_shareable = MPU_ACCESS_SHAREABLE;
  •     mpu_init_struct.region_number = MPU_REGION_NUMBER2;
  •     mpu_init_struct.subregion_disable = MPU_SUBREGION_ENABLE;
  •     mpu_init_struct.instruction_exec = MPU_INSTRUCTION_EXEC_PERMIT;
  •     mpu_init_struct.tex_type = MPU_TEX_TYPE0;
  •     mpu_region_config(&mpu_init_struct);
  •     mpu_region_enable();


  •     /* enable the MPU */
  •     ARM_MPU_Enable(MPU_MODE_PRIV_DEFAULT);
  • }




回帖(2)

龙献益

2025-9-11 16:53:26
   MPU是不是没有配置。
举报

岳臻俊

2025-9-15 17:50:23

针对GD32H737开启Cache后程序跑飞的问题,结合RT-Thread 4.1.1的特性,以下是关键排查点与解决方案:


问题原因分析



  1. Cache配置与内存属性不匹配

    • Cortex-M7需通过MPU设置内存区域的Cache策略(WT/WB/NonCacheable),未正确配置时可能导致数据不一致。


  2. 初始化顺序错误

    • 过早开启Cache(如系统初始化前)。


  3. DMA/外设数据一致性问题

    • DMA操作区域未配置为Non-Cacheable,导致Cache数据未同步。


  4. 链接脚本未适配Cache

    • 需要.nocache段声明非缓存区域(如DMA缓冲区)。





解决方案


1. 配置MPU设置Cache策略


在RT-Thread中启用MPU(rt_hw_mpu_init),按需配置内存区域:


#include 
#include

/* 定义内存区域属性 */
#define NORMAL_NOCACHE          0x800  // Outer and Inner Non-cacheable
#define DEVICE_MEMORY           0x1000 // Device Memory
#define STRONGLY_ORDERED        0x0    // Strongly Ordered

void rt_hw_mpu_configure(void)
{
    struct mpu_region region_cfg;

    /* Region 0: Flash (512KB, WT策略) */
    region_cfg.addr = 0x08000000;
    region_cfg.attr = RT_HW_MPU_REGION_WT; // Write-Through
    rt_hw_mpu_set(0, ®ion_cfg, 512 * 1024);

    /* Region 1: SRAM1 (256KB, WB_WA策略) */
    region_cfg.addr = 0x20000000;
    region_cfg.attr = RT_HW_MPU_REGION_WB_WA; // Write-Back, Write-Allocate
    rt_hw_mpu_set(1, ®ion_cfg, 256 * 1024);

    /* Region 2: DMA缓冲区 (Non-Cacheable) */
    region_cfg.addr = 0x20040000;
    region_cfg.attr = NORMAL_NOCACHE;
    rt_hw_mpu_set(2, ®ion_cfg, 32 * 1024);

    /* 启用MPU */
    rt_hw_mpu_enable();
}

2. 调整初始化顺序


rt_hw_board_init()中正确排序:


int rt_hw_board_init(void)
{
    /* 先配置MPU */
    rt_hw_mpu_configure();

    /* 其他初始化(时钟、外设) */
    ...

    /* 最后开启Cache */
    SCB_EnableICache();
    SCB_EnableDCache();
}

3. 非缓存内存声明(链接脚本)


修改链接脚本link.lds


SECTIONS
{
    ...
    .nocache (NOLOAD) : {
        . = ALIGN(4);
        *(.nocache)
        . = ALIGN(4);
    } > RAM
}

在代码中声明非缓存区:


RT_SECTION(".nocache") uint8_t dma_buffer[BUFFER_SIZE];

4. Cache维护操作


DMA操作前后添加缓存维护:


/* DMA发送前:清空数据到内存 */
SCB_CleanDCache_by_Addr(dma_buffer, sizeof(dma_buffer));
start_dma_transfer();

/* DMA接收后:无效化缓存区 */
SCB_InvalidateDCache_by_Addr(dma_buffer, sizeof(dma_buffer));

5. 排查固件库兼容性



  • 确保使用最新GD32H7xx固件库。

  • 检查system_gd32h7xx.c中SystemInit()是否正确初始化MMU/Cache相关寄存器。




调试建议




  1. 分步启用Cache  



    • 先仅开启I-Cache测试。

    • 再开启D-Cache,定位问题模块。




  2. 串口日志辅助调试

    在关键步骤添加日志输出,定位崩溃点:


    rt_kprintf("Enabling I-Cache...n");
    SCB_EnableICache();
    rt_kprintf("I-Cache enabledn");



  3. J-Link连接失败处理  



    • 尝试硬件复位后再连接。

    • 检查BOOT引脚配置(是否从Flash启动)。

    • 若无法连接,暂时关闭Cache并重新烧录。




  4. 检查RT-Thread移植文件

    确保context_gcc.S中的Cache维护操作正确(如rt_hw_cpu_dcache_clean_invalidate())。






注意事项



  • 外设寄存器区域:必须配置为Non-Cacheable(使用DEVICE_MEMORY属性)。

  • RT-Thread IPC对象:若使用共享内存,需声明为非缓存或手动维护缓存一致性。

  • 定时器与中断:开启Cache后指令预取加速,可能导致时序变化,需重新校准延时。


通过以上步骤系统性排查,问题通常能定位到MPU配置或内存一致性维护上。建议优先验证MPU设置并隔离问题模块。

举报

更多回帖

发帖
×
20
完善资料,
赚取积分