历史上的今天
返回首页

历史上的今天

今天是:2024年12月17日(星期二)

正在发生

2020年12月17日 | STM32F7xx —— 内存管理

2020-12-17 来源:eefocus

目的:高效、快速的分配,并在适当的时候回收内存资源。最终就是实现malloc和free函数。(实现方法参考原子哥)


#define CONFIG_SRAM_OUT_ENABLE     0

 

typedef enum

{

  SRAM_TYPE_IN,   // 内部内存池

#if(CONFIG_SRAM_OUT_ENABLE == 1)

  SRAM_YPE_OUT,   // 外部内存池(SDRAM)

#endif

  SRAM_TYPE_DTCM, // DTCM内存池(此部分SRAM仅仅CPU可以访问!!!)

  SRAM_TYPE_MAX,  // 最多支持的SRAM块数.

} sram_type_t;

 

// 内部SRAM

#define SRAM_IN_BLOCK_SIZE        64            // 内存块大小为64字节

#define SRAM_IN_MAX_SIZE          (160 * 1024)  // 最大管理内存160K

#define SRAM_IN_ALLOC_TABLE_SIZE  (SRAM_IN_MAX_SIZE / SRAM_IN_BLOCK_SIZE)

 

#if(CONFIG_SRAM_OUT_ENABLE == 1)

// 外部SDRAM里面

#define SRAM_OUT_BLOCK_SIZE       64            // 内存块大小为64字节

#define SRAM_OUT_MAX_SIZE         (100 *1024)   // 最大管理内存100K

#define SRAM_OUT_ALLOC_TABLE_SIZE (SRAM_OUT_MAX_SIZE / SRAM_OUT_BLOCK_SIZE)

#endif

 

// CCM,用于管理DTCM(特别注意,这部分SRAM,仅CPU可以访问!!)

#define SRAM_DTCM_BLOCK_SIZE      64                  //内存块大小为64字节

#define SRAM_DTCM_MAX_SIZE        (100 *1024)             //最大管理内存60K

#define SRAM_DTCM_ALLOC_TABLE_SIZE  (SRAM_DTCM_MAX_SIZE/SRAM_DTCM_BLOCK_SIZE)

//内存池(32字节对齐)

__align(32) uint8_t sram_in_base[SRAM_IN_MAX_SIZE];                                      // 内部SRAM内存池

uint32_t sram_in_map_base[SRAM_IN_ALLOC_TABLE_SIZE];

 

#if(CONFIG_SRAM_OUT_ENABLE == 1)

__align(32) uint8_t sram_out_base[SRAM_OUT_MAX_SIZE] __attribute__((at(0xC01F4000)));   // 外部SDRAM内存池

uint32_t sram_out_map_base[SRAM_OUT_ALLOC_TABLE_SIZE] __attribute__((at(0xC01F4000 + SRAM_OUT_MAX_SIZE))); // 外部SRAM内存池MAP

#endif

 

__align(32) uint8_t sram_dtcm_base[SRAM_DTCM_MAX_SIZE] __attribute__((at(0x20000000))); // 内部DTCM内存池

uint32_t sram_dtcm_map_base[SRAM_DTCM_ALLOC_TABLE_SIZE] __attribute__((at(0x20000000 + SRAM_DTCM_MAX_SIZE))); //内部DTCM内存池MAP

 

static const uint32_t memtblsize[SRAM_TYPE_MAX] = {SRAM_IN_ALLOC_TABLE_SIZE,

#if(CONFIG_SRAM_OUT_ENABLE == 1)

                                            SRAM_OUT_ALLOC_TABLE_SIZE,

#endif

                                            SRAM_DTCM_ALLOC_TABLE_SIZE

                                           }; //内存表大小

 

static const uint32_t memblksize[SRAM_TYPE_MAX] = {SRAM_IN_BLOCK_SIZE,

#if(CONFIG_SRAM_OUT_ENABLE == 1)

                                            SRAM_OUT_BLOCK_SIZE,

#endif

                                            SRAM_DTCM_BLOCK_SIZE

                                           };     //内存分块大小

 

static const uint32_t memsize[SRAM_TYPE_MAX] = {SRAM_IN_MAX_SIZE,

#if(CONFIG_SRAM_OUT_ENABLE == 1)

                                         SRAM_OUT_MAX_SIZE,

#endif

                                         SRAM_DTCM_MAX_SIZE

                                        };          //内存总大小

 

void mymem_init(uint8_t type);

uint16_t mymem_perused(uint8_t type);

 

typedef struct

