RT-Thread 学习笔记:memheap 死机问题的分析与解决

news2025/4/28 16:28:43

验证环境

  • NUCLEO-L476RG 开发板,板载 STM32L476RGT6(96K SARM1 + 32K SRAM2)

  • Win10 64 位

  • Keil MDK 5.36

  • RT-Thread 5.0.1 版本(2023-05-28 master 主线)

  • bsp : bsp\stm32\stm32l476-st-nucleo

功能描述

  • 最近在研究 RT-Thread 内存的管理,熟悉了一下 memheap 的功能实现,并且了解到 memheap 支持多块内存(物理地址不连续)的管理,当开启 memheap 后,rt_malloc 可以遍历所有注册过的 memheap 内存块,并且进行 内存的申请与释放。

  • 当前 STM32L476RGT6 支持两块 SRAM,其中 SRAM1 96KB,还有一块 SRAM2 32KB,SRAM2 默认没有使用,尝试开启 SRAM2

环境搭建

  • stm32l476-st-nucleo 开启 memheap 的方法

2023-05-28_170606.png

  • stm32l476-st-nucleo 开启 SRAM2 的方法
#define HEAP_SRAM2_BEGIN                (0x10000000)
#define HEAP_SRAM2_SIZE                 (32 * 1024)

static struct rt_memheap memheap_sram2;

int system_sram2_init(void)
{
    return rt_memheap_init(&memheap_sram2, "sram2", (void *)HEAP_SRAM2_BEGIN, (rt_size_t)HEAP_SRAM2_SIZE);
}
INIT_BOARD_EXPORT(system_sram2_init);

功能测试

  • 写两个测试命令:一直申请内存直到无法申请内存,一直释放所以申请的内存,确认 rt_malloc 会自动到新增加的 memheap SRAM2 中申请内存

  • 功能验证通过,但是遇到死机问题

  • 测试的函数

void *user_alloc(rt_size_t size)
{
    return rt_memheap_alloc(&memheap_sram2, size);
}

void user_free(void *ptr)
{
    rt_memheap_free(ptr);
}

void user_alloc_test(void)
{
    for (int i = 0; i < MEMHEAP_BLOCK_NUM; i++)
    {
        user_ptr[i] = user_alloc(500);
        if (!user_ptr[i])
        {
            rt_kprintf("malloc failed, index = %d\n", i);
            return;
        }
        else
        {
            rt_kprintf("[%d] : 0x%08x\n", i, user_ptr[i]);
        }
    }
}
MSH_CMD_EXPORT(user_alloc_test, user_alloc_test);

void user_free_test(void)
{
    for (int i = 0; i < MEMHEAP_BLOCK_NUM; i++)
    {
        if (user_ptr[i])
        {
            rt_kprintf("[%d] : 0x%08x\n", i, user_ptr[i]);
            user_free(user_ptr[i]);
        }
    }
}
MSH_CMD_EXPORT(user_free_test, user_free_test);
  • 死机的信息

2023-05-28_195104.png

  • 死机后,打印线程,发现 idle 线程栈异常

2023-05-28_195133.png

  • 开启 CmBacktrace 组件后,发现死机的问题不是固定的,申请申请一个小内存,都会触发异常

问题分析

  • idle 线程的结构数据被破坏了,这就说明,内存越界了,但是测试例程只调用了 RT-Thread memheap 的 内存申请与释放 API,并没有其他的操作

  • 手动申请一块内存,没有触发死机, list thread 发现,idle 线程的栈数据,依旧是异常的!

2023-05-28_195714.png

  • 由于 开发板可以 单步调试,所以经过单步调试,加上分析,确认内存的范围,各个线程栈的内存范围,发现了一个奇怪的问题: 申请的内存偶尔会与线程栈的【静态内存】重叠

  • 由于死机问题并不是必现,但是 idle 线程栈数据异常是必现的。当前怀疑 memheap 的内存范围设置存在问题,通过对比其他开发板的 bsp,发现了问题所在。

  • 原来 bsp stm32l476-st-nucleo 系统的内存 HEAP_BEGIN 设置有问题,直接设置的 第一块内存的起始地址:

#define STM32_SRAM1_START              (0x20000000)
#define HEAP_BEGIN                     STM32_SRAM1_START
  • 初步看上去好像没有问题,其实RT-Thread 开机后,静态的内存数据、线程栈,依旧会占用一些内存,也就是其实内存地址,不能设置为 STM32_SRAM1_START,而是 【剩余内存】

  • 【剩余内存】或者叫【空闲内存】的获取方法如下:

#if defined(__ARMCC_VERSION)
extern int Image$$RW_IRAM1$$ZI$$Limit;
#define HEAP_BEGIN      ((void *)&Image$$RW_IRAM1$$ZI$$Limit)
#elif __ICCARM__
#pragma section="CSTACK"
#define HEAP_BEGIN      (__segment_end("CSTACK"))
#else
extern int __bss_end;
#define HEAP_BEGIN      ((void *)&__bss_end)
#endif
  • 如在 Keil MDK5 上,是 #define HEAP_BEGIN ((void *)&Image$$RW_IRAM1$$ZI$$Limit), 也就是 SRAM1 的 剩余内存作为系统 堆内存使用,而不是 SRAM1 的全部内存作为 堆内存使用

