免费咨询医院/网站快速优化排名官网

免费咨询医院,网站快速优化排名官网,网站点击代码,上海品牌网站建设公司排名由于项目需要用到内存管理进行动态申请和释放,今天又重新学习了一下正点原子的内存管理实验,温习了一下内存管理的实质。首先先上正点原子内存管理的源代码: malloc.c文件: #include "./MALLOC/malloc.h"#if !(__ARMC…

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

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);        /* 重新分配内存(外部调用) */#endifmain函数添加测试代码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);
}

测试结果如下:

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

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

相关文章

【Centos7搭建Zabbix4.x监控HCL模拟网络设备:zabbix-server搭建及监控基础05

兰生幽谷&#xff0c;不为莫服而不芳&#xff1b; 君子行义&#xff0c;不为莫知而止休。 5.zabbix监控HCL模拟网络设备 在保证zabbix-server与HCL网络相通的情况下进行如下操作。 5.1创建主机群 配置-主机群-创建主机群 图 19 取名&#xff0c;添加。 图 20 5.2 创建监控…

趣味极简品牌海报艺术贴纸设计圆润边缘无衬线粗体装饰字体 Chunko Bold - Sans Serif Font

Chunko Bold 是一种功能强大的显示字体&#xff0c;体现了大胆极简主义的原则 – 当代设计的主流趋势。这种自信的字体将粗犷的几何形状与现代的趣味性相结合&#xff0c;具有圆润的边缘和强烈的存在感&#xff0c;与当今的极简主义设计方法完美契合。无论是用于鲜明的构图还是…

2025-03-21 Unity 序列化 —— 自定义2进制序列化

文章目录 前言1 项目结构1.1 整体1.2 代码 2 实现2.1 Processor2.1.1 BaseType2.1.2 CollectionType2.1.3 CustomType 2.2 ByteFormatter2.3 ByteHelper 3 使用 前言 ​ BinaryFormatter 类可以将 C# 类对象快速转换为字节数组数据。 ​ 在网络开发时&#xff0c;不会使用 Bi…

嵌入式项目:利用心知天气获取天气数据实验方案

【实验目的】 1、利用心知天气服务器获取指定位置天气数据 2、将天气数据解析并可视化显示到OLED屏幕 【实验原理】 【实验步骤】 官网注册

LabVIEW FPGA与Windows平台数据滤波处理对比

LabVIEW在FPGA和Windows平台均可实现数据滤波处理&#xff0c;但两者的底层架构、资源限制、实时性及应用场景差异显著。FPGA侧重硬件级并行处理&#xff0c;适用于高实时性场景&#xff1b;Windows依赖软件算法&#xff0c;适合复杂数据处理与可视化。本文结合具体案例&#x…

深度解析 Android Matrix 变换(二):组合变换 pre、post

前言 在上一篇文章中&#xff0c;我们讲解了 Canvas 中单个变换的原理和效果&#xff0c;即缩放、旋转和平移。但是单个旋转仅仅是基础&#xff0c;Canvas 变换最重要的是能够随意组合各种变换以实现想要的效果。在这种情况下&#xff0c;就需要了解如何组合变换&#xff0c;以…

FAQ - VMware vSphere Web 控制台中鼠标控制不了怎么办?

问题描述 在VMware vSphere vCenter Server 的 Web 控制台中新建了一台 Windows Server 2008 R2 虚拟机&#xff0c;但是鼠标进入控制台后&#xff0c;可以看见鼠标光标&#xff0c;但是移动却没有反应。 根因分析 暂无。 解决方案 选中虚拟机>操作>编辑设置>添加新…

关于极端场景下,数据库更新与 MQ 消息一致性保障方案的详细总结

目录 一、核心问题场景 二、RocketMQ 事务消息方案 1. 核心机制 2. 执行流程 3. 关键优势 4. 局限性 三、消息表方案 1. 核心机制 2. 执行流程 3. 关键优势 4. 局限性 四、方案对比与选择 五、实施建议 六、总结 一、核心问题场景 当数据库更新后,若 MQ 消息未…

【redis】主从复制:拓扑结构、原理和psync命令解析

文章目录 拓扑一主一从相关问题 一主多从相关问题 树形主从结构相关问题 主从复制原理复制流程 psync 命令命令解析replicatonidoffset总结 运行流程 拓扑 若干个节点之间按照什么样的方式来进行组织连接 一主一从 都可以读&#xff0c;从节点可以帮主节点分担一部分的压力只…

[RoarCTF 2019]Easy Calc-3.23BUUCTF练习day5(2)