{

void (* init)(uint8_t );

uint16_t (* perused)(uint8_t); // 内存使用率

uint8_t *membase[SRAM_TYPE_MAX]; // 内存池 管理SRAMBANK个区域的内存

uint32_t *memmap[SRAM_TYPE_MAX]; // 内存管理状态表

uint8_t  memrdy[SRAM_TYPE_MAX];    // 内存管理是否就绪

} sram_dev_t;

 

//内存管理控制器

static sram_dev_t sram_dev =

{

  mymem_init,        // 内存初始化

  mymem_perused,     // 内存使用率

  sram_in_base,

 

#if(CONFIG_SRAM_OUT_ENABLE == 1)

  sram_out_base,

#endif

  sram_dtcm_base,  // 内存池

  sram_in_map_base,

#if(CONFIG_SRAM_OUT_ENABLE == 1)

  sram_out_map_base,

#endif

  sram_dtcm_map_base,

  0,

#if(CONFIG_SRAM_OUT_ENABLE == 1)

  0,

#endif

  0,

};

 

// 内存管理初始化

static void mymem_init(uint8_t memx)

{

  memset(sram_dev.memmap[memx], 0, memtblsize[memx] * 4); // 内存状态表数据清零

  sram_dev.memrdy[memx] = 1;                              // 内存管理初始化OK

}

 

// 获取内存使用率

// type:所属内存块

// 返回值:使用率(扩大了10倍,0~1000,代表0.0%~100.0%)

static uint16_t mymem_perused(uint8_t type)

{

  uint32_t used = 0;

  uint32_t i;

  for(i = 0; i < memtblsize[type]; ++i)

  {

    if(sram_dev.memmap[type][i])

    {

      used++;

    }

  }

  return (used * 1000) / (memtblsize[type]);

}

 

// 内存分配(内部调用)

// type:所属内存块

// size:要分配的内存大小(字节)

// 返回值:0XFFFFFFFF,代表错误;其他,内存偏移地址

static uint32_t mymem_malloc(uint8_t type, uint32_t size)

{

  signed long offset = 0;

  uint32_t nmemb;     // 需要的内存块数

  uint32_t cmemb = 0; // 连续空内存块数

  uint32_t i;

 

  if(!sram_dev.memrdy[type])

  {

    sram_dev.init(type);  // 未初始化,先执行初始化

  }

  if(size == 0)

  {

    return 0xFFFFFFFF;  // 不需要分配

  }

  nmemb = size / memblksize[type]; // 获取需要分配的连续内存块数

  if(size % memblksize[type])

  {

    nmemb++;

  }

  for(offset = memtblsize[type] - 1; offset >= 0; offset--) // 搜索整个内存控制区

  {

    if(!sram_dev.memmap[type][offset])

    {

      cmemb++;    // 连续空内存块数增加

    }

    else

    {

      cmemb = 0;  // 连续内存块清零

    }

    if(cmemb == nmemb)                // 找到了连续nmemb个空内存块

    {

      for(i = 0; i < nmemb; i++)      // 标注内存块非空

      {

        sram_dev.memmap[type][offset + i] = nmemb;

      }

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

    }

  }

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

}

 

// 释放内存(内部调用)

// type:所属内存块

// offset:内存地址偏移

// 返回值:0,释放成功;1,释放失败;

static uint8_t mymem_free(uint8_t type, uint32_t offset)

{

  int i;

  if(!sram_dev.memrdy[type])// 未初始化,先执行初始化

  {

    sram_dev.init(type);

    return 1;// 未初始化

  }

  if(offset < memsize[type]) // 偏移在内存池内.

  {

    int index = offset / memblksize[type];    // 偏移所在内存块号码

    int nmemb = sram_dev.memmap[type][index]; // 内存块数量

    for(i = 0; i < nmemb; i++)                // 内存块清零

    {

      sram_dev.memmap[type][index + i] = 0;

    }

    return 0;

  }

  else

  {

    return 2;  // 偏移超区了.

  }

}

 

void MemInit(uint8_t type)

{

  memset(sram_dev.memmap[type], 0, memtblsize[type] * 4); // 内存状态表数据清零

  sram_dev.memrdy[type] = 1;              // 内存管理初始化OK

}

 

// 释放内存(外部调用)

// type:所属内存块

// ptr:内存首地址

void MemFree(uint8_t type, void *ptr)

{

  uint32_t offset;

  if(ptr == NULL)

  {

    return;  // 地址为0.

  }

  offset = (uint32_t)ptr - (uint32_t)sram_dev.membase[type];

  mymem_free(type, offset); // 释放内存

}

 

// 分配内存

void *MemAlloc(uint8_t type, uint32_t size)

{

  uint32_t offset;

  offset = mymem_malloc(type, size);

  if(offset == 0XFFFFFFFF)

  {

    return NULL;

  }

  else

  {

    return (void*)((uint32_t)sram_dev.membase[type] + offset);

  }

}

 

