keil c51的内部RAM(idata)动态内存管理程序(转)

源:keil c51的内部RAM(idata)动态内存管理程序

  程序比较简单,但感觉比较有意思,个人认为有一定应用价值,希望大家有更好的思路和方法,互相促进。
  程序的基本思路是:在CPU堆栈指针SP以上的RAM区域,通过把堆栈指针SP上移若干个字节,把空出的RAM区域供用户使用,当用户在使用完后又可以把该RAM区域释放。
  头文件dmalloc51.h

/*
*********************************************************************************************************
*                     C51内部RAM动态内存申请函数 ,动态内存释放函数
*                        (c) Copyright 2004.6, LM7556,China
*                              All Rights Reserved
*
*
* 文件 : dmalloc51.h
*********************************************************************************************************
*/

//动态内存申请函数DMEM8U *dmalloc(DMEM8U dmsize,StkSize)从RAM堆栈中开辟一段空间做变量区.
//动态内存释放函数DMEM8U freedmalloc(DMEM8U *dmp,DMEM8U dmsize)把动态内存分配的空间从堆栈中释放。

/******************************** Define Messages *****************************************/
#define CPU_PCLEN 2        //CPU 程序指针长度(字节数).
#define RAM_SIZE 0x100    //CPU内部RAM字节数。
#define MEM_OVER 0xff    //CPU内部RAM内存不够。
#define NO_MEM_DEL 0xfe    //试图释放不存在的内存空间。
#define MEM_DELETED 0xfd    //内存空间释放成功。

typedef unsigned char idata DMEM8U;

/************* 动态内存申请函数DMEM8U *dmalloc(DMEM8U dmsize,StkSize) *********************/
//该函数把堆栈SP向上移动dmsize字节空间,再返回指向该空间起始地址的指针,
//入口参数;dmsize是需要分配的空间大小,以DMEM8U为单位。
//          StkSize 需要给CPU预留的堆栈空间.
//出口参数: 返回 STACK_OVER --- CPU内部RAM堆栈溢出,分配的空间不存在.
//            如果成功则返回一个指针,该指针指向所分配空间(大小为dmsize)的起始地址。
DMEM8U *dmalloc(DMEM8U dmsize,StkSize);

/************ 动态内存释放函数 freedmalloc(DMEM8U *dmp,DMEM8U dmsize) *********************/
//该函数把起始地址为dmp的空间(大小为dmsize)从堆栈中释放。
//入口参数;dmsize是需要释放的空间大小,以DMEM8U为单位。
//          dmp指针指向需要释放空间的起始地址.
//出口参数: 返回MEM_DELETE --- 内存空间释放成功.
//          返回NO_MEM_DEL --- 试图释放不存在的内存空间.
DMEM8U freedmalloc(DMEM8U *dmp,DMEM8U dmsize);

主文件 : dmalloc51.c

/*
*********************************************************************************************************
*                     C51内部RAM动态申请函数 ,动态释放函数
*                      (c) Copyright 2004.6, LM7556,China
*                            All Rights Reserved
*
*
* 文件 : dmalloc51.c
*********************************************************************************************************
*/

#include    "dmalloc51.h"
sfr SP    = 0x81;

/************* 动态内存申请函数DMEM8U *dmalloc(DMEM8U dmsize,StkSize) *********************/
//动态内存申请函数DMEM8U *dmalloc(DMEM8U dmsize,StkSize)从RAM堆栈中开辟一段空间做变量区.
//该函数把堆栈SP向上移动dmsize字节空间,再返回指向该空间起始地址的指针,
//入口参数;dmsize是需要分配的空间大小,以DMEM8U为单位。
//          StkSize 需要给CPU预留的堆栈空间.
//出口参数: 返回 STACK_OVER --- CPU内部RAM堆栈溢出,分配的空间不存在.
//            如果成功则返回一个指针,该指针指向所分配空间(大小为dmsize)的起始地址。
DMEM8U *dmalloc(DMEM8U dmsize,StkSize)
{DMEM8U *p1,*p2,spbuf; unsigned int StkChk;

    StkChk=SP+dmsize+StkSize;
    if (StkChk>(RAM_SIZE-1)) {return MEM_OVER;}    //检查要申请的内存是否存在.
    spbuf=SP;
    spbuf-=CPU_PCLEN;
    p1=(DMEM8U*)spbuf;
    p2=p1+dmsize;
    spbuf=(DMEM8U)p2+CPU_PCLEN;
    SP=spbuf;
//把上一级函数的返回地址移到该空间的上面,使本函数自己在执行完后可以正确的返回到上一级函数.
    p1++;p2++;
    *p2++=*p1++;
    *p2=*p1;
    p1--;
    return p1;
}

