硬汉嵌入式论坛

 找回密码
 立即注册
查看: 1560|回复: 2
收起左侧

[UART] STM32H7串口DMA使用打开Cache出现异常

[复制链接]

2

主题

3

回帖

9

积分

新手上路

积分
9
发表于 2024-12-10 23:53:20 | 显示全部楼层 |阅读模式
目前想使用STM32H743的开发板进行串口的空闲中断+DMA的测试的,但是发现一个问题呢  就是我这边只要打开了Cache就会出现异常了 比如第一次上位机下发STM32H743APPlication打印就是STM32H743APPlication 没有问题呢!但是换一个发送的字符串打印的还是之前的字符串STM32H743APPlication的 但是不打开Cache跟MPU保护就没有问题 这个大家知道是什么问题吗????主要的代码如下:

void HAL_UART_IdleCpltCallback(UART_HandleTypeDef *huart)
{

if (huart == &huart1)
  {                       
    // 清除IDLE标志
    __HAL_UART_CLEAR_IDLEFLAG(huart);
    // 中止当前接收
    if (HAL_UART_AbortReceive(huart) != HAL_OK)
    {
      // 错误处理
      Error_Handler();
    }
    // 停止DMA接收
    if (HAL_UART_DMAStop(huart) != HAL_OK)
    {
      // 错误处理
      Error_Handler();
    }
    // 计算接收到的数据长度
    rx_data.len = UART_BUF_SIZE - __HAL_DMA_GET_COUNTER(huart->hdmarx);
    // 设置标志位
    rx_data.flag = 1;
    // 重新启动DMA接收
    if (HAL_UART_Receive_DMA(huart, UART_RECV_RXBUF, UART_BUF_SIZE) != HAL_OK)
    {
      // 错误处理
      Error_Handler();
    }
  }
}

