娇小w搡bbbb搡bbb,《第一次の人妻》,中国成熟妇女毛茸茸,边啃奶头边躁狠狠躁视频免费观看

歷史上的今天

今天是:2025年01月09日(星期四)

正在發生

2019年01月09日 | STM32學習筆記一一內存管理

發布者:大泉人家 來源: 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;        //偏移所在內存塊號碼  

        int nmemb=mallco_dev.memmap[index]; //內存塊數量

        for(i=0;i

        {  

            mallco_dev.memmap[index+i]=0;  

        }

        return 0;  

    }

    else

        return 2;//偏移超區了.  

}  

//釋放內存(外部調用) 

//ptr:內存首地址 

void myfree(void *ptr)  

{  

    u32 offset;  

    if(ptr==NULL)

        return;//地址為0.  

    offset=(u32)ptr-(u32)mallco_dev.membase;  

    mem_free(offset);   //釋放內存     

}  

//分配內存(外部調用)

//size:內存大小(字節)

//返回值:分配到的內存首地址.

void *mymalloc(u32 size)  

{  

    u32 offset;     


    offset=mem_malloc(size);                       

    if(offset==0XFFFFFFFF)

        return NULL;  

    else 

        return (void*)((u32)mallco_dev.membase+offset);  

}  

//重新分配內存(外部調用)

//*ptr:舊內存首地址

//size:要分配的內存大小(字節)

//返回值:新分配到的內存首地址.

void *myrealloc(void *ptr,u32 size)  

{  

    u32 offset;  


    offset=mem_malloc(size);  

    if(offset==0XFFFFFFFF)

        return NULL;     

    else  

    {                                      

        mymemcpy((void*)((u32)mallco_dev.membase+offset),ptr,size); //拷貝舊內存內容到新內存   

        myfree(ptr);                                                //釋放舊內存

        return (void*)((u32)mallco_dev.membase+offset);             //返回新內存首地址

    }  

}


主函數測試:


#include "led.h"

#include "delay.h"

#include "sys.h"

#include "usart.h"

#include "lcd.h"

#include "key.h"

#include "malloc.h" 

#include "usmart.h" 


 int main(void)

 { 

    u8 key;      

    u8 i=0;     

    u8 *p=0;

    u8 *tp=0;

    u8 paddr[18];           //存放P Addr:+p地址的ASCII值 


    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 設置中斷優先級分組2

    delay_init();            //延時函數初始化    

    uart_init(9600);        //串口初始化為9600

    LED_Init();             //初始化與LED連接的硬件接口

    LCD_Init();             //初始化LCD    

    usmart_dev.init(72);    //初始化USMART 

    KEY_Init();             //按鍵初始化   

    mem_init();             //初始化內存池


    POINT_COLOR=RED;//設置字體為紅色 

    LCD_ShowString(60,50,200,16,16,"Mini STM32");   

    LCD_ShowString(60,70,200,16,16,"MALLOC TEST");  

    LCD_ShowString(60,90,200,16,16,"ATOM@ALIENTEK");

    LCD_ShowString(60,110,200,16,16,"2014/3/12");  

    LCD_ShowString(60,130,200,16,16,"KEY0:Malloc");

    LCD_ShowString(60,150,200,16,16,"KEY1:Write Data");

    LCD_ShowString(60,170,200,16,16,"WK_UP:Free");


    POINT_COLOR=BLUE;//設置字體為藍色  

    LCD_ShowString(60,190,200,16,16,"SRAM USED:   %");  

    while(1)

    {   

        key=KEY_Scan(0);//不支持連按 

        switch(key)

        {

            case 0:     //沒有按鍵按下    

                break;

            case 1:     //KEY0按下

                p=mymalloc(2048);   //申請2K字節

                if(p!=NULL)

                    sprintf((char*)p,"Memory Malloc Test%03d",i);//向p寫入一些內容

                break;

            case 2:     //KEY1按下       

                if(p!=NULL)

                {

                    sprintf((char*)p,"Memory Malloc Test%03d",i);//更新顯示內容    

                    LCD_ShowString(60,250,200,16,16,p);          //顯示P的內容

                }

                break;

            case 3:     //WK_UP按下     

                myfree(p);  //釋放內存

                p=0;        //指向空地址

                break; 

        }

        if(tp!=p)

        {

            tp=p;

            sprintf((char*)paddr,"P Addr:0X%08X",(u32)tp);

            LCD_ShowString(60,230,200,16,16,paddr); //顯示p的地址

            if(p)LCD_ShowString(60,250,200,16,16,p);//顯示P的內容

            else LCD_Fill(60,250,239,266,WHITE);    //p=0,清除顯示

        }

        delay_ms(10);   

        i++;

        if((i%20)==0)//DS0閃爍.

        {

            LCD_ShowNum(60+80,190,mem_perused(),3,16);//顯示內存使用率

            LED0=!LED0;

        }

    }          

}


參考:


1.原子庫函數教程


2.STM32-內存管理



關鍵字:STM32  內存管理 引用地址:STM32學習筆記一一內存管理

上一篇:STM32學習筆記一一UCOSII(1)
下一篇:STM32學習筆記一一DMA傳輸

0

推薦閱讀

