当前位置: 首页 > news >正文

正点原子内存管理学习和修改

        由于项目需要用到内存管理进行动态申请和释放,今天又重新学习了一下正点原子的内存管理实验,温习了一下内存管理的实质。首先先上正点原子内存管理的源代码:

malloc.c文件:

#include "./MALLOC/malloc.h"

#if !(__ARMCC_VERSION >= 6010050)   /* 不是AC6编译器,即使用AC5编译器时 */

/* 内存池(32字节对齐) */
static __align(32) uint8_t mem1base[MEM1_MAX_SIZE];                                                           /* 内部SRAM内存池 */
static __align(32) uint8_t mem2base[MEM2_MAX_SIZE] __attribute__((at(0X10000000)));                           /* 内部CCM内存池 */
static __align(32) uint8_t mem3base[MEM3_MAX_SIZE] __attribute__((at(0XC01F4000)));                           /* 外部SDRAM内存池,前面2M给LTDC用了(1280*800*2) */

/* 内存管理表 */
static MT_TYPE mem1mapbase[MEM1_ALLOC_TABLE_SIZE];                                                            /* 内部SRAM内存池MAP */
static MT_TYPE mem2mapbase[MEM2_ALLOC_TABLE_SIZE] __attribute__((at(0X10000000 + MEM2_MAX_SIZE)));            /* 内部CCM内存池MAP */
static MT_TYPE mem3mapbase[MEM3_ALLOC_TABLE_SIZE] __attribute__((at(0XC01F4000 + MEM3_MAX_SIZE)));            /* 外部SRAM内存池MAP */

#else      /* 使用AC6编译器时 */

/* 内存池(32字节对齐) */
static __ALIGNED(32) uint8_t mem1base[MEM1_MAX_SIZE];                                                         /* 内部SRAM内存池 */
static __ALIGNED(32) uint8_t mem2base[MEM2_MAX_SIZE] __attribute__((section(".bss.ARM.__at_0X10000000")));    /* 内部CCM内存池 */
static __ALIGNED(32) uint8_t mem3base[MEM3_MAX_SIZE] __attribute__((section(".bss.ARM.__at_0XC01F4000")));    /* 外部SDRAM内存池,前面2M给LTDC用了(1280*800*2) */

/* 内存管理表 */
static MT_TYPE mem1mapbase[MEM1_ALLOC_TABLE_SIZE];                                                            /* 内部SRAM内存池MAP */
static MT_TYPE mem2mapbase[MEM2_ALLOC_TABLE_SIZE] __attribute__((section(".bss.ARM.__at_0X1000F000")));       /* 内部CCM内存池MAP */
static MT_TYPE mem3mapbase[MEM3_ALLOC_TABLE_SIZE] __attribute__((section(".bss.ARM.__at_0XC1E30000")));       /* 外部SRAM内存池MAP */

#endif

/* 内存管理参数 */
const uint32_t memtblsize[SRAMBANK] = {MEM1_ALLOC_TABLE_SIZE, MEM2_ALLOC_TABLE_SIZE, MEM3_ALLOC_TABLE_SIZE};  /* 内存表大小 */
const uint32_t memblksize[SRAMBANK] = {MEM1_BLOCK_SIZE, MEM2_BLOCK_SIZE, MEM3_BLOCK_SIZE};                    /* 内存分块大小 */
const uint32_t memsize[SRAMBANK] = {MEM1_MAX_SIZE, MEM2_MAX_SIZE, MEM3_MAX_SIZE};                             /* 内存总大小 */

/* 内存管理控制器 */
struct _m_mallco_dev mallco_dev=
{
  my_mem_init,                                /* 内存初始化 */
  my_mem_perused,                             /* 内存使用率 */
  mem1base, mem2base, mem3base,               /* 内存池 */
  mem1mapbase, mem2mapbase, mem3mapbase,      /* 内存管理状态表 */
  0, 0, 0,                                    /* 内存管理未就绪 */
};

/**
 * @brief       复制内存
 * @param       *des : 目的地址
 * @param       *src : 源地址
 * @param       n    : 需要复制的内存长度(字节为单位)
 * @retval      无
 */
void my_mem_copy(void *des, void *src, uint32_t n)  
{  
    uint8_t *xdes = des;
    uint8_t *xsrc = src; 
    while (n--)*xdes++ = *xsrc++;  
}  

