你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。
chrome
firefox
safari
ie8及以上
ST
意法半导体官网
STM32
中文官网
ST
全球论坛
登录/注册
首页
技术问答
话题
资源
创客秀
视频
标签
每日签到
STM32团队2
论坛吐槽优化专区
升级测试
ST意法半导体中文论坛
»
论坛
›
【技术区】
›
ST开发工具
›
【HAL库每天一例】第042例:FSMC-扩展SRAM内存管理 ...
返回列表
查看:
991
|
回复:
1
【HAL库每天一例】第042例:FSMC-扩展SRAM内存管理
[复制链接]
haohao663
haohao663
当前离线
在线时间
498 小时
UID
331315
ST金币
0
蝴蝶豆
0
注册时间
2015-6-4
122
主题
129
回帖
0
蝴蝶豆
论坛元老
最后登录
2019-5-28
收听TA
发消息
发表于 2016-6-16 08:44:40
|
显示全部楼层
|
阅读模式
a4a.1 32b0c
【HAL库每天一例】系列例程从今天开始持续更新。。。。。
我们将坚持每天至少发布一个基于YS-F1Pro开发板的HAL库例程,
该系列例程将带领大家从零开始使用HAL库,后面会持续添加模块应用例程。
同样的,我们还程序发布基于HAL库的
指导文档和视频教程
,欢迎持续关注,并提出改进意见。
例程下载:
资料包括程序、相关说明资料以及软件使用截图
YSF1_HAL-042. FSMC-扩展SRAM内存管理.zip
(4.88 MB, 下载次数: 24)
2016-6-16 08:44 上传
点击文件名下载附件
/**
******************************************************************************
* 硬石YS-F1Pro开发板例程功能说明
*
* 例程名称: YSF1_HAL-042. FSMC-扩展SRAM内存管理
*
******************************************************************************
* 说明:
* 本例程配套硬石stm32开发板YS-F1Pro使用。
* 版权归硬石嵌入式开发团队所有,请勿商用。
******************************************************************************
*/
【1】例程简介
FSMC:可变静态存储控制器,是STM32系列采用的一种新型的存储器扩展技术。
RAM在单片机作用类似与电脑的内存。STM32F106ZET6内部有64KB大小的RAM,对应一般工程程序
是足够使用的,但如果需要运行类似STemWin支持的界面设计就显得有点捉襟见肘,我们可以外部扩
展SRAM。
YS-F1Pro开发板板载1M字节的扩展SRAM,本例程增加动态内存管理驱动,这样提高内存的使用率。
【2】跳线帽情况
******* 为保证例程正常运行,必须插入以下跳线帽 **********
丝印编号 IO端口 目标功能引脚 出厂默认设置
JP1 PA10 TXD(CH340G) 已接入
JP2 PA9 RXD(CH340G) 已接入
【3】操作及现象
使用开发板配套的MINI USB线连接到开发板标示“调试串口”字样的MIMI USB接口(需要安装驱动),
在电脑端打开串口调试助手工具,设置参数为115200 8-N-1。下载完程序之后,在串口调试助手窗口
可接收到信息。
/******************* (C) COPYRIGHT 2015-2020 硬石嵌入式开发团队 *****END OF FILE****/
bsp_malloc.h文件内容
#ifndef __BSP_MALLOC_H__
#define __BSP_MALLOC_H__
/* 包含头文件 ----------------------------------------------------------------*/
#include "stm32f1xx_hal.h"
/* 宏定义 --------------------------------------------------------------------*/
#ifndef NULL
#define NULL 0
#endif
//定义两个内存池
#define SRAMIN 0 //内部内存池
#define SRAMEX 1 //外部内存池
#define SRAMBANK 2 //定义支持的SRAM块数.
//mem1内存参数设定.mem1完全处于内部SRAM里面.
#define MEM1_BLOCK_SIZE 32 //内存块大小为32字节
#define MEM1_MAX_SIZE 40*1024 //最大管理内存 40K
#define MEM1_ALLOC_TABLE_SIZE MEM1_MAX_SIZE/MEM1_BLOCK_SIZE //内存表大小
//mem2内存参数设定.mem2的内存池处于外部SRAM里面
#define MEM2_BLOCK_SIZE 32 //内存块大小为32字节
#define MEM2_MAX_SIZE 928*1024 //最大管理内存960K
#define MEM2_ALLOC_TABLE_SIZE MEM2_MAX_SIZE/MEM2_BLOCK_SIZE //内存表大小
/* 类型定义 ------------------------------------------------------------------*/
//内存管理控制器
struct _m_mallco_dev
{
void ( * init ) ( uint8_t ); //初始化
uint8_t ( * perused ) ( uint8_t ); //内存使用率
uint8_t * membase [ SRAMBANK ]; //内存池 管理SRAMBANK个区域的内存
uint16_t * memmap [ SRAMBANK ]; //内存管理状态表
uint8_t memrdy [ SRAMBANK ]; //内存管理是否就绪
};
/* 扩展变量 ------------------------------------------------------------------*/
extern struct _m_mallco_dev mallco_dev; //在mallco.c里面定义
/* 函数声明 ------------------------------------------------------------------*/
void mymemset(void *s,uint8_t c,uint32_t count); //设置内存
void mymemcpy(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); //内存释放(内部调用)
uint8_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 /* __BSP_MALLOC_H__ */
/*************************************** 硬石嵌入式开发团队 *****END OF FILE****/
复制代码
bsp_malloc.c文件内容
/**
******************************************************************************
* 文件名程: bsp_malloc.c
* 作 者: 硬石嵌入式开发团队
* 版 本: V1.0
* 编写日期: 2015-10-04
* 功 能: 动态内存分配管理实现
******************************************************************************
* 说明:
* 本例程配套硬石stm32开发板YS-F1Pro使用。
*
* 淘宝:
* 论坛:http://www.ing10bbs.com
*
******************************************************************************
*/
/* 包含头文件 ----------------------------------------------------------------*/
#include "malloc/bsp_malloc.h"
#include "exSRAM/bsp_exSRAM.h"
/* 私有宏定义 ----------------------------------------------------------------*/
/* 私有变量 ------------------------------------------------------------------*/
#if defined ( __CC_ARM ) // 使用Keil编译环境
//内存池(4字节对齐)
__align(4) uint8_t mem1base[MEM1_MAX_SIZE]; //内部SRAM内存池
__align(4) uint8_t mem2base[MEM2_MAX_SIZE] __attribute__((at(EXSRAM_BANK_ADDR))); //外部SRAM内存池
//内存管理表
uint16_t mem1mapbase[MEM1_ALLOC_TABLE_SIZE]; //内部SRAM内存池MAP
uint16_t mem2mapbase[MEM2_ALLOC_TABLE_SIZE] __attribute__((at(EXSRAM_BANK_ADDR+MEM2_MAX_SIZE))); //外部SRAM内存池MAP
#elif defined ( __ICCARM__ ) // 使用IAR编译环境
//内存池(4字节对齐)
#pragma pack(4)
uint8_t mem1base[MEM1_MAX_SIZE]; //内部SRAM内存池
#pragma location=EXSRAM_BANK_ADDR
#pragma pack(4)
uint8_t mem2base[MEM2_MAX_SIZE]; //外部SRAM内存池
//内存管理表
uint16_t mem1mapbase[MEM1_ALLOC_TABLE_SIZE]; //内部SRAM内存池MAP
#pragma location=(EXSRAM_BANK_ADDR+MEM2_MAX_SIZE)
uint16_t mem2mapbase[MEM2_ALLOC_TABLE_SIZE]; //外部SRAM内存池MAP
#endif
//内存管理参数
const uint32_t memtblsize[SRAMBANK]={MEM1_ALLOC_TABLE_SIZE,MEM2_ALLOC_TABLE_SIZE}; //内存表大小
const uint32_t memblksize[SRAMBANK]={MEM1_BLOCK_SIZE,MEM2_BLOCK_SIZE}; //内存分块大小
const uint32_t memsize[SRAMBANK]={MEM1_MAX_SIZE,MEM2_MAX_SIZE}; //内存总大小
/* 私有类型定义 --------------------------------------------------------------*/
//内存管理控制器
struct _m_mallco_dev mallco_dev=
{
my_mem_init, //内存初始化
my_mem_perused, //内存使用率
mem1base,mem2base, //内存池
mem1mapbase,mem2mapbase, //内存管理状态表
0,0, //内存管理未就绪
};
/* 扩展变量 ------------------------------------------------------------------*/
/* 私有函数原形 --------------------------------------------------------------*/
/* 函数体 --------------------------------------------------------------------*/
//复制内存
//*des:目的地址
//*src:源地址
//n:需要复制的内存长度(字节为单位)
void mymemcpy(void *des,void *src,uint32_t n)
{
uint8_t *xdes=des;
uint8_t *xsrc=src;
while(n--)*xdes++=*xsrc++;
}
//设置内存
//*s:内存首地址
//c :要设置的值
//count:需要设置的内存大小(字节为单位)
void mymemset(void *s,uint8_t c,uint32_t count)
{
uint8_t *xs = s;
while(count--)*xs++=c;
}
//内存管理初始化
//memx:所属内存块
void my_mem_init(uint8_t memx)
{
mymemset(mallco_dev.memmap[memx], 0,memtblsize[memx]*2);//内存状态表数据清零
mymemset(mallco_dev.membase[memx], 0,memsize[memx]); //内存池所有数据清零
mallco_dev.memrdy[memx]=1; //内存管理初始化OK
}
//获取内存使用率
//memx:所属内存块
//返回值:使用率(0~100)
uint8_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*100)/(memtblsize[memx]);
}
//内存分配(内部调用)
//memx:所属内存块
//size:要分配的内存大小(字节)
//返回值: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;//未找到符合分配条件的内存块
}
//释放内存(内部调用)
//memx:所属内存块
//offset:内存地址偏移
//返回值:0,释放成功;1,释放失败;
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;//偏移超区了.
}
//释放内存(外部调用)
//memx:所属内存块
//ptr:内存首地址
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); //释放内存
}
//分配内存(外部调用)
//memx:所属内存块
//size:内存大小(字节)
//返回值:分配到的内存首地址.
void *mymalloc(uint8_t memx,uint32_t size)
{
uint32_t offset;
offset=my_mem_malloc(memx,size);
if(offset==0XFFFFFFFF)return NULL;
else return (void*)((uint32_t)mallco_dev.membase[memx]+offset);
}
//重新分配内存(外部调用)
//memx:所属内存块
//*ptr:旧内存首地址
//size:要分配的内存大小(字节)
//返回值:新分配到的内存首地址.
void *myrealloc(uint8_t memx,void *ptr,uint32_t size)
{
uint32_t offset;
offset=my_mem_malloc(memx,size);
if(offset==0XFFFFFFFF)return NULL;
else
{
mymemcpy((void*)((uint32_t)mallco_dev.membase[memx]+offset),ptr,size); //拷贝旧内存内容到新内存
myfree(memx,ptr); //释放旧内存
return (void*)((uint32_t)mallco_dev.membase[memx]+offset); //返回新内存首地址
}
}
/***************************************硬石嵌入式开发团队 *****END OF FILE****/
复制代码
回复
使用道具
举报
Ian-392967
Ian-392967
当前离线
在线时间
22 小时
UID
392967
ST金币
0
蝴蝶豆
0
注册时间
2015-1-11
0
主题
153
回帖
0
蝴蝶豆
中级会员
中级会员, 积分 392, 距离下一级还需 108 积分
最后登录
2020-1-5
收听TA
发消息
发表于 2016-7-2 06:58:42
|
显示全部楼层
a1024a.1 32b0c
谢谢分享!
回复
支持
反对
使用道具
举报
返回列表
关于
意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
微信公众号
手机版
快速回复
返回顶部
返回列表