// 重新分配内存

void *MemRealloc(uint8_t type, void *ptr, uint32_t size)

{

  uint32_t offset;

  offset = mymem_malloc(type, size);

  if(offset == 0xFFFFFFFF)

  {

    return NULL;

  }

  else

  {

    memcpy((void*)((uint32_t)sram_dev.membase[type] + offset), ptr, size); // 拷贝旧内存内容到新内存

    MemFree(type, ptr);                                                     // 释放旧内存

    return (void*)((uint32_t)sram_dev.membase[type] + offset);              // 返回新内存首地址

  }

}


推荐阅读

史海拾趣

ZTE高新兴(Gosuncn)公司的发展小趣事

对于J-107B型高频双头式热合机电路,网友可能提出的问题及回答如下:

问题一:J-107B型高频双头式热合机的主要工作原理是什么?

回答:J-107B型高频双头式热合机的主要工作原理是利用高频电场作用于塑料材料,使其内部分子发生极化现象,并在高频电场的快速变化下,这些被极化的分子以同样极快的速度跟随变化,从而因介电损耗产生大量的热量。这些热量聚集并达到高温,使塑料材料熔化。在熔化状态下,通过施加一定的压力,可以使两块或多块塑料熔合粘结在一起,实现高频热合的目的。

问题二:J-107B型高频双头式热合机的电路结构有哪些主要部分?

回答:J-107B型高频双头式热合机的电路结构主要包括以下几个主要部分:

  1. 高频振荡电路:这是热合机的核心部分,通常由电子管(如Fu-33中功率发射电子管)组成,用于产生高频电场。电子管通过自激振荡方式工作,利用电子管的授间电容作振荡回路的主电窖,组成考毕兹振荡器。

  2. 时间控制电路:用于控制热合的时间,通常由电子管(如6P6P电子管)和时间控制元件(如RP1和RP2调节器)组成。通过调整这些元件,可以精确地控制热合过程中的各个阶段时间,如预热时间、熔合时间和冷却时间。

  3. 电源电路:为整个热合机提供稳定的电源供应,确保高频振荡电路和时间控制电路的正常工作。电源电路需要满足一定的电压和电流要求,通常要求电源电压在190~230V范围内。

  4. 保护电路:为了防止电路过载、短路等异常情况的发生,热合机还配备了保护电路。这些电路能够在检测到异常情况时迅速切断电源,保护设备和操作人员的安全。

问题三:如何维护和保养J-107B型高频双头式热合机?

回答:为了保持J-107B型高频双头式热合机的良好性能和延长使用寿命,需要进行定期的维护和保养。以下是一些建议:

  1. 定期检查电源线和插头:确保它们没有损坏或松动,避免电源问题导致的故障。

  2. 清洁机器内部:定期清理机器内部的灰尘和杂物,保持机器内部的清洁和干燥。这有助于防止电子元件因灰尘积累而损坏。

  3. 检查电子元件:定期检查高频振荡电路和时间控制电路中的电子元件是否损坏或老化。如有需要,应及时更换以确保电路的正常工作。

  4. 调整和维护模具:模具是热合机的关键部件之一,需要定期进行调整和维护。确保模具的接合位置准确、平整,避免模具损坏导致的热合质量下降。

  5. 注意安全操作:在操作过程中,应注意安全用电和防火措施。避免在潮湿或腐蚀性气体环境下使用热合机,以防止触电或设备损坏。

  6. 定期校准:对于需要精确控制时间或温度的热合机,应定期进行校准以确保其准确性。这有助于提高热合质量和生产效率。

富之光(Fujicon)公司的发展小趣事

自成立以来,富致科技始终秉持创新精神,不断投入研发,引进美国最新的PPTC技术,并结合海内外技术专家的智慧,成功开发出多款高性能的自复式保险丝产品。这些产品凭借其出色的安全性能、稳定性和可靠性,迅速在市场上获得了认可。同时,富致科技积极拓展国内外市场,与众多知名企业和行业伙伴建立了长期稳定的合作关系,进一步巩固了其在PPTC保险丝领域的领先地位。

EDI [Electronic devices inc.]公司的发展小趣事

随着科技的进步,Eclipse Magnetics公司开始关注航空航天领域的需求。他们发现,在复杂的航空系统中,精确的磁性控制至关重要。于是,公司投入大量研发资源,成功开发出一系列高性能的磁性产品,为航空航天领域提供了可靠的解决方案。这一突破不仅巩固了Eclipse Magnetics在电子行业中的地位,还为公司赢得了众多知名客户的信任。

Exel Microelectronics Inc公司的发展小趣事