/**
 * @brief       设置内存值
 * @param       *s    : 内存首地址
 * @param       c     : 要设置的值
 * @param       count : 需要设置的内存大小(字节为单位)
 * @retval      无
 */
void my_mem_set(void *s, uint8_t c, uint32_t count)  
{  
    uint8_t *xs = s;  
    while (count--)*xs++ = c;  
}  

/**
 * @brief       内存管理初始化
 * @param       memx : 所属内存块
 * @retval      无
 */
void my_mem_init(uint8_t memx)  
{  
    my_mem_set(mallco_dev.memmap[memx], 0, memtblsize[memx] * 4);  /* 内存状态表数据清零 */
    mallco_dev.memrdy[memx] = 1;                                   /* 内存管理初始化OK */
}

/**
 * @brief       获取内存使用率
 * @param       memx : 所属内存块
 * @retval      使用率(扩大了10倍,0~1000,代表0.0%~100.0%)
 */
uint16_t my_mem_perused(uint8_t memx)  
{  
    uint32_t used = 0;  
    uint32_t i;

    for (i = 0; i < memtblsize[memx]; i++)  
    {
        if (mallco_dev.memmap[memx][i])
        {
            used++;
        }
    }

    return (used * 1000) / (memtblsize[memx]);  
}

/**
 * @brief       内存分配(内部调用)
 * @param       memx : 所属内存块
 * @param       size : 要分配的内存大小(字节)
 * @retval      内存偏移地址
 *   @arg       0 ~ 0xFFFFFFFE : 有效的内存偏移地址
 *   @arg       0xFFFFFFFF     : 无效的内存偏移地址
 */