/************ 动态内存释放函数 freedmalloc(DMEM8U *dmp,DMEM8U dmsize) *********************/
//动态内存释放函数DMEM8U freedmalloc(DMEM8U *dmp,DMEM8U dmsize)把动态内存分配的空间从堆栈中释放。
//该函数把起始地址为dmp的空间(大小为dmsize)从堆栈中释放。
//入口参数;dmsize是需要释放的空间大小,以DMEM8U为单位。
//          dmp指针指向需要释放空间的起始地址.
//出口参数: 返回MEM_DELETE --- 内存空间释放成功.
//          返回NO_MEM_DEL --- 试图释放不存在的内存空间.
DMEM8U freedmalloc(DMEM8U *dmp,DMEM8U dmsize)
{DMEM8U *p1,*p2,spbuf,i;

    spbuf=(DMEM8U)dmp+dmsize;
    if (spbuf<=(DMEM8U)dmp) {return NO_MEM_DEL;}
    if (spbuf>SP-CPU_PCLEN) {spbuf=SP-CPU_PCLEN;}
    i=SP-spbuf;
    p1=(DMEM8U*)spbuf;
    p1++;
    p2=dmp;
    spbuf=(SP-spbuf)+p2;
    spbuf--;
    while (i)
    {
        *p2++=*p1++;    //把上一级函数的返回地址移到该空间的底部,使程序可以返回到上一级函数.
        i--;
    }
    SP=spbuf;
    return MEM_DELETED;
}

  应用范例:

文件 : main.c

#include    <reg52.h>
#include    <stdio.h>
#include    <intrins.h>

#define STACK_SIZE 0x30    //为程序预留的最小堆栈.
#include    "dmalloc51.h"

void initsio(void);
void TDelay(unsigned int t);

void Fn_dRamA(void);
void Fn_dRamB(void);
void Fn_dRamC(void);

void main(void)
{
    initsio();
    while (1)
    {
        TDelay(500);
        Fn_dRamA();
        printf("\n");
        TDelay(500);
        Fn_dRamB();
        printf("\n");
        TDelay(500);
        Fn_dRamC();
        printf("\n");
    }
}

#define dmSIZE_A 0x20
void Fn_dRamA(void)
{unsigned char i,*mp,*mpp;
    if ((mpp=dmalloc(dmSIZE_A,STACK_SIZE))==MEM_OVER) {return;};
    mp=mpp;
    for (i=0;i<dmSIZE_A-1;i++)
    {
        *mp++=i+0x20;
    }
    *mp=0;
    printf(mpp);
    printf("\n");
    Fn_dRamB();
    freedmalloc(mpp,dmSIZE_A);    //后面加nop()为了防止c51把freedmalloc(mpp)做ljmp 调用。
    _nop_();
}

#define dmSIZE_B 0x20
void Fn_dRamB(void)
{unsigned char i,*mp,*mpp;
    if ((mpp=dmalloc(dmSIZE_B,STACK_SIZE))==MEM_OVER) {return;};
    mp=mpp;
    for (i=0;i<dmSIZE_B-1;i++)
    {
        *mp++=i+0x40;
    }
    *mp=0;
    printf(mpp);
    printf("\n");
    Fn_dRamC();
    freedmalloc(mpp,dmSIZE_B);    //后面加nop()为了防止c51把freedmalloc(mpp)做ljmp 调用。
    _nop_();
}

#define dmSIZE_C 0x20
void Fn_dRamC(void)
{unsigned char i,*mp,*mpp;

    if ((mpp=dmalloc(dmSIZE_C,STACK_SIZE))==MEM_OVER) {return;};
    mp=mpp;
    for (i=0;i<dmSIZE_C-1;i++)
    {
        *mp++=i+0x60;
    }
    *mp=0;
    printf(mpp);
    printf("\n");
    freedmalloc(mpp,dmSIZE_C);    //后面加nop()为了防止c51把freedmalloc(mpp)做ljmp 调用。
    _nop_();
}

void TDelay(unsigned int t)
{unsigned int i,j;
    for (i=0;i<t;i++)
    {
        for (j=0;j<t;j++) {}
    }
}

void initsio(void)
{
   TMOD=TMOD&0x0F;
   TMOD=TMOD|0x20;
   TL1=0xFD,TH1=0xFD;//19200 , 22.1184MHz
   SCON=0x50;PCON=0x00;
   TR1=1;
   TI    = 1;                  /* TI:   set TI to send first char of UART    */
}
时间: 2024-08-29 14:41:31

keil c51的内部RAM(idata)动态内存管理程序(转)的相关文章

keil程序在外部RAM中调试的问题总结(个人的一点经验总结)

