【STM32】内存管理

【STM32】内存管理

文章目录

  • 【STM32】内存管理
    • 1、内存管理简介
    • 疑问:为啥不用标准的 C 库自带的内存管理算法?
    • 2、分块式内存管理(掌握)
      • 分配方向
      • 分配原理
      • 释放原理
      • 分块内存管理 管理内存情况
    • 3、内存管理使用(掌握)
      • 操作步骤
      • 内存池
      • 内存管理表

1、内存管理简介

如何在LCD 上面实现SD卡文件浏览?

需要读取所有文件名到内存,然后显示到LCD。一般的方法,是定义一个数组来存储所有文件名

1,需要知道最大文件名的长度。255字节。

2,需要知道文件个数。 100?1000?10000 ?

如果没有内存管理:则要定义一个:uint8_t filenametbl[10000][255]; 的数组!(占用2550K字>节内存

内存管理,是指软件运行时对MCU内存资源的分配和使用的技术。(内存的大管家)

其最主要目的是:如何高效,快速的分配,并且在适当的时候释放和回收内存资源。(防止内存泄露、内存碎片)

内存使用三部曲:1. 内存申请(分配) 2. 内存使用 3.内存释放

内存管理的实现方法有很多种,最终都是实现2个函数:malloc和free;

malloc内存申请
free内存释放

标准的 C 库也提供了函数 malloc()和函数 free()来实现动态地申请和释放内存 。

疑问:为啥不用标准的 C 库自带的内存管理算法?

因为标准 C 库的动态内存管理方法有如下几个缺点:

  • 占用大量的代码空间 不适合用在资源紧缺的嵌入式系统中
  • 没有线程安全的相关机制
  • 运行有不确定性,每次调用这些函数时花费的时间可能都不相同
  • 内存碎片化
  • ………

2、分块式内存管理(掌握)

分块式内存管理由内存池和内存管理表两部分组成。内存池被等分为n块,对应的内存管理表,大小也为n,内存管理表的每一个项对应内存池的一块内存。

内存管理表的项值代表的意义:当该项值为0时,代表对应的内存块未被占用;当该项值非零时,代表该项对应的内存块已经被占用,其数值则代表被连续占用的内存块数。

当内存管理刚初始化的时候,内存管理表全部清零,表示没有任何内存块被占用。

分配方向

分配原理

当指针p调用malloc申请内存时,

① 先判断p要分配的内存块数(m)

② 从第n项开始,向下查找,直到找到m块连续的空内存块(即对应内存管理表项为0)

③ 将这m个内存管理表项的值都设置为m(标记被占用)

④ 把最后的这个空内存块的地址返回指针p,完成一次分配

注意:如果当内存不够时(找到最后也没有找到连续m块空闲内存),则返回NULL给p,表示分配失败。

释放原理

当指针p申请的内存用完,需要释放的时候,调用free函数实现。

free函数实现:

① 先判断p指向的内存地址所对应的内存块

② 找到对应的内存管理表项目,得到p所占用的内存块数目m

③ 将这m个内存管理表项目的值都清零,标记释放,完成一次内存释放

分块内存管理 管理内存情况

3、内存管理使用(掌握)

操作步骤

1、初始化内存

内存管理控制器 struct _m_malloc_dev
外扩SRAM 需初始化(内部SRAM不需要)
内存管理表 清零	void my_mem_init(uint8_t memx)

2、申请内存

void *mymalloc(uint8_t memx, uint32_t size)

3、操作内存

sprintf((char *)p, “Memory Malloc Test%03d”, i);

4、释放内存(用完,一定要释放)

void myfree(uint8_t memx, void *ptr)
/* 内存管理控制器 */
#define SRAMBANK 2 	/* 定义管理的内存片数*/
struct _m_mallco_dev
{void 		(*init)(uint8_t);			/* 函数指针,指向内存初始化函数,用于初始化内存管理 */uint8_t	(*perused)(uint8_t);		/* 函数指针,指向内存使用率函数,用于获取内存使用率 */uint8_t 	*membase[SRAMBANK]; 	/* 内存池指针,指向内存池 */uint16_t 	*memmap[SRAMBANK];  	/* 内存管理表指针,指向内存管理表 */uint8_t  	memrdy[SRAMBANK]; 		/* 内存管理表就绪标志,用于表示内存管理表是否已初始化 */
};
struct _m_mallco_dev mallco_dev
{my_mem_init,	my_mem_perused, 		mem1base, mem2base,		mem1mapbase, mem2mapbase,	0, 0,	
};MEMx_MAX_SIZE 		内存池中内存块大小
MEMx_ALLOC_TABLE_SIZE 	内存管理表中项数
/* 内存池 */
static __align(64) uint8_t mem1base[MEM1_MAX_SIZE];
static __align(64) uint8_t mem2base[MEM2_MAX_SIZE];
/* 内存管理表 */
static uint16_t mem1mapbase[MEM1_ALLOC_TABLE_SIZE];
static uint16_t mem2mapbase[MEM2_ALLOC_TABLE_SIZE];

内存池

uint8_t mem1base[MEM1_MAX_SIZE]
MEM1_ALLOC_TABLE_SIZE个内存块

内存管理表

uint16_t mem1mapbase[MEM1_ALLOC_TABLE_SIZE]
MEM1_ALLOC_TABLE_SIZE个项
项的大小为2字节

void my_mem_init(uint8_t memx)
{uint8_t mttsize = sizeof(MT_TYPE); 	/* 获取memmap数组的类型长度(uint16_t /uint32_t)*/my_mem_set(mallco_dev.memmap[memx], 0, memtblsize[memx] * mttsize);	/* 内存管理表数据清零 */mallco_dev.memrdy[memx] = 1;        	/* 内存管理初始化OK */
}
uint16_t my_mem_perused(uint8_t memx)
{uint32_t i, used = 0;for (i = 0; i < memtblsize[memx]; i++)if (mallco_dev.memmap[memx][i])used++;return (used * 1000) / (memtblsize[memx]);
}
void my_mem_set(void *s, uint8_t c, uint32_t count)
{uint8_t *xs = s;while (count--) *xs++ = c;
}

void *mymalloc(uint8_t memx, uint32_t size)
{uint32_t offset; 	offset = my_mem_malloc(memx, size);if (offset == 0xFFFFFFFF) return NULL;	/* 申请出错 */else return (void *)((uint32_t)mallco_dev.membase[memx] + offset);	/* 申请没问题,返回首地址 */
}
uint32_t my_mem_malloc(uint8_t memx, uint32_t size)
{/* 1、判断内存块memx是否已经初始化 *//* 2、通过size获取需要分配的连续内存块数x *//* 3、搜索符合 要求内存块数x 的内存块 *//* 4、找到符合要求内存块数区域,对其管理表写入内存块数的值x,返回偏移地址 */
}

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【SpringMVC】十分钟跑起来一个SpringMVC项目

目录标题 1 项目概述1.项目结构解析2. MVC项目的结构和每个组件的作用&#xff1a;3. 项目的工作流程&#xff1a;4 后期可以扩展的点&#xff1a;2.源码学习1. HelloController 类&#xff0c;Spring MVC控制器2 springmvc-servlet.xml - Spring MVC的主要配置文件3.web 目录 …

【复习】计算机网络

网络模型 OSI 应用层&#xff1a;给应用程序提供统一的接口表示层&#xff1a;把数据转换成兼容另一个系统能识别的格式会话层&#xff1a;负责建立、管理、终止表示层实体之间的通信会话传输层&#xff1a;负责端到端的数据传输网络层&#xff1a;负责数据的路由、转发、分片…

2025年- G17-Lc91-409.最长回文-java版

1.题目描述 2.思路 思路1: 判断一个字符串中的字母个数是否是偶数个。 遍历字符串&#xff0c;检查每个字符是否是字母&#xff08;可以通过 Character.isLetter() 来判断&#xff09;。 累加字母的个数。 最后判断字母的个数是否是偶数。 思路2: 这段 Java 代码的作用是 统…

本地安装 Grafana Loki

本地安装 Grafana Loki 一、 安装 Loki1. 下载 Loki2. 创建 Loki 配置文件3. 创建 Loki 服务 二、安装 Promtail1. 下载 Promtail2. 创建 Promtail 配置文件3. 创建 Promtail 服务 三、 安装 Grafana四、启动所有服务五、添加loki 数据源1. 添加仪表板2. 日志查询面板 json 参考…

创建虚拟环境以及配置对应的项目依赖

文章目录 首先创建一个虚拟环境&#xff0c;创建一个名字为myenv,并且版本为xxx的虚拟环境 conda create --name myenv pythonxxx激活虚拟环境 conda activate myenv下载所需的依赖&#xff0c;如果有requirements.txt文件 pip install -r requirements.txt容易出现的错误&a…

W803|联盛德|WM IoT SDK2.X测试|(1)开箱:开发板及说明

前几天关注的联盛德微电子新推出了WM IoT SDK2.X&#xff0c;正式发布后&#xff0c;邀请用户参加“免费试用&#xff0c;赢千元大礼”活动&#xff0c;填写信息&#xff0c;等待统一发送&#xff0c;很快收到了板子。 活动地址&#xff1a;联盛德微电子WM IoT SDK2.X正式发布…

SSI用量子计算来玩AI

刚到家&#xff0c;早上说今天回来要写SSI为什么这么牛B&#xff0c;那就必须得写 SSI是什么公司&#xff1f; Safe Super Intelligence 就是中间这个秃子的公司 ilya 前openAI 首席科学家(现在的mark chen确实有点水) Daniel Gross、Ilya Sutskever、Daniel Levy&#xff…

【分布式数据一致性算法】Gossip协议详解

在分布式系统中&#xff0c;多个节点同时提供服务时&#xff0c;数据一致性是核心挑战。在多个节点中&#xff0c;若其中一个节点的数据发生了修改&#xff0c;其他节点的数据都要进行同步。 一种比较简单粗暴的方法就是 集中式发散消息&#xff0c;简单来说就是一个主节点同时…

文档检索服务平台

文档检索服务平台是基于Elasticsearch的全文检索&#xff0c;包含数据采集、数据清洗、数据转换、数据检索等模块。 项目地址&#xff1a;Github、国内Gitee 演示地址&#xff1a;http://silianpan.cn/gdss/ 以下是演示角色和账号&#xff08;密码同账号&#xff09;&#xf…

【YOLOv8】YOLOv8改进系列(2)----替换主干网络之FasterNet(CVPR 2023)

主页&#xff1a;HABUO&#x1f341;主页&#xff1a;HABUO &#x1f341;YOLOv8入门改进专栏&#x1f341; &#x1f341;如果再也不能见到你&#xff0c;祝你早安&#xff0c;午安&#xff0c;晚安&#x1f341; 【YOLOv8改进系列】&#xff1a; 【YOLOv8】YOLOv8结构解读…

Linux信号

目录 1. 信号的概念搞定&#xff08;输出结论&#xff0c;支撑我们的理解&#xff09; 补充知识 2.信号的产生 补充知识 3.信号的保存 4.阻塞信号 1. 信号其他相关常见概念 2. 在内核中的表示 3. sigset_t 4. 信号集操作函数 sigprocmask sigpending 5. 信号的…

NI Multisim仿真实现39计数器

功能需求 39进制计数器。 功能分析 &#xff08;1&#xff09;时钟信号产生电路&#xff1a;用555定时器产生时钟脉冲 2&#xff09;计数器&#xff1a; 用两片74160先串接起来构成一个百进制计数器&#xff1b;再用置数法接成39进制计数器。&#xff08;可用开关控制计数器…

DeepSeek R1/V3满血版——在线体验与API调用

前言&#xff1a;在人工智能的大模型发展进程中&#xff0c;每一次新模型的亮相都宛如一颗投入湖面的石子&#xff0c;激起层层波澜。如今&#xff0c;DeepSeek R1/V3 满血版强势登场&#xff0c;为大模型应用领域带来了全新的活力与变革。 本文不但介绍在线体验 DeepSeek R1/…

Android Binder机制

Binder是IPC&#xff08;进程间通信&#xff09;的一种机制&#xff0c;它允许不同的应用或系统服务在不同的进程中安全地交换数据。Binder的核心原理是基于客户端-服务器模型&#xff08;C/S架构)。 一、Binder的定义 1. Binder是Android中的一个类&#xff0c;它继承了IBind…

医疗AI领域中GPU集群训练的关键技术与实践经验探究(上)

医疗AI领域中GPU集群训练的关键技术与实践经验探究(上) 一、引言 1.1 研究背景与意义 在科技飞速发展的当下,医疗 AI 作为人工智能技术与医疗领域深度融合的产物,正引领着医疗行业的深刻变革。近年来,医疗 AI 在疾病诊断、药物研发、健康管理等诸多方面取得了显著进展,…

MariaDB 历史版本下载地址 —— 筑梦之路

MariaDB 官方yum源里面只有目前在维护的版本&#xff0c;而有时候对于老项目来说还是需要老版本的rpm包&#xff0c;国内很多镜像站都是同步的官方仓库&#xff0c;因此下载老版本也不好找&#xff0c;这里主要记录下从哪里可以下载到历史版本的MariaDB rpm包。 1. 官方归档网…

特辣的海藻!2

基础知识点 整型数字-->字符数字 方法一&#xff1a;使用Character.forDigit()方法 Character.forDigit(int num, int radix) 该方法可以将整型数字转换为对应的字符形式。radix表示进制 Tips&#xff1a; ● 需要转换的整型数字必须在 0 到 radix-1 的范围内&#xff0c;…

RoCEv2 高性能传输协议与 Lossless 无损网络

目录 文章目录 目录RoCERoCEv2 协议栈RoCEv2 需要 Lossless NetworkLossless Network 拥塞控制技术网络拥塞的原因PFC 基于优先级的流量控制PFC Deadlock&#xff08;死锁&#xff09;的问题PFC Storm&#xff08;风暴&#xff09;的问题ECN 显式拥塞通知拥塞控制ECN 拥塞控制滞…

win10把c盘docker虚拟硬盘映射迁移到别的磁盘

c盘空间本身就比较小、如果安装了docker服务后&#xff0c;安装的时候没选择其他硬盘&#xff0c;虚拟磁盘也在c盘会占用很大的空间&#xff0c;像我的就三十多个G&#xff0c;把它迁移到其他磁盘一下子节约几十G 1、先输入下面命令查看 docker 状态 wsl -l -v 2、如果没有停止…

论文笔记:Autonomy-of-Experts Model

202501 arxiv 1 intro MoE中常被忽视的一个关键问题是路由器的决策过程与专家执行之间的分离 路由器无法直接评估专家的能力&#xff0c;因此它对专家的选择基本上是没有标签的预测如果路由器做出了错误的预测&#xff0c;选择的专家可能会试图处理这些令牌&#xff0c;但未能…