uint32_t my_mem_malloc(uint8_t memx, uint32_t size)  
{  
    signed long offset = 0;  
    uint32_t nmemb;                                             /* 需要的内存块数 */
    uint32_t cmemb = 0;                                         /* 连续空内存块数 */
    uint32_t i;

    if (!mallco_dev.memrdy[memx])
    {
        mallco_dev.init(memx);                                  /* 未初始化,先执行初始化 */
    }
    if (size == 0) 
    {
        return 0XFFFFFFFF;                           /* 不需要分配 */
    }
    nmemb = size / memblksize[memx];                            /* 获取需要分配的连续内存块数 */

    if (size % memblksize[memx])
    {
        nmemb++;
    }

    for (offset = memtblsize[memx] - 1; offset >= 0; offset--)   /* 搜索整个内存控制区 */
    {
        if (!mallco_dev.memmap[memx][offset])
        {
            cmemb++;                                            /* 连续空内存块数增加 */
        }
        else 
        {
            cmemb = 0;                                          /* 连续内存块清零 */
        }

        if (cmemb == nmemb)                                     /* 找到了连续nmemb个空内存块 */
        {
            for (i = 0;i < nmemb; i++)                          /* 标注内存块非空  */
            {  
                mallco_dev.memmap[memx][offset + i] = nmemb;  
            }

            return (offset * memblksize[memx]);                 /* 返回偏移地址  */
        }
    }

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

/**
 * @brief       释放内存(内部调用)
 * @param       memx   : 所属内存块
 * @param       offset : 内存地址偏移
 * @retval      释放结果
 *   @arg       0, 释放成功;
 *   @arg       1, 释放失败;
 *   @arg       2, 超区域了(失败);
 */
uint8_t my_mem_free(uint8_t memx, uint32_t offset)
{
    int i;

    if (!mallco_dev.memrdy[memx])                   /* 未初始化,先执行初始化 */
    {
        mallco_dev.init(memx);
        return 1;                                   /* 未初始化 */
    }

    if (offset < memsize[memx])                     /* 偏移在内存池内. */
    {
        int index = offset / memblksize[memx];      /* 偏移所在内存块号码 */
        int nmemb = mallco_dev.memmap[memx][index]; /* 内存块数量 */

        for (i = 0; i < nmemb; i++)                 /* 内存块清零 */
        {
            mallco_dev.memmap[memx][index + i] = 0;
        }

        return 0;
    }
    else
    {
        return 2;                                  /* 偏移超区了. */
    }
}

/**
 * @brief       释放内存(外部调用)
 * @param       memx : 所属内存块
 * @param       ptr  : 内存首地址
 * @retval      无
 */
void myfree(uint8_t memx, void *ptr)
{
    uint32_t offset;

    if (ptr == NULL)return;     /* 地址为0. */

    offset = (uint32_t)ptr - (uint32_t)mallco_dev.membase[memx];
    my_mem_free(memx, offset);  /* 释放内存 */
}

/**
 * @brief       分配内存(外部调用)
 * @param       memx : 所属内存块
 * @param       size : 要分配的内存大小(字节)
 * @retval      分配到的内存首地址.
 */
void *mymalloc(uint8_t memx, uint32_t size)
{
    uint32_t offset;
    offset = my_mem_malloc(memx, size);

    if (offset == 0xFFFFFFFF)   /* 申请出错 */
    {
        return NULL;            /* 返回空(0) */
    }
    else                        /* 申请没问题, 返回首地址 */
    {
        return (void *)((uint32_t)mallco_dev.membase[memx] + offset);
    }
}

/**
 * @brief       重新分配内存(外部调用)
 * @param       memx : 所属内存块
 * @param       *ptr : 旧内存首地址
 * @param       size : 要分配的内存大小(字节)
 * @retval      新分配到的内存首地址.
 */
void *myrealloc(uint8_t memx, void *ptr, uint32_t size)
{
    uint32_t offset;
    offset = my_mem_malloc(memx, size);

    if (offset == 0xFFFFFFFF)                                                          /* 申请出错 */
    {
        return NULL;                                                                   /* 返回空(0) */
    }
    else                                                                               /* 申请没问题, 返回首地址 */
    {
        my_mem_copy((void *)((uint32_t)mallco_dev.membase[memx] + offset), ptr, size); /* 拷贝旧内存内容到新内存 */
        myfree(memx, ptr);                                                             /* 释放旧内存 */
        return (void *)((uint32_t)mallco_dev.membase[memx] + offset);                  /* 返回新内存首地址 */
    }
}

malloc.h文件:

#ifndef __MALLOC_H
#define __MALLOC_H

#include "./SYSTEM/sys/sys.h"


#ifndef NULL
#define NULL 0
#endif

/* 定义三个内存池 */
#define SRAMIN                  0                               /* 内部内存池 */
#define SRAMCCM                 1                               /* CCM内存池(此部分SRAM仅仅CPU可以访问!!!) */
#define SRAMEX                  2                               /* 外部内存池(SDRAM) */

/* 定义内存管理表类型,当外扩SDRAM的时候,必须使用uint32_t类型,否则可以定义成uint16_t,以节省内存占用 */
#define MT_TYPE     uint32_t

#define SRAMBANK                3                               /* 定义支持的SRAM块数. */


/* mem1内存参数设定.mem1完全处于内部SRAM里面. */
#define MEM1_BLOCK_SIZE         64                              /* 内存块大小为64字节 */
#define MEM1_MAX_SIZE          160 * 1024                       /* 最大管理内存 160K */
#define MEM1_ALLOC_TABLE_SIZE  MEM1_MAX_SIZE / MEM1_BLOCK_SIZE  /* 内存表大小 */
     
/* mem2内存参数设定.mem2处于CCM,用于管理CCM(特别注意,这部分SRAM,仅CPU可以访问!!) */
#define MEM2_BLOCK_SIZE         64                              /* 内存块大小为64字节 */
#define MEM2_MAX_SIZE           60 * 1024                       /* 最大管理内存60K */
#define MEM2_ALLOC_TABLE_SIZE   MEM2_MAX_SIZE / MEM2_BLOCK_SIZE /* 内存表大小 */
     
/* mem3内存参数设定.mem3的内存池处于外部SDRAM里面 */
#define MEM3_BLOCK_SIZE         64                              /* 内存块大小为64字节 */
#define MEM3_MAX_SIZE           28912 * 1024                    /* 最大管理内存28912K */
#define MEM3_ALLOC_TABLE_SIZE   MEM3_MAX_SIZE / MEM3_BLOCK_SIZE /* 内存表大小 */

/* 内存管理控制器 */
struct _m_mallco_dev
{
    void (*init)(uint8_t);              /* 初始化 */
    uint16_t (*perused)(uint8_t);       /* 内存使用率 */
    uint8_t *membase[SRAMBANK];         /* 内存池 管理SRAMBANK个区域的内存 */
    uint32_t *memmap[SRAMBANK];         /* 内存管理状态表 */
    uint8_t  memrdy[SRAMBANK];          /* 内存管理是否就绪 */
};

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

/******************************************************************************************/

void my_mem_set(void *s, uint8_t c, uint32_t count);            /* 设置内存 */
void my_mem_copy(void *des, void *src, uint32_t n);             /* 复制内存 */
void my_mem_init(uint8_t memx);                                 /* 内存管理初始化函数(外/内部调用) */
uint32_t my_mem_malloc(uint8_t memx, uint32_t size);            /* 内存分配(内部调用) */
uint8_t my_mem_free(uint8_t memx, uint32_t offset);             /* 内存释放(内部调用) */
uint16_t my_mem_perused(uint8_t memx) ;                         /* 获得内存使用率(外/内部调用)  */

/* 用户调用函数 */
void myfree(uint8_t memx, void *ptr);                           /* 内存释放(外部调用) */
void *mymalloc(uint8_t memx, uint32_t size);                    /* 内存分配(外部调用) */
void *myrealloc(uint8_t memx, void *ptr, uint32_t size);        /* 重新分配内存(外部调用) */

#endif

对于单个内存池来说在移植的时候只需要修改以下内容:

        malloc.h文件中的:内存块大小宏定义(MEMx_BLOCK_SIZE)、内存池大小宏定义(MEMx_MAX_SIZE)、内存管理表单个元素的大小(MT_TYPE),通过这三个参即可得到内存管理表元素的个数。

        malloc.c文件中需要修改的是:内存池的对其方式[__align(32)]、内存池的指定地址[__attribute__((at(0XC0000000)))],修改了这两个参数就能保证内存池的定义不会出错。

        对于内存管理的移植除了需要修改单个内存池的定义信息外还需要修改内存池的数量(SRAMBANK)、内存池的编号(#define SRAMIN      0 ;#define SRAMCCM      1  ;#define SRAMEX     2    ),同时还需要修改内存管理控制器结构体的参数(mallco_dev)。

从上面可以看出正点原子这份代码是基于“保证内存池的大小”的角度进行定义的,换句话说我是指定了了内存池的大小,但是没有指定整个内存池和内存管理表的大小,所以可以换一种方式进行定义:指定单个内存池全部的大小,然后自己程序自己去计算block的数量,这样就可以保证单个内存池所占用的内存不会超过指定的大小,修改如下:

/* mem1内存参数设定.mem1完全处于内部SRAM里面. */
#define MEM1_TOTAL_SIZE         64*1024 		/* 内部SRAM大小为64K字节 */
#define MEM1_BLOCK_SIZE         64                  /* 内存块大小为64字节 */
#define MEM1_ALLOC_TABLE_NUM    MEM1_TOTAL_SIZE/(MEM1_BLOCK_SIZE+sizeof(MT_TYPE)) /* block的数量=内存管理表的数量*/
#define MEM1_MAX_SIZE			MEM1_ALLOC_TABLE_NUM*MEM1_BLOCK_SIZE	/* 内存池的大小为:block的大小*数量 */

/* mem2内存参数设定.mem2处于CCM,用于管理CCM(特别注意,这部分SRAM,仅CPU可以访问!!) */
#define MEM2_TOTAL_SIZE         64*1024 		/* CCM大小为64K字节 */
#define MEM2_BLOCK_SIZE         64                  /* 内存块大小为64字节 */
#define MEM2_ALLOC_TABLE_NUM    MEM2_TOTAL_SIZE/(MEM2_BLOCK_SIZE+sizeof(MT_TYPE)) /* block的数量=内存管理表的数量*/
#define MEM2_MAX_SIZE			MEM2_ALLOC_TABLE_NUM*MEM2_BLOCK_SIZE	/* 内存池的大小为:block的大小*数量 */

/* mem3内存参数设定.mem3的内存池处于外部SDRAM里面 */
#define MEM3_TOTAL_SIZE         32*1024*1024 		/* SDRAM大小为32M字节 */
#define MEM3_BLOCK_SIZE         64                  /* 内存块大小为64字节 */
#define MEM3_ALLOC_TABLE_NUM    MEM3_TOTAL_SIZE/(MEM3_BLOCK_SIZE+sizeof(MT_TYPE)) /* block的数量=内存管理表的数量*/
#define MEM3_MAX_SIZE			MEM3_ALLOC_TABLE_NUM*MEM3_BLOCK_SIZE	/* 内存池的大小为:block的大小*数量 */

最后再附上单独管理SDRAM的测试代码:

malloc.c源代码


#include "malloc.h"

/* 内存池(32字节对齐) */
static __align(32) uint8_t mem3base[MEM3_MAX_SIZE] __attribute__((at(0XC0000000)));                           /* 外部SDRAM内存池  SDRAM起始地址:0XC0000000*/

/* 内存管理表 */
static MT_TYPE mem3mapbase[MEM3_ALLOC_TABLE_NUM] __attribute__((at(0XC0000000 + MEM3_MAX_SIZE)));            /* 外部SRAM内存池MAP */


/* 内存管理参数 */
const uint32_t memtblsize[SRAMBANK] = {MEM3_ALLOC_TABLE_NUM};   			 /* 内存表数量 */
const uint32_t memblksize[SRAMBANK] = {MEM3_BLOCK_SIZE};                   	 /* 单个block大小 */
const uint32_t memsize[SRAMBANK] = {MEM3_MAX_SIZE};                             /* 每个内存池的大小 */

/* 内存管理控制器 */
struct _m_mallco_dev mallco_dev=
{
  my_mem_init,                                /* 内存初始化 */
  my_mem_perused,                             /* 内存使用率 */
  mem3base,             					  /* 内存池 */
  mem3mapbase,     							/* 内存管理状态表 */
  0,                                   	  /* 内存管理未就绪 */
};

/**
 * @brief       复制内存
 * @param       *des : 目的地址
 * @param       *src : 源地址
 * @param       n    : 需要复制的内存长度(字节为单位)
 * @retval      无
 */
void my_mem_copy(void *des, void *src, uint32_t n)  
{  
    uint8_t *xdes = des;
    uint8_t *xsrc = src; 
    while (n--)*xdes++ = *xsrc++;  
}  

/**
 * @brief       设置内存值
 * @param       *s    : 内存首地址
 * @param       c     : 要设置的值
 * @param       count : 需要设置的内存大小(字节为单位)
 * @retval      无
 */
void my_mem_set(void *s, uint8_t c, uint32_t count)  
{  
    uint8_t *xs = s;  
    while (count--)*xs++ = c;  
}  

/**
 * @brief       内存管理初始化
 * @param       memx : 所属内存块
 * @retval      无
 */
void my_mem_init(uint8_t memx)  
{  
    my_mem_set(mallco_dev.memmap[memx], 0, memtblsize[memx] * 4);  /* 内存状态表数据清零 */
    mallco_dev.memrdy[memx] = 1;                                   /* 内存管理初始化OK */
}

/**
 * @brief       获取内存使用率
 * @param       memx : 所属内存块
 * @retval      使用率(扩大了10倍,0~1000,代表0.0%~100.0%)
 */
uint16_t my_mem_perused(uint8_t memx)  
{  
    uint32_t used = 0;  
    uint32_t i;

    for (i = 0; i < memtblsize[memx]; i++)  
    {
        if (mallco_dev.memmap[memx][i])
        {
            used++;
        }
    }

    return (used * 1000) / (memtblsize[memx]);  
}

/**
 * @brief       内存分配(内部调用)
 * @param       memx : 所属内存块
 * @param       size : 要分配的内存大小(字节)
 * @retval      内存偏移地址
 *   @arg       0 ~ 0xFFFFFFFE : 有效的内存偏移地址
 *   @arg       0xFFFFFFFF     : 无效的内存偏移地址
 */
uint32_t my_mem_malloc(uint8_t memx, uint32_t size)  
{  
    signed long offset = 0;  
    uint32_t nmemb;                                             /* 需要的内存块数 */
    uint32_t cmemb = 0;                                         /* 连续空内存块数 */
    uint32_t i;

    if (!mallco_dev.memrdy[memx])
    {
        mallco_dev.init(memx);                                  /* 未初始化,先执行初始化 */
    }
    if (size == 0) 
    {
        return 0XFFFFFFFF;                           /* 不需要分配 */
    }
    nmemb = size / memblksize[memx];                            /* 获取需要分配的连续内存块数 */

    if (size % memblksize[memx])
    {
        nmemb++;
    }

    for (offset = memtblsize[memx] - 1; offset >= 0; offset--)   /* 搜索整个内存控制区 */
    {
        if (!mallco_dev.memmap[memx][offset])
        {
            cmemb++;                                            /* 连续空内存块数增加 */
        }
        else 
        {
            cmemb = 0;                                          /* 连续内存块清零 */
        }

        if (cmemb == nmemb)                                     /* 找到了连续nmemb个空内存块 */
        {
            for (i = 0;i < nmemb; i++)                          /* 标注内存块非空  */
            {  
                mallco_dev.memmap[memx][offset + i] = nmemb;  
            }

            return (offset * memblksize[memx]);                 /* 返回偏移地址  */
        }
    }

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

/**
 * @brief       释放内存(内部调用)
 * @param       memx   : 所属内存块
 * @param       offset : 内存地址偏移
 * @retval      释放结果
 *   @arg       0, 释放成功;
 *   @arg       1, 释放失败;
 *   @arg       2, 超区域了(失败);
 */
uint8_t my_mem_free(uint8_t memx, uint32_t offset)
{
    int i;

    if (!mallco_dev.memrdy[memx])                   /* 未初始化,先执行初始化 */
    {
        mallco_dev.init(memx);
        return 1;                                   /* 未初始化 */
    }

    if (offset < memsize[memx])                     /* 偏移在内存池内. */
    {
        int index = offset / memblksize[memx];      /* 偏移所在内存块号码 */
        int nmemb = mallco_dev.memmap[memx][index]; /* 内存块数量 */

        for (i = 0; i < nmemb; i++)                 /* 内存块清零 */
        {
            mallco_dev.memmap[memx][index + i] = 0;
        }

        return 0;
    }
    else
    {
        return 2;                                  /* 偏移超区了. */
    }
}

/**
 * @brief       释放内存(外部调用)
 * @param       memx : 所属内存块
 * @param       ptr  : 内存首地址
 * @retval      无
 */
void myfree(uint8_t memx, void *ptr)
{
    uint32_t offset;

    if (ptr == NULL)return;     /* 地址为0. */

    offset = (uint32_t)ptr - (uint32_t)mallco_dev.membase[memx];
    my_mem_free(memx, offset);  /* 释放内存 */
}

/**
 * @brief       分配内存(外部调用)
 * @param       memx : 所属内存块
 * @param       size : 要分配的内存大小(字节)
 * @retval      分配到的内存首地址.
 */
void *mymalloc(uint8_t memx, uint32_t size)
{
    uint32_t offset;
    offset = my_mem_malloc(memx, size);

    if (offset == 0xFFFFFFFF)   /* 申请出错 */
    {
        return NULL;            /* 返回空(0) */
    }
    else                        /* 申请没问题, 返回首地址 */
    {
        return (void *)((uint32_t)mallco_dev.membase[memx] + offset);
    }
}

/**
 * @brief       重新分配内存(外部调用)
 * @param       memx : 所属内存块
 * @param       *ptr : 旧内存首地址
 * @param       size : 要分配的内存大小(字节)
 * @retval      新分配到的内存首地址.
 */
void *myrealloc(uint8_t memx, void *ptr, uint32_t size)
{
    uint32_t offset;
    offset = my_mem_malloc(memx, size);

    if (offset == 0xFFFFFFFF)                                                          /* 申请出错 */
    {
        return NULL;                                                                   /* 返回空(0) */
    }
    else                                                                               /* 申请没问题, 返回首地址 */
    {
        my_mem_copy((void *)((uint32_t)mallco_dev.membase[memx] + offset), ptr, size); /* 拷贝旧内存内容到新内存 */
        myfree(memx, ptr);                                                             /* 释放旧内存 */
        return (void *)((uint32_t)mallco_dev.membase[memx] + offset);                  /* 返回新内存首地址 */
    }
}

malloc.h源代码

#ifndef __MALLOC_H
#define __MALLOC_H

#include "main.h"


#ifndef NULL
#define NULL 0
#endif

/* 定义三个内存池 */
#define SRAMEX                  0                               /* 外部内存池(SDRAM) */

/* 定义内存管理表类型,当外扩SDRAM的时候,必须使用uint32_t类型,否则可以定义成uint16_t,以节省内存占用 */
#define MT_TYPE     uint32_t

#define SRAMBANK                1                               /* 定义支持的SRAM块数. */

#define MEM3_TOTAL_SIZE         32*1024*1024																			/* SDRAM大小为32M字节 */
#define MEM3_BLOCK_SIZE         64                              									/* 内存块大小为64字节 */
#define MEM3_ALLOC_TABLE_NUM    MEM3_TOTAL_SIZE/(MEM3_BLOCK_SIZE+sizeof(MT_TYPE)) /* block的数量=内存管理表的数量*/
#define MEM3_MAX_SIZE						MEM3_ALLOC_TABLE_NUM*MEM3_BLOCK_SIZE							/* 内存池的大小为:block的大小*数量 */



/* 内存管理控制器 */
struct _m_mallco_dev
{
    void (*init)(uint8_t);              /* 初始化 */
    uint16_t (*perused)(uint8_t);       /* 内存使用率 */
    uint8_t *membase[SRAMBANK];         /* 内存池 管理SRAMBANK个区域的内存 */
    uint32_t *memmap[SRAMBANK];         /* 内存管理状态表 */
    uint8_t  memrdy[SRAMBANK];          /* 内存管理是否就绪 */
};

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

/******************************************************************************************/

void my_mem_set(void *s, uint8_t c, uint32_t count);            /* 设置内存 */
void my_mem_copy(void *des, void *src, uint32_t n);             /* 复制内存 */
void my_mem_init(uint8_t memx);                                 /* 内存管理初始化函数(外/内部调用) */
uint32_t my_mem_malloc(uint8_t memx, uint32_t size);            /* 内存分配(内部调用) */
uint8_t my_mem_free(uint8_t memx, uint32_t offset);             /* 内存释放(内部调用) */
uint16_t my_mem_perused(uint8_t memx) ;                         /* 获得内存使用率(外/内部调用)  */

/* 用户调用函数 */
void myfree(uint8_t memx, void *ptr);                           /* 内存释放(外部调用) */
void *mymalloc(uint8_t memx, uint32_t size);                    /* 内存分配(外部调用) */
void *myrealloc(uint8_t memx, void *ptr, uint32_t size);        /* 重新分配内存(外部调用) */

#endif

main函数添加测试代码

char *str = 0;
mallco_dev.init(SRAMEX);
str = mymalloc(SRAMEX, 50);
if(str)
{
	sprintf(str, "012345678900123456789001234567890");
	HAL_Delay(10);//这里因为SDRAM的读写需要时间所以一定需要插入一点延时,不然串口无打印信息
	printf("%s\n",str);
	myfree(SRAMEX,str);
}

测试结果如下:

相关文章:

  • Linux深度解析运行级别管理
  • 自动插入分号机制
  • ElementUI el-menu导航开启vue-router模式
  • C语言 - 整数与浮点数运算的类型转换规则
  • 定时器(java)
  • Linux安装MySQL数据库并使用C语言进行数据库开发
  • 【从零实现Json-Rpc框架】- 项目设计篇
  • C语言指针(二)
  • 有哪一些解放生产力的AI工具【前端】
  • GAMES101-现代计算机图形学入门(Assignment5)
  • 练习:自动驾驶
  • Linux中的基本开发工具(上)
  • 系统与网络安全------网络应用基础(3)
  • 图解CNN、RNN、LSTM
  • 【杂谈】-人工智能驱动的编码:提升效率还是增加网络安全隐患?
  • c++ primer 阅读手记 第三章
  • js中async+await+promise的用法及常见问题总结
  • Linux多线程详解
  • Docker镜像相关命令(Day2)
  • 【大模型】数字人 EchoMimicV2 的环境配置和使用
  • 做设计找图片的网站/网站新站整站排名
  • 石家庄网站建设石家庄/网络推广外包想手机蛙软件
  • 怎么用vs做动态网站/seo优化网络推广
  • 自己做网站什么类型的比较好/百度关键词搜索排行
  • wordpress users/深圳外包seo
  • 如何加强企业网站建设 论文/网页怎么做