keil程序在内部RAM调试的基本步骤网上已经有很多了,我就不再赘述,大家可以在网上搜到很多. 但是有些时候内部RAM并不够用,这就需要将程序装入外部RAM中调试,而在这个过程中可能会出现各种各样的问题,在这里我将会把我遇到过的一些问题和需要注意的地方总结一下,希望能够对大家有所帮助. 有错误的地方也希望大神们能够不吝赐教,提前表示感谢··· 转载请注明出处:waitig's blog 先介绍下我项目使用的硬件,芯片是LPC1788,外部RAM是MT48LC4M32B2,大小为16M(128Mb

Keil C51里关于堆栈指针的处理

Keil C是非常优秀的C51编译器,可能是最好的C51编译器,提供各种优化模式,对变量的优化和地址安排做得非常好.这是用C语言写代码的好处之一,如果用汇编写,得费一大番功夫给各个变量安排内存物理地址,还得时刻记住哪些地址的内存单元是已经分配了,新增加的变量就不能占用那些已经分配了的单元,以免产生内存交叠冲突和溢出.我一直非常信赖Keil C51的编译结果,在我的印象里,它对内存的分配是完美的,只要代码用它编译时没有报告任何warning和error,代码运行时不可能内存冲突或溢出的现象.但,今

KEIL C51中const和code的使用

code是KEIL C51 扩展的关键字,用code修饰的变量将会被放到CODE区里.但C语里的const关键字好像也有定义不能改变的变量的功能,这两个关键字有什么区别呢?在帮助手册里查找const,可以找到以下的描述1 Variables declared with the const type qualifier alone are stored in the memory area (data, idata, xdata, and so on) associated with their

[51单片机] Keil C51中变量的使用方法详解

引言    8051内核单片机是一种通用单片机,在国内占有较大的市场份额.在将C语言用于51内核单片机的研究方面,Keil公司做得最为成功.由于51内核单片机的存储结构的特殊性,Keil C51中变量的使用与标准C有所不同.正确地使用变量,有利于获得高效的目标代码.下面详细介绍Keil C51中变量的使用方法. 1 CPU存储结构与变量的关系    变量都需要有存储空间,存储空间的不同使得变量使用时的工作效率也不同.    标准C的典型运行环境是8086(含IA-32系列)内核,其存储结构是CP

FreeRTOS 动态内存管理

本章节为大家讲解 FreeRTOS 动态内存管理,动态内存管理是 FreeRTOS 非常重要的一项功能,前面章节讲解的任务创建. 信号量. 消息队列. 事件标志组. 互斥信号量. 软件定时器组等需要的 RAM 空间都是通过动态内存管理从 FreeRTOSConfig.h 文件定义的 heap 空间中申请的. 动态内存管理介绍FreeRTOS 支持 5 种动态内存管理方案,分别通过文件 heap_1,heap_2,heap_3,heap_4 和 heap_5实现,这 5 个文件在 FreeRTOS

C++ Primer笔记8_动态内存_智能指针

1.动态内存 C++中,动态内存管理是通过一对运算符完成的:new和delete.C语言中通过malloc与free函数来实现先动态内存的分配与释放.C++中new与delete的实现其实会调用malloc与free. new分配: 分配变量空间: int *a = new int; // 不初始化 int *b = new int(10); //初始化为10 string *str = new string(10, ); 分配数组空间: int *arr = new int[10];//分配的

【C语言天天练(九)】动态内存分配

引言:数组的元素存储于内存中连续的位置上.当一个数组被声明时.它所须要的内存在编译时就被分配. 可是,我们能够使用动态内存分配在执行时为它分配内存. 一块内存的生命周期能够分为四个阶段:分配.初始化.使用.释放. 内存的分配一般使用C函数库里的malloc函数(原型:void *malloc(size_t size)). 关于malloc函数应该注意一下几点: 1.malloc的參数就是须要分配的内存的字节数. 2.malloc所分配的是一块连续的内存. 3.分配成功.则返回指向分配内存起始地址

SQLite剖析之动态内存分配

SQLite通过动态内存分配来获取各种对象(例如数据库连接和SQL预处理语句)所需内存.建立数据库文件的内存Cache.以及保存查询结果.我们做了很多努力来让SQLite的动态内存分配子系统可靠.可预测.健壮并且高效.本文概述SQLite的动态内存分配,软件开发人员在使用SQLite时可以据此获得最佳性能. 1.特性    SQLite内核和它的内存分配子系统提供以下特性:    (1)对内存分配失败的健壮处理.如果一个内存分配请求失败(即malloc()或realloc()返回NULL),SQ

iOS开发之c语言基础Lesson-10 动态内存管理 上课笔记 与 试题练习

//函数声明 int max(int a, int b); char * getString(); int main(int argc, const char * argv[]) { //////////////////Lesson 10 动态内存管理 课堂笔记 和 练习 ///////复习上周所学 /////////常量和变量的区别: //常量中的内容不能被修改,只能访问: //变量中存储的数据时可以随时修改的. // //const 关键字的作用: 修饰变量不可改变.当做常量使用 //  c