正點原子內存管理學習和修改

????????由于項目需要用到內存管理進行動態申請和釋放,今天又重新學習了一下正點原子的內存管理實驗,溫習了一下內存管理的實質。首先先上正點原子內存管理的源代碼:

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.pswp.cn/diannao/74287.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/74287.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/74287.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

時空觀測者:俯身拾貝

目錄 中華文明時空貝殼集&#xff08;按時間排序&#xff09;1. 良渚玉琮&#xff08;約公元前3300-2300年&#xff09;2. 三星堆青銅神樹&#xff08;公元前1200年&#xff09;3. 殷墟甲骨文&#xff08;約公元前14世紀&#xff09;4. 京杭大運河&#xff08;公元前486年始建&…

護網期間監測工作全解析:內容與應對策略

護網期間監測工作全解析&#xff1a;內容與應對策略 一、引言 在數字化浪潮中&#xff0c;網絡安全的重要性愈發凸顯&#xff0c;護網行動作為保障關鍵信息基礎設施安全的關鍵舉措&#xff0c;備受矚目。護網期間&#xff0c;監測工作是發現潛在威脅、防范攻擊的重要防線。全…

【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;與當今的極簡主義設計方法完美契合。無論是用于鮮明的構圖還是…

Spring Boot(十七):集成和使用Redis

Redis(Remote Dictionary Server,遠程字典服務器)是一個開源的、基于內存的數據結構存儲系統,它可以用作數據庫、緩存和消息中間件。Spring Boot 中集成和使用Redis主要涉及以下幾個步驟: 添加依賴 在項目的pom.xml文件中添加Redis的依賴。Spring Boot提供了對Redis的集…

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…

為WordPress自定義一個留言板

要在WordPress中創建一個留言反饋表單&#xff0c;并實現后臺管理功能&#xff0c;您可以按照以下步驟進行操作&#xff1a; 1. 創建留言反饋表單 首先&#xff0c;您需要使用一個表單插件來創建表單。推薦使用 Contact Form 7 或 WPForms。以下是使用 Contact Form 7 的示例…

嵌入式項目:利用心知天氣獲取天氣數據實驗方案

【實驗目的】 1、利用心知天氣服務器獲取指定位置天氣數據 2、將天氣數據解析并可視化顯示到OLED屏幕 【實驗原理】 【實驗步驟】 官網注冊

go-zero學習筆記

內容不多&#xff0c;只有部分筆記&#xff0c;剩下的沒有繼續學下去&#xff0c;包括路由與處理器、日志中間件、請求上下文 文章目錄 1、go-zero核心庫1.1 路由與處理器1.2 日志中間件1.3 請求上下文 1、go-zero核心庫 1.1 路由與處理器 package mainimport ("github…

【Go】Go語言繼承-多態模擬

繼承&#xff08;結構體嵌入&#xff09;多態&#xff08;接口實現和空接口&#xff09; 1. 繼承&#xff08;結構體嵌入&#xff09; Go 語言沒有傳統的面向對象的繼承機制&#xff0c;但可以通過“結構體嵌入”實現類似繼承的效果。 結構體嵌入&#xff1a;在結構體中嵌入另…

kotlin知識體系(四) : inline、noinline、crossinline 關鍵字對應編譯后的代碼是怎樣的 ?

kotlin中inline、noinline、crossinline 關鍵字的作用 在 Kotlin 里&#xff0c;inline、noinline 和 crossinline 這幾個關鍵字和高階函數緊密相關&#xff0c;它們能夠對高階函數的行為進行優化和控制。下面為你詳細闡述它們的作用和原理。 inline 關鍵字 inline 關鍵字用…

LabVIEW FPGA與Windows平臺數據濾波處理對比

LabVIEW在FPGA和Windows平臺均可實現數據濾波處理&#xff0c;但兩者的底層架構、資源限制、實時性及應用場景差異顯著。FPGA側重硬件級并行處理&#xff0c;適用于高實時性場景&#xff1b;Windows依賴軟件算法&#xff0c;適合復雜數據處理與可視化。本文結合具體案例&#x…

深度解析 Android Matrix 變換(二):組合變換 pre、post

前言 在上一篇文章中&#xff0c;我們講解了 Canvas 中單個變換的原理和效果&#xff0c;即縮放、旋轉和平移。但是單個旋轉僅僅是基礎&#xff0c;Canvas 變換最重要的是能夠隨意組合各種變換以實現想要的效果。在這種情況下&#xff0c;就需要了解如何組合變換&#xff0c;以…

Java并發編程之CountDownLatch

1. 基本原理 計數器 CountDownLatch 在創建時需要指定一個初始計數值。這個值通常代表需要等待完成的任務數或線程數。 等待與遞減 等待&#xff1a;調用 await() 方法的線程會被阻塞&#xff0c;直到計數器變為 0。遞減&#xff1a;每當一個任務完成后&#xff0c;應調用 cou…

C++|GLog開源庫的使用 如何實現自定義類型消息日志

參考&#xff1a; C glog使用教程與代碼演示 C第三方日志庫Glog的安裝與使用超詳解 GLOG從入門到入門 glog 設置日志級別_glog C版本代碼分析 文章目錄 日志等級自定義消息創建使用宏定義 日志等級 在 glog 中&#xff0c;日志的嚴重性是通過 LogSeverity 來區分的&#xff0c…

FAQ - VMware vSphere Web 控制臺中鼠標控制不了怎么辦?

問題描述 在VMware vSphere vCenter Server 的 Web 控制臺中新建了一臺 Windows Server 2008 R2 虛擬機&#xff0c;但是鼠標進入控制臺后&#xff0c;可以看見鼠標光標&#xff0c;但是移動卻沒有反應。 根因分析 暫無。 解決方案 選中虛擬機>操作>編輯設置>添加新…

Rust+WebAssembly:開啟瀏覽器3D渲染新時代

引言 在當今的 Web 開發領域&#xff0c;隨著用戶對網頁交互體驗的要求日益提高&#xff0c;3D 渲染技術在 Web 應用中的應用愈發廣泛。從沉浸式的 Web 游戲&#xff0c;到逼真的虛擬展示場景&#xff0c;3D 渲染引擎承擔著將虛擬 3D 世界呈現到用戶瀏覽器中的關鍵任務。其性能…

在小米AX6000中添加tailscale monitor

經過測試&#xff0c;發現小米路由器中的tailscale可能會因為某種原因狀態異常&#xff0c; 為了讓tailscale恢復正常&#xff0c;所以又寫了monitor用來監控&#xff1a; #!/bin/sh# Define Tailscale related paths TAILSCALED_PATH"/tmp/tailscale/tailscale_1.80.3_a…

表達式括號匹配(stack)(信息學奧賽一本通-1353)

【題目描述】 假設一個表達式有英文字母&#xff08;小寫&#xff09;、運算符&#xff08;&#xff0c;—&#xff0c;?&#xff0c;/&#xff09;和左右小&#xff08;圓&#xff09;括號構成&#xff0c;以“ ”作為表達式的結束符。請編寫一個程序檢查表達式中的左右圓括號…

IM 基于 WebRtc 視頻通信功能

IM&#xff08;即時通訊&#xff09;基于 WebRTC&#xff08;Web Real-Time Communication&#xff0c;網頁實時通訊&#xff09; 原理 WebRTC 是一種支持網頁瀏覽器進行實時語音通話或視頻通話的技術&#xff0c;它提供了一組 JavaScript API&#xff0c;使得在瀏覽器之間無…