[RoarCTF 2019]Easy Calc-3.23BUUCTF练习day5(2) 解题过程 查看源码 发现calc.php页面&#xff0c;访问一下 分析代码 首先获取$_GET[num]的值并赋给变量$str。然后定义了一个黑名单数组$blacklist&#xff0c;包含了一系列被禁止的字符或转义字符&#xff0c;如空格、制表…

阻塞队列:原理、应用及实现

阻塞队列&#xff1a;原理、应用及实现 什么是阻塞队列以生产消费者模型形象地理解阻塞队列阻塞队列实现生产消费者模型模拟实现阻塞队列实现生产消费者模型 什么是阻塞队列 阻塞队列是一种特殊且实用的队列数据结构&#xff0c;它同样遵循 “先进先出” 的原则。与普通队列不…

【开源宝藏】30天学会CSS - DAY5 第五课 脉冲动画

以下是一个完整的渐进式教程&#xff0c;拆解如何用 HTML CSS 构建“Pulsar”水波脉冲动画。通过阅读&#xff0c;你将理解每个核心属性与关键帧如何配合&#xff0c;让一个小圆不断散发动态波纹&#xff0c;并且文字始终停留在圆心。 第 0 步&#xff1a;项目概览 文件结构示…

2060 裁纸刀

2060 裁纸刀 ⭐️难度&#xff1a;简单 &#x1f31f;考点&#xff1a;2022、规律、思维 &#x1f4d6; &#x1f4da; import java.util.Arrays; import java.util.LinkedList; import java.util.Queue; import java.util.Scanner;public class Main {static int N 100010…

python学习笔记--实现简单的爬虫(一)

任务&#xff1a;爬取豆瓣最受欢迎的250个电影的资料 链接&#xff1a;豆瓣电影 Top 250 用浏览器打开后&#xff0c;使用F12或鼠标右键--检查&#xff0c;查看网页的源代码&#xff0c;分析网页结构&#xff0c;如下图所示&#xff1a; 分析后得知&#xff1a; 1.电影名位于…

Cursor+Claude-3.5生成Android app

一、Android Studio下载 https://developer.android.com/studio?hlzh-tw#get-android-studio 等待安装完成 二、新建工程 点击new project 选择Empty Activity 起一个工程名 当弹出这个框时 可以在settings里面选择No proxy 新建好后如下 点击右边模拟器&#xff0c…

Java EE(15)——网络原理——TCP协议解析一

一.确认应答/(确认)序列号 接收方接收到数据后&#xff0c;向发送方返回一个确认信号(ack)&#xff0c;告诉发送方数据被成功接收。ACK报文段只是作为确认使用的&#xff0c;一般来说不携带应用层数据&#xff08;载荷&#xff09;&#xff0c;也就是说只有报头部分。但有可能…

C#单例模式

单例模式 (Singleton),保证一个类仅有一个实例&#xff0c;并提供一个访问它的全局访问点。通常我们可以让一个全局变量使得一个对象被访问&#xff0c;但它不能防止你实例化对个对象&#xff0c;一个最好的办法就是&#xff0c;让类自身负责保护它的唯一实例。这个类可以保证没…

NO.55十六届蓝桥杯备战|排序|插入|选择|冒泡|堆|快速|归并(C++)

插⼊排序 插⼊排序(Insertion Sort)类似于玩扑克牌插牌过程&#xff0c;每次将⼀个待排序的元素按照其关键字⼤⼩插⼊到前⾯已排好序的序列中&#xff0c;按照该种⽅式将所有元素全部插⼊完成即可 #include <iostream> using namespace std; const int N 1e5 10; …

【Oracle资源损坏类故障】:详细了解坏块

目录 1、物理坏块与逻辑坏块 1.1、物理坏块 1.2、逻辑坏块 2、两个坏块相关的参数 2.1、db_block_checksum 2.2、db_block_checking 3、检测坏块 3.1、告警日志 3.2、RMAN 3.3、ANALYZE 3.4、数据字典 3.5、DBVERIFY 4、修复坏块 4.1、RMAN修复 4.2、DBMS_REPA…

计算机网络高频(二)TCP/IP基础

计算机网络高频(二)TCP/IP基础 1.什么是TCP/IP⭐⭐ TCP/IP是一种网络通信协议,它是互联网中最常用的协议之一。TCP/IP有两个基本的协议:TCP(传输控制协议)和IP(互联网协议)。 TCP(Transmission Control Protocol,传输控制协议)是一种可靠的、面向连接的协议。它负…