随着全球对环保问题的日益关注,Exel Microsystems Inc公司也积极响应,履行环保责任。公司在XXXX年开始实施绿色生产战略,通过采用环保材料、优化生产流程等措施,降低了生产过程中的能耗和废弃物排放。此外,Exel还积极参与环保公益活动,推动行业和社会的可持续发展。这些举措不仅彰显了公司的社会责任感,也为公司赢得了良好的社会声誉。

HALO Electronics公司的发展小趣事

XXXX年,Exel Microsystems Inc公司意识到了品质管理对于企业发展的重要性。于是,公司开始引进先进的品质管理理念和体系,加强了对产品从研发到生产的全过程控制。通过严格的品质管理,Exel的产品质量得到了显著提升,客户满意度也随之提高。这一举措不仅增强了公司的市场竞争力,也为公司的长期发展奠定了坚实基础。

长工微电子公司的发展小趣事

为了进一步拓展市场,长工微电子积极寻求战略合作。近期,长工微电子与世强先进(深圳)科技股份有限公司签署战略合作协议,授权世强先进全线代理其旗下电源管理IC、开关转换器、多相控制器、降压电源模块、电子保险丝等产品。这一合作有助于长工微电子更好地满足客户需求,提高市场占有率。

问答坊 | AI 解惑

BU 72435 ROHM热卖

本帖最后由 jameswangsynnex 于 2015-3-3 20:01 编辑 我们大量ROHM BU72435库存价格好,有需求请和我联系。 陈庭松 13138889236 …

查看全部问答>

有关无线技术的一些标准(一)

请想象一下,当您乔迁新居,要将电器的电源插头插进墙上插座里去,结果却发现根本不能匹配时是什么感受。应该感谢几十年之前设立的电气标准,发生这种事情的可能性已经很少了。其他还有一些标准也在为我们服务,比如我们可以跟与不同网络服务商打交 ...…

查看全部问答>

Windows CE中的命令提示行的和PC机上的XP中的有啥区别?

网上说:     Windows CE和Windows XP Embedded存在诸多本质区别。首先,Windows CE是一款全32位、Unicode操作系统,它不支持MS-DOS或Windows 3.x应用。         这里说的MS-DOS不就是台式机上的命令提示行中DOS ...…

查看全部问答>

wince ADC驱动请教。

我想实现在wince液晶上 显示采样信号波形。波形频率很低。 肯定要包括ADC驱动,和应用程序 第一个问题:我想要ADC每隔500ms采样一次,用中断来实现。这个500ms中断在驱动中如何实现? 第二个问题:应用程序获取AD结果可以使用流驱动接口,但是读 ...…

查看全部问答>

串口通讯中的DCB结构

串口通讯中的DCB结构 我看很多程序,它里面使用了BCD结构,但是BCD结果不是在winbase.h中定义的吗, 程序里面并没有#include \"winbase.h\",但是编译确实成功的,为什么? 我是学了VC现在学EVC,觉得有点困扰,EVC很多库函数都不一样了,怎么找 ...…

查看全部问答>

WINCE中文显示的问题

以下我做了不同平台的测试 第一个平台是Default language为中文(中国) 第二个平台是Default language为英语(英文) 第三个平台是Default language为英语(英文),并加入MUI多国语言的支持. 应用程序代码如下: char   cTest[]  & ...…

查看全部问答>

bootloader中的一些问题

小弟关于bootloader中有几个问题不清楚,麻烦兄弟们帮忙解释下, 1,其中涉及到内存映射,它的作用是什么? 2,cpu又是如何区分flash和ram的地址呢,难到有控制flash和ram地址的寄存器吗? 3,如果flash的os要加载到ram中执行,又是如何实现拷贝的呢,如 ...…

查看全部问答>

关于嵌入式系统开发的经验

各位同道中人,欢迎各位谈谈自己入门的经验以及推荐一些好的资料,作为LZ,先为大家献上一点啦! 现面有几个不错的网站 ,仅供参考 http://162.105.146.27/cgi-bin/ftp_search?BeginWith=208&FType=255&word=Linux http://linux.ubuntu.org. ...…

查看全部问答>

急求Lcd 中“-”的编码?

急求Lcd 中“-”的编码? 顺便问下Lcd中是怎样进行汉字编码的!…

查看全部问答>

大四学生请教:毕设被安排做lm3s9b92的以太网通讯功能

在下大四学生,之前在学校只接触过很浅的嵌入式知识,现在毕业设计被安排在一公司参加一个项目,要实现一块板子的以太网通讯功能,板子应该是arm cortex m3核心,lm3s9b92的型号,我要实现的功能是将温度、液位等数据通过以太网接口传给计算机,我 ...…

查看全部问答>