datasheet

STM32学习笔记一一内存管理

2019-01-09来源: eefocus 关键字:STM32  内存管理

1.简介

内存管理:指软件运行时对计算机内存资源的分配和使用的技术。其最主要的目的是如何高效,快速的分配,并且在适当的时候释放和回收内存资源。 内存管理的实现方法有很多种,最终都是要实现两个函数: malloc 和 free。


malloc :函数用于内存申请; 

free: 函数用于内存释放。


1.1 分块式内存管理原理


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


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


比如:某项值为 10,那么说明包括本项对应的内存块在内,总共分配了 10 个内存块给外部的某 

个指针。内寸分配方向如图所示,是从顶—>底的分配方向。即首先从最末端开始找空内存。当内存管理刚初始化的时候,内存表全部清零,表示没有任何内存块被占用。


1.2 分配原理

当指针 p 调用 malloc 申请内存的时候,先判断 p 要分配的内存块数(m),然后从第 n 项开始,向下查找,直到找到 m 块连续的空内存块(即对应内存管理表项为 0),然后将这 m 个内存管理表项的值都设置为 m(标记被占用),最后,把最后的这个空内存块的地址返回指针 p,完成一次分配。


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


1.2 释放原理

当 p 申请的内存用完,需要释放的时候,调用 free 函数实现。 free 函数先判断 p 指向的内存地址所对应的内存块,然后找到对应的内存管理表项目,得到 p 所占用的内存块数目 m(内存管理表项目的值就是所分配内存块的数目),将这 m 个内存管理表项目的值都清零,标记释放,完成一次内存释放。


2.软件分析

头文件:


#ifndef __MALLOC_H

#define __MALLOC_H

#include "stm32f10x.h"


#ifndef NULL

#define NULL 0

#endif


//内存参数设定.

#define MEM_BLOCK_SIZE          32                              //内存块大小为32字节

#define MEM_MAX_SIZE            42*1024                         //最大管理内存 42K

#define MEM_ALLOC_TABLE_SIZE    MEM_MAX_SIZE/MEM_BLOCK_SIZE     //内存表大小



//内存管理控制器

struct _m_mallco_dev

{

    void (*init)(void);             //初始化

    u8 (*perused)(void);            //内存使用率

    u8  *membase;                   //内存池 

    u16 *memmap;                    //内存管理状态表

    u8  memrdy;                     //内存管理是否就绪

};

extern struct _m_mallco_dev mallco_dev; //在mallco.c里面定义


void mymemset(void *s,u8 c,u32 count);  //设置内存

void mymemcpy(void *des,void *src,u32 n);//复制内存     

void mem_init(void);                     //内存管理初始化函数(外/内部调用)

u32 mem_malloc(u32 size);               //内存分配(内部调用)

u8 mem_free(u32 offset);                //内存释放(内部调用)

u8 mem_perused(void);                   //得内存使用率(外/内部调用) 

////////////////////////////////////////////////////////////////////////////////

//用户调用函数

void myfree(void *ptr);                 //内存释放(外部调用)

void *mymalloc(u32 size);               //内存分配(外部调用)

void *myrealloc(void *ptr,u32 size);    //重新分配内存(外部调用)

#endif



参考例程:


#include "malloc.h"     


//内存池(4字节对齐)

__align(4) u8 membase[MEM_MAX_SIZE];            //SRAM内存池

//内存管理表

u16 memmapbase[MEM_ALLOC_TABLE_SIZE];           //SRAM内存池MAP

//内存管理参数       

const u32 memtblsize=MEM_ALLOC_TABLE_SIZE;      //内存表大小

const u32 memblksize=MEM_BLOCK_SIZE;            //内存分块大小

const u32 memsize=MEM_MAX_SIZE;                 //内存总大小



//内存管理控制器

struct _m_mallco_dev mallco_dev=

{

    mem_init,           //内存初始化

    mem_perused,        //内存使用率

    membase,            //内存池

    memmapbase,         //内存管理状态表

    0,                  //内存管理未就绪

};


//复制内存

//*des:目的地址

//*src:源地址

//n:需要复制的内存长度(字节为单位)

void mymemcpy(void *des,void *src,u32 n)  