解决方法

  • 如上,重新设置 HEAP_BEGIN 即可

  • 编译发现 RW_IRAM1 不存在,需要修改链接文件:bsp\stm32\stm32l476-st-nucleo\board\linker_scripts\link.sct,增加 RW_IRAM1 的定义

2023-05-28_200650.png

  RW_IRAM1 0x20000000 0x00018000  {  ; RW data
   .ANY (+RW +ZI)
  }
  • 以上修改后,memheap 内存测试通过,不再触发死机

小结

  • memheap 使用起来还是比较的简单,可以通过设置 开启 RT_USING_MEMHEAP_AUTO_BINDING,也就是 勾选 [*] Use all of memheap objects as heap,决定新增加的 memheap 的内存是否参与系统常规的内存管理,如 rt_malloc、rt_free

  • 用户可以单独的实现自己的 memheap 内存块 alloc、free 函数,这样只操作特定的 memheap。

  • 当前的一个小缺点:如果 memheap 内存块较多,超过2个,如 RAM1、RAM2、RAM3,并且开启了 [*] Use all of memheap objects as heap,想实现 RAM1与 RAM2 作为系统通用内存管理,RAM3 用户专用内存管理,那么当前的 memheap 机制做不到,因为 rt_malloc 依旧会在 RAM1、RAM2 不能申请内存时,去 RAM3 申请内存

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/580410.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

机器学习-线性代数-矩阵与空间映射

矩阵 文章目录 矩阵直观理解特殊矩阵矩阵的基本运算矩阵( A A A)乘向量( x x x)的本质&#xff1a;改变空间位置矩阵&#xff1a;空间映射关系矮胖矩阵对空间的降维压缩高瘦矩阵无法覆盖目标空间方阵映射矩阵的秩 直观理解 一个 m n m \times n mn的大小矩阵&#xff0c;直观…

fastjson与lombok一起用出现序列化问题

文章内部信息已脱敏。 有一次在测试环境调用网易电子签章平台的接口&#xff0c;用来生成印章图片。 首先用postman去测试接口&#xff0c;除了必传的固定请求头&#xff0c;请求体参数如下&#xff1a; {"userId": "***********","templateType&qu…

数据在内存中是如何存储的?(上)

C语言进阶——数据在内存中是如何存储的&#xff1f; 一. 整型数据的二进制表示二.数据类型详细介绍1.1 类型的基本归类1.2认识有无符号的区别&#xff08; signed 和 unsigned &#xff09;1.3代码理解一&#xff1a;1.4代码二理解&#xff1a;1.5代码三理解&#xff1a;1.6代…

【P40】JMeter 录制控制器(Recording Controller)

文章目录 一、录制控制器&#xff08;Recording Controller&#xff09;二、准备工作三、测试计划设计 一、录制控制器&#xff08;Recording Controller&#xff09; 可以理解为一个占位符&#xff0c;用来告诉代理服务器将脚本录制到何处&#xff0c;本身无任何逻辑作用&…

AI时代来临,新时代程序员如何紧追时代的风口浪尖?

文章目录 背景AI时代的背景和机遇抓住AI时代的机遇新时代程序员的技能和素质实践建议和资源总结 背景 在这个快速发展的AI时代&#xff0c;程序员们正置身于科技革新的前沿。随着人工智能技术的蓬勃发展和广泛应用&#xff0c;程序员的作用变得愈发重要和关键。他们不再是简单…

Doris之rollup上卷及物化视图

Rollup上卷 通过建表语句创建出来的表称为 Base 表&#xff08;Base Table,基表&#xff09; 在 Base 表之上&#xff0c;我们可以创建任意多个 ROLLUP 表。这些 ROLLUP 的数据是基于 Base 表产生的&#xff0c;并且在物理上是独立存储的。 Rollup表的好处&#xff1a; 和基表…

如何在华为OD机试中获得满分?Java实现【最长的连续子序列】一文详解!

✅创作者&#xff1a;陈书予 &#x1f389;个人主页&#xff1a;陈书予的个人主页 &#x1f341;陈书予的个人社区&#xff0c;欢迎你的加入: 陈书予的社区 &#x1f31f;专栏地址: Java华为OD机试真题&#xff08;2022&2023) 文章目录 1. 题目描述2. 输入描述3. 输出描述…

如何在华为OD机试中获得满分?Java实现【滑动窗口】一文详解!

✅创作者&#xff1a;陈书予 &#x1f389;个人主页&#xff1a;陈书予的个人主页 &#x1f341;陈书予的个人社区&#xff0c;欢迎你的加入: 陈书予的社区 &#x1f31f;专栏地址: Java华为OD机试真题&#xff08;2022&2023) 文章目录 1. 题目描述2. 输入描述3. 输出描述…