/**
* @brief       设置某个区域的MPU保护
* @param       baseaddr:MPU保护区域的基址(首地址)
* @param       size:MPU保护区域的大小(必须是32的倍数,单位为字节),可设置的值参考:CORTEX_MPU_Region_Size
* @param       rnum:MPU保护区编号,范围:0~7,最大支持8个保护区域,可设置的值参考:CORTEX_MPU_Region_Number
* @param       de:禁止指令访问;0,允许指令访问;1,禁止指令访问
* @param       ap:访问权限,访问关系如下:可设置的值参考:CORTEX_MPU_Region_Permission_Attributes
*   @arg       MPU_REGION_NO_ACCESS,无访问(特权&用户都不可访问)
*   @arg       MPU_REGION_PRIV_RW,仅支持特权读写访问
*   @arg       MPU_REGION_PRIV_RW_URO,禁止用户写访问(特权可读写访问)
*   @arg       MPU_REGION_FULL_ACCESS,全访问(特权&用户都可访问)
*   @arg       MPU_REGION_PRIV_RO,仅支持特权读访问
*   @arg       MPU_REGION_PRIV_RO_URO,只读(特权&用户都不可以写)
*   @arg       详见:STM32F7编程手册.pdf,4.6节,Table 89.
* @param       sen  : 是否允许共用;MPU_ACCESS_NOT_SHAREABLE,不允许;MPU_ACCESS_SHAREABLE,允许
* @param       cen  : 是否允许cache;MPU_ACCESS_NOT_CACHEABLE,不允许;MPU_ACCESS_CACHEABLE,允许
* @param       ben  : 是否允许缓冲;MPU_ACCESS_NOT_BUFFERABLE,不允许;MPU_ACCESS_BUFFERABLE,允许
* @retval      0,成功.
*              其他,错误.
*/
uint8_t mpu_set_protection(uint32_t baseaddr, uint32_t size, uint32_t rnum, uint8_t de, uint8_t ap, uint8_t sen, uint8_t cen, uint8_t ben)
{
    MPU_Region_InitTypeDef mpu_region_init_handle;
    HAL_MPU_Disable();                                                   /* 配置MPU之前先关闭MPU,配置完成以后在使能MPU */
    mpu_region_init_handle.Enable = MPU_REGION_ENABLE;                   /* 使能该保护区域 */
    mpu_region_init_handle.Number = rnum;                                /* 设置保护区域 */
    mpu_region_init_handle.BaseAddress = baseaddr;                       /* 设置基址 */
    mpu_region_init_handle.DisableExec = de;                             /* 是否允许指令访问 */
    mpu_region_init_handle.Size = size;                                  /* 设置保护区域大小 */
    mpu_region_init_handle.SubRegionDisable = 0X00;                      /* 禁止子区域 */
    mpu_region_init_handle.TypeExtField = MPU_TEX_LEVEL0;                /* 设置类型扩展域为level0 */
    mpu_region_init_handle.AccessPermission = (uint8_t)ap;               /* 设置访问权限, */
    mpu_region_init_handle.IsShareable = sen;                            /* 是否共用? */
    mpu_region_init_handle.IsCacheable = cen;                            /* 是否cache? */
    mpu_region_init_handle.IsBufferable = ben;                           /* 是否缓冲? */
    HAL_MPU_ConfigRegion(&mpu_region_init_handle);                       /* 配置MPU */
    HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);                              /* 开启MPU */
    return 0;
}
/**
* @brief       设置需要保护的存储块
* @param       无
* @note        必须对部分存储区域进行MPU保护,否则可能导致程序运行异常
*              比如MCU屏不显示,摄像头采集数据出错等等问题...
*/
void mpu_memory_protection(void)
{

    /* 保护整个DTCM,共128K字节 */
    mpu_set_protection( 0x20000000,                 /* 基地址 */
                        MPU_REGION_SIZE_128KB,      /* 长度 */
                        MPU_REGION_NUMBER1, 0,      /* NUMER1,允许指令访问 */
                        MPU_REGION_FULL_ACCESS,     /* 全访问 */
                        MPU_ACCESS_NOT_SHAREABLE,   /* 禁止共用 */
                        MPU_ACCESS_CACHEABLE,       /* 允许cache */
                        MPU_ACCESS_BUFFERABLE);     /* 允许缓冲 */
   
    /* 保护整个AXI SRAM,共512K字节 */
    mpu_set_protection( 0x24000000,                 /* 基地址 */
                        MPU_REGION_SIZE_512KB,      /* 长度 */
                        MPU_REGION_NUMBER2, 0,      /* NUMER2,允许指令访问 */
                        MPU_REGION_FULL_ACCESS,     /* 全访问 */
                        MPU_ACCESS_NOT_SHAREABLE,   /* 禁止共用 */
                        MPU_ACCESS_CACHEABLE,       /* 允许cache */
                        MPU_ACCESS_BUFFERABLE);     /* 允许缓冲 */
   
    /* 保护整个SRAM1~SRAM3,共512K字节 */
    mpu_set_protection( 0x30000000,                 /* 基地址 */
                        MPU_REGION_SIZE_512KB,      /* 长度 */
                        MPU_REGION_NUMBER3, 0,      /* NUMER3,允许指令访问 */
                        MPU_REGION_FULL_ACCESS,     /* 全访问 */
                        MPU_ACCESS_NOT_SHAREABLE,   /* 禁止共用 */
                        MPU_ACCESS_CACHEABLE,       /* 允许cache */
                        MPU_ACCESS_BUFFERABLE);     /* 允许缓冲 */
                        
    /* 保护整个SRAM4,共64K字节 */
    mpu_set_protection( 0x38000000,                 /* 基地址 */
                        MPU_REGION_SIZE_64KB,       /* 长度 */
                        MPU_REGION_NUMBER4, 0,      /* NUMER4,允许指令访问 */
                        MPU_REGION_FULL_ACCESS,     /* 全访问 */
                        MPU_ACCESS_NOT_SHAREABLE,   /* 禁止共用 */
                        MPU_ACCESS_CACHEABLE,       /* 允许cache */
                        MPU_ACCESS_BUFFERABLE);     /* 允许缓冲 */
                        
    /* 保护MCU LCD屏所在的FMC区域,共64M字节 */
    mpu_set_protection( 0x60000000,                 /* 基地址 */
                        MPU_REGION_SIZE_64MB,       /* 长度 */
                        MPU_REGION_NUMBER5, 0,      /* NUMER5,允许指令访问 */
                        MPU_REGION_FULL_ACCESS,     /* 全访问 */
                        MPU_ACCESS_NOT_SHAREABLE,   /* 禁止共用 */
                        MPU_ACCESS_NOT_CACHEABLE,   /* 禁止cache */
                        MPU_ACCESS_NOT_BUFFERABLE); /* 禁止缓冲 */
                        
    /* 保护SDRAM区域,共32M字节 */
    mpu_set_protection( 0xC0000000,                 /* 基地址 */
                        MPU_REGION_SIZE_32MB,       /* 长度 */
                        MPU_REGION_NUMBER6, 0,      /* NUMER6,允许指令访问 */
                        MPU_REGION_FULL_ACCESS,     /* 全访问 */
                        MPU_ACCESS_NOT_SHAREABLE,   /* 禁止共用 */
                        MPU_ACCESS_CACHEABLE,       /* 允许cache */
                        MPU_ACCESS_BUFFERABLE);     /* 允许缓冲 */
                        
    /* 保护整个NAND FLASH区域,共256M字节 */
    mpu_set_protection( 0x80000000,                 /* 基地址 */
                        MPU_REGION_SIZE_256MB,      /* 长度 */
                        MPU_REGION_NUMBER7, 1,      /* NUMER7,禁止指令访问 */
                        MPU_REGION_FULL_ACCESS,     /* 全访问 */
                        MPU_ACCESS_NOT_SHAREABLE,   /* 禁止共用 */
                        MPU_ACCESS_NOT_CACHEABLE,   /* 禁止cache */
                        MPU_ACCESS_NOT_BUFFERABLE); /* 禁止缓冲 */
}


PIC1.png
PIC2.png
PIC3.png
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117546
QQ
发表于 2024-12-11 08:45:51 | 显示全部楼层
把这个删掉,这种骚操作不要加,全部MPU的API管理即可

2.png

解决办法有两个

1、配置UART所使用的RAM空间的属性为最低性能,也就是完全关闭读写Cache即可,此贴

使用STM32H7的AXI SRAM,SRAM1到SRAM4对应的Cache最高性能和最低性能配置
https://forum.anfulai.cn/forum.php?mod=viewthread&tid=99322

2、也可以回环打印前,优先调用下函数

SCB_CleanInvalidateDCache



最后就是程序里面的一些其他问题,有时间可以改进下

1、MPU的NUMBER是从NUMBER0开始的
2、HAL库提供了UART DMA IDEL函数,不要用法自己造函数了。

回复

使用道具 举报

2

主题

3

回帖

9

积分

新手上路

积分
9
 楼主| 发表于 2024-12-15 03:49:51 | 显示全部楼层
好的好的 我这边测试看看呢
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-8-14 05:26 , Processed in 0.053428 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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