全球最大芯片廠商英特爾公司深陷“芯片門”丑聞,芯片漏洞問題持續發酵。據美國媒體報道,英特爾在美國面臨至少三起來自消費者的集體訴訟,公司首席執行官布賴恩·克爾扎尼奇被曝去年大幅減持公司股票,不過英特爾否認此事與芯片漏洞存在關聯。美國石英財經網站等媒體日前披露,英特爾公司芯片存在嚴重技術缺陷,引發全球用戶對信息安全的擔憂。專業人士指...
2019年已經來臨,面對日新月異的技術發展,我們所面臨的關鍵工程趨勢和挑戰,例如物聯網(IoT)、從原型驗證到商業化部署的5G技術推進以及大眾自動駕駛等領域也是越來越繁雜。但是這些工程趨勢正在打破傳統的行業和產品測試,帶來了前所未有的復雜挑戰,但這也極大地推動了創新。 EE梳理了近期科技行業趨勢,分別從技術、公司發展、行業、等角度選出了幾個...
在拉斯維加斯舉辦的2020年國際消費電子展(2020年1月7日至10日)上,科技公司大陸集團將與音響專家森海塞爾聯合推出了一款車載無音箱音響系統。這款獨一無二的系統將讓車內四處流淌栩栩如生的沉浸式聲效。這兩家公司將把森海塞爾的專利AMBEO 3D音頻技術與大陸集團的Ac2ated Sound音響系統整合到一起。大陸集團的創新概念完全摒棄了傳統的音箱技術,而是...
深圳市金泰克半導體有限公司(以下簡稱“金泰克”)總部位于廣東省深圳市坪山區,是國內知名的專業存儲方案提供商,致力于打造存儲全產業鏈的發展模式。金泰克創建于2000年,成立之初主要專注于消費類市場,2010年開始布局行業市場,并在研發?才儲備、生產中心組建、流程體系梳理、大客戶培養開發等方面持續發力。經過十余年的市場耕耘和沉淀,公司在消費...

史海拾趣

問答坊 | AI 解惑

請教控制類該準備什么傳感器模塊?

本帖最后由 paulhyde 于 2014-9-15 02:59 編輯 請教各位電子設計競賽過來人,做控制類的題目需要準備什么樣的模塊?或者傳感器模塊? 謝謝啦。 [ 本帖最后由 open82977352 于 2010-2-2 19:50 編輯 ]    …

查看全部問答∨

SD卡總線驅動SDBus.dll是怎么樣與總線控制器驅動關聯起來的

SD卡總線驅動SDBus.dll是怎么樣與總線控制器驅動SDHC_XXX.dll關聯起來的?…

查看全部問答∨

請成都的獵頭朋友幫個忙

    我是四川人,目前在上海工作,最近打算回成都找個工作。     簡單介紹一下自己。名校碩士畢業,三年vxworks設備驅動及DSP(TI C6000系列)軟件開發經驗,擅長數字信號處理,數值計算方面的算法開發,數模電路有些基礎,但 ...…

查看全部問答∨

PC寄存器地址的問題

1.  ; 文件名:TEST4.S 2.  ; 功能:通過查表實現程序散轉 3.  ; 說明:使用ARMulate軟件仿真調試 4.  NumCon   EQU    0x40003001    ; 定義變量NumCn     ...…

查看全部問答∨

請問 即插即用 和 熱插拔 的區別

這個問題我已google,baidu之。。還是不是很明白。。我剛涉及到驅動開發這一塊內容。。希望能得到大家通俗的解釋。。。不要給我google和baidu出的答案。。…

查看全部問答∨

求助:請介紹一家能開電腦主板(x86)的公司,謝謝2!

請教:      我們公司想找一家公司開一塊電腦主板!      請各位大哥一些有這方面能力的公司!      QQ:19335776      EMAIL:LSH9982008@163.COM 謝謝!…

查看全部問答∨

用HT7333成功替代BL8505,穩定提供的3.3V供電

    一早找到HT7333代替BL8505,HT7333的1、3腳分別接到C7兩端(其中1腳接到C7的接地端),2腳接到C4的正端(在PCB版上靠近R14),L1不接。     就穩定的提供了3.3V的電壓。      以前講過:1117- ...…

查看全部問答∨

NAND01G-B datasheet中怎么沒有命令寄存器,數據寄存器,地址寄存器的內存映射

dsp通過emifa與nandflash連接,nandflash型號是NAND01GW3A. 可是datasheet中怎么沒有命令寄存器,數據寄存器,地址寄存器的內存映射地址.…

查看全部問答∨

linux設備驅動程序(中文第三版) 2.6內核

linux設備驅動程序(中文第三版) 2.6內核新手做點貢獻賺點入門費阿絕對好書啊…

查看全部問答∨

avr studio4 寄存器問題

請問定義的變量a,在avr studio4中怎樣能看到a中的數據呢?很著急,希望好心人幫忙。先謝謝啦!  …

查看全部問答∨
小廣播
添点儿料...
无论热点新闻、行业分析、技术干货……
設計資源 培訓 開發板 精華推薦

最新單片機文章
何立民專欄 單片機及嵌入式寶典

北京航空航天大學教授,20余年來致力于單片機與嵌入式系統推廣工作。

 
EEWorld訂閱號

 
EEWorld服務號

 
汽車開發圈

 
機器人開發圈

電子工程世界版權所有 京ICP證060456號 京ICP備10001474號-1 電信業務審批[2006]字第258號函 京公網安備 11010802033920號 Copyright ? 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
主站蜘蛛池模板: 吴桥县| 南澳县| 泌阳县| 宜兰县| 新蔡县| 应用必备| 赤水市| 松江区| 平山县| 淅川县| 福海县| 建宁县| 小金县| 胶州市| 三穗县| 滨州市| 淳化县| 扶余县| 内江市| 南开区| 新和县| 黎平县| 江西省| 铁岭市| 封开县| 巴塘县| 曲靖市| 武定县| 泸西县| 贵定县| 湘潭市| 永顺县| 秭归县| 乳山市| 政和县| 长乐市| 商都县| 游戏| 亚东县| 甘孜县| 铁力市|