软件测试理论----接口测试中restful接口状态码规范

一、restful接口状态码总体分类 类别描述1xx&#xff1a;信息通信传输协议信息2xx&#xff1a;成功表示客户端的请求已成功接受3xx&#xff1a;重定向表示客户端必须执行一些其他操作才能完成其请求4xx&#xff1a;客户端错误此类错误状态码指向客户端5xx&#xff1a;服务器错…

在SPSS Statistics中使用R(插件)

date: 2018-10-30 09:26:33 在SPSS中使用R&#xff08;插件&#xff09; 谷歌或者百度“SPSS中调用R”, 最详细也是最靠谱的就是IBM SPSS社区的这两篇文章: https://www.ibm.com/developerworks/cn/data/library/ba/ba-1401spss-r/https://www.ibm.com/developerworks/cn/ana…

基于Open3D的点云处理6-点云去噪

当我们从扫描设备获取点云数据时&#xff0c;数据会包含噪声和伪影&#xff0c;点云噪声特性包括不真实的点、孤立点、不规则&#xff0c;基于噪声特性对器进行去除&#xff1b; 统计滤波 Statistical Outlier Removal&#xff08;SOR&#xff09;&#xff08;去除离群点&…

【JVM】13. 垃圾回收器

文章目录 13.1. GC分类与性能指标13.1.1. 垃圾回收器概述13.1.2. 垃圾收集器分类13.1.3. 评估GC的性能指标吞吐量暂停时间吞吐量 vs 暂停时间 13.2. 不同的垃圾回收器概述13.2.1. 垃圾回收器发展史13.2.2. 7种经典的垃圾收集器13.2.3. 7款经典收集器与垃圾分代之间的关系13.2.4…

前端自动化测试 —— Jest 测试框架应用

目录​​​​​​​ 什么是自动化测试 为什么要用前端自动化测试 前端自动化分类和思想 单元测试 集成测试 TDD 测试驱动开发&#xff08;Test Driven Development&#xff09; BDD 行为驱动开发&#xff08;Behavior Driven Development&#xff09; 如何自己写非框架…

分布式软件架构——SOA架构/微服务架构/无服务架构

SOA架构 Service-Oriented Architecture&#xff0c;面向服务的架构。面向服务的架构是一次具体地、系统性地成功解决分布式服务主要问题的架构模式。了解SOA架构前&#xff0c;先了解三种比较有代表性的服务拆分的架构模式&#xff0c;这些架构模式是SOA演化过程的中间产物&a…

偷偷曝光下国内这些软件外包公司!(2023 最新版)

ChatGPT狂飙160天&#xff0c;世界已经不是之前的样子。 我新建了人工智能中文站https://ai.weoknow.com 每天给大家更新可用的国内可用chatGPT资源 根据网上的资料&#xff0c;整理出来的一份国内软件外包公司的名单。 找工作的同学都要看看&#xff0c;根据自身的情况&#…

杰理AC632N实现custom hid

1. 设备描述符修改 设备描述符主要修改的是PID、VID、设备发现版本号以及字符串描述。 static const u8 sDeviceDescriptor[] { //<Device DescriptorUSB_DT_DEVICE_SIZE, // bLength: Size of descriptorUSB_DT_DEVICE, // bDescriptorType: Device #if defi…

langchain简版教程附案例

简介 LangChain是一个开源的应用开发框架。基于该开源框架&#xff0c;我们可以把大模型与各种工具结合从而实现各种功能&#xff0c;比如基本文档的问答&#xff0c;解析网页内容、查询表格数据等。目前支持Python和TypeScript两种编程语言。当前Python框架支持的模型和功能最…

腾讯云服务器ping不通解决方法(公网IP/安全组/系统多维度)

腾讯云服务器ping不通什么原因&#xff1f;ping不通公网IP地址还是域名&#xff1f;新手站长从云服务器公网IP、安全组、Linux系统和Windows操作系统多方面来详细说明腾讯云服务器ping不通的解决方法&#xff1a; 目录 腾讯云服务器ping不通原因分析及解决方法 安全组ICMP协…

智能计价器-第14届蓝桥杯省赛Scratch中级组真题第5题

[导读]&#xff1a;超平老师的《Scratch蓝桥杯真题解析100讲》已经全部完成&#xff0c;后续会不定期解读蓝桥杯真题&#xff0c;这是Scratch蓝桥杯真题解析第140讲。 智能计价器&#xff0c;本题是2023年5月7日举行的第14届蓝桥杯省赛Scratch图形化编程中级组真题第5题&#…

楼宇租赁管理系统-什么是楼宇租赁系统

楼宇租赁管理系统是一种综合管理平台&#xff0c;它为不同规模楼宇的租赁管理提供了全面的解决方案。楼宇租赁管理系统的主要功能包括租赁管理、财务管理、维修管理、报告管理以及客户服务管理等。让我们逐一介绍每一个功能点。 一、租赁管理 楼宇租赁管理系统通过集成租户信息…