{  

    u8 *xdes=des;

    u8 *xsrc=src; 

    while(n--)

        *xdes++=*xsrc++;  

}  

//设置内存

//*s:内存首地址

//c :要设置的值

//count:需要设置的内存大小(字节为单位)

void mymemset(void *s,u8 c,u32 count)  

{  

    u8 *xs = s;  

    while(count--)

        *xs++=c;  

}      

//内存管理初始化  

void mem_init(void)  

{  

    mymemset(mallco_dev.memmap, 0,memtblsize*2);//内存状态表数据清零  

    mymemset(mallco_dev.membase, 0,memsize);    //内存池所有数据清零  

    mallco_dev.memrdy=1;                        //内存管理初始化OK  

}  

//获取内存使用率

//返回值:使用率(0~100)

u8 mem_perused(void)  

{  

    u32 used=0;  

    u32 i;  


    for(i=0;i

    {  

        if(mallco_dev.memmap[i])

            used++; 

    } 

    return (used*100)/(memtblsize);  

}  

//内存分配(内部调用)

//memx:所属内存块

//size:要分配的内存大小(字节)

//返回值:0XFFFFFFFF,代表错误;其他,内存偏移地址 

u32 mem_malloc(u32 size)  

{  

    signed long offset=0;  

    u16 nmemb;  //需要的内存块数  

    u16 cmemb=0;//连续空内存块数

    u32 i;  


    if(!mallco_dev.memrdy)

        mallco_dev.init();  //未初始化,先执行初始化 

    if(size==0)

        return 0XFFFFFFFF;              //不需要分配

    nmemb=size/memblksize;                      //获取需要分配的连续内存块数

    if(size%memblksize)

        nmemb++;  

    for(offset=memtblsize-1;offset>=0;offset--) //搜索整个内存控制区  

    {     

        if(!mallco_dev.memmap[offset])

            cmemb++;    //连续空内存块数增加

        else 

            cmemb=0;                            //连续内存块清零

        if(cmemb==nmemb)                        //找到了连续nmemb个空内存块

        {

            for(i=0;i

            {  

                mallco_dev.memmap[offset+i]=nmemb;  

            }  

            return (offset*memblksize);         //返回偏移地址  

        }

    }  

    return 0XFFFFFFFF;//未找到符合分配条件的内存块  

}  

//释放内存(内部调用) 

//offset:内存地址偏移

//返回值:0,释放成功;1,释放失败;  

u8 mem_free(u32 offset)  

{  

    int i;  

    if(!mallco_dev.memrdy)//未初始化,先执行初始化

    {

        mallco_dev.init();    

        return 1;//未初始化  

    }  

    if(offset

    {  

int index=offset/memblksize; //偏移所在内

[1] [2]

关键字:STM32  内存管理

编辑:什么鱼 引用地址:http://www.eeworld.com.cn/mcu/2019/ic-news010942852.html
本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。

上一篇:STM32学习笔记一一UCOSII(1)
下一篇:最后一页

关注eeworld公众号 快捷获取更多信息
关注eeworld公众号
快捷获取更多信息
关注eeworld服务号 享受更多官方福利
关注eeworld服务号
享受更多官方福利

推荐阅读

STM32程序移植技巧总结

1. 工程更换不同的STM32芯片eg:stm32f103rct6 ---->stm32f103c8t6:1.1. 修改芯片点击魔术棒,在出来的菜单栏里,Device 选项重新选择芯片1.2. 修改启动文件此处举例是 RCT6 修改为 C8T6,因为 flash 容量大小不一样,所以需要对应修改启动文件,如果是 flash 大小相同,此步骤不需要。此处由:startup_stm32f10x_hd.s修改为startup_stm32f10x_md.s1.3. 修改全局宏定义同样先点击魔术棒,在菜单栏选择 C/C++。进而修改全局宏定义。此处:STM32F10X_HD–>STM32F10X_MD1.4. 重新添加FLASH
发表于 2019-01-09
STM32程序移植技巧总结

STM32学习笔记一一FLASH 模拟 EEPROM

1. 简述STM32 本身没有自带 EEPROM,但是 STM32 具有在应用编程(IAP:In Application Programming)功能,可以把它的 FLASH 当成 EEPROM 来使用。不同型号的 STM32,其 FLASH 容量也有所不同,最小的只有 16K 字节,最大的则达到了1024K 字节。MiniSTM32 开发板选择的 STM32F103RCT6 的 FLASH 容量为 256K 字节,属于大容量产品,闪存模块组织如下图:1.1 主存储器:该部分用来存放代码和数据常数(如 const 类型的数据)。对于大容量产品,其被划分为 256 页,每页 2K 字节。**注意:**小容量和中容量产品则每页
发表于 2019-01-09
STM32学习笔记一一FLASH 模拟 EEPROM

STM32学习笔记一一HEX文件和BIN文件格式

1. 引言今天看串口的 IAP ,平时我们通过 JTAG 等工具下载的都是 HEX 文件,都没有思考一下 HEX 的文件组成。而串口 IAP 下载的是 BIN 文件,刚好在这里区分学习一下。我们平时烧写 HEX 文件是不需要设置地址信息的,因为已经包含在文件里面,而使用 BIN 烧写,需要在程序中指定地址。2. 简述Intel hex 文件是记录文本行的 ASCII 文本文件,在 Intel HEX 文件中,每一行是一个 HEX 记录,由十六进制数组成的机器码或者数据常量。Intel HEX 文件经常被用于将程序或数据传输存储到 ROM、EPROM,大多数编程器和模拟器使用Intel HEX文件。2.1 HEX文件HEX 文件是包括
发表于 2019-01-09
STM32学习笔记一一HEX文件和BIN文件格式

STM32学习笔记一一串口 IAP

(Bootloader 程序)必须通过其它手段,如 JTAG 或 ISP 烧入;第二部分代码(APP 程序)可以使用第一部分代码 IAP 功能烧入,也可以和第一部分代码一起烧入,以后需要程序更新时再通过第一部分 IAP代码更新。他们存放在 STM32 FLASH 的不同地址范围,一般从最低地址区开始存放 Bootloader,紧跟其后的就是 APP 程序。2 .STM32程序流程2.1 STM32 正常的程序运行流程下图为 STM32 正常的程序运行流程:STM32 的内部闪存(FLASH)地址起始于 0x08000000,一般情况下,程序文件就从此地址开始写入。此外STM32是基于Cortex-M3内核的微控制器,其内部通过一张
发表于 2019-01-09
STM32学习笔记一一串口 IAP

STM32学习笔记一一待机唤醒

1. 简述1.1 低功耗模式:在系统或电源复位以后,微控制器处于运行状态。当CPU不需继续运行时,可以利用多种低功耗模式来节省功耗,例如:等待某个外部事件时,常见的按键唤醒。用户需要根据最低电源消耗、最快速启动时间和可用的唤醒源等条件,选定一个最佳的低功耗模式。1.2 STM32F10X系列的低功耗模式STM32F10xxx有三种低功耗模式:–模式– –特点—睡眠模式 Cortex-M3内核停止,所有外设包括Cortex-M3核心的外设,如NVIC、系统时钟(SysTick)等仍在运行停止模式 所有的时钟都已停止待机模式 1.8V电源关闭在这三种低功耗模式中,最低功耗的是待机模式,在此模式下,最低只需 2uA 左右的电流。停机模式
发表于 2019-01-09
STM32学习笔记一一待机唤醒

STM32学习笔记一一红外遥控

}2.2 中断捕获u8 RmtSta=0;u16 Dval;u32 RmtRec=0;u8 RmtCnt=0;void TIM5_IRQHandler(void){ if(TIM_GetITStatus(TIM5,TIM_IT_Update)!= RESET) { if(RmtSta&0x80)//数据接收到标志位 { RmtSta &= ~0x10;//取消上升沿捕获标记 if((RmtSta&0x0F)==0x00) RmtSta |= 1<<6; if((RmtSta&0x0F)<14) RmtSta++; else { RmtSt
发表于 2019-01-09
STM32学习笔记一一红外遥控

小广播

何立民专栏

单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号 电信业务审批[2006]字第258号函 京公海网安备110108001534 Copyright © 2005-2018 EEWORLD.com.cn, Inc. All rights reserved
pt type="text/javascript" src="//v3.jiathis.com/code/jia.js?uid=2113614" charset="utf-8">