[STM32F1] 【HAL库每天一例】第042例: FSMC-扩展SRAM内存管理

[复制链接]
 楼主| 亼亽 发表于 2016-6-16 08:35 | 显示全部楼层 |阅读模式
【HAL库每天一例】系列例程从今天开始持续更新。。。。。
我们将**每天至少发布一个基于YS-F1Pro开发板的HAL库例程,
该系列例程将带领大家从零开始使用HAL库,后面会持续添加模块应用例程。
同样的,我们还程序发布基于HAL库的指导文档和视频教程,欢迎持续关注,并提出改进意见。
例程下载:
资料包括程序、相关说明资料以及软件使用截图
等级不够,不给发连接(去掉下面链接空格)
百度云:pan. baidu. com/s/1jIvrqlC
(硬石YS-F1Pro开发板HAL库例程持续更新\1. 软件设计之基本裸机例程(HAL库版本)\YSF1_HAL-042. FSMC-扩展SRAM内存管理


/**
  ******************************************************************************
  *                           硬石YS-F1Pro开发板例程功能说明
  *
  *  例程名称: YSF1_HAL-042. FSMC-扩展SRAM内存管理
  *   
  ******************************************************************************
  * 说明:
  * 本例程配套硬石stm32开发板YS-F1Pro使用。
  *
  * 淘宝:
  * 论坛:ing10bbs
  * 版权归硬石嵌入式开发团队所有,请勿商用。
  ******************************************************************************
  */

【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文件内容
  1. #ifndef __BSP_MALLOC_H__
  2. #define __BSP_MALLOC_H__

  3. /* 包含头文件 ----------------------------------------------------------------*/
  4. #include "stm32f1xx_hal.h"

  5. /* 宏定义 --------------------------------------------------------------------*/
  6. #ifndef NULL
  7. #define NULL 0
  8. #endif

  9. //定义两个内存池
  10. #define SRAMIN                         0                                         //内部内存池
  11. #define SRAMEX                   1                                         //外部内存池

  12. #define SRAMBANK                        2                                   //定义支持的SRAM块数.       

  13. //mem1内存参数设定.mem1完全处于内部SRAM里面.
  14. #define MEM1_BLOCK_SIZE                             32                                                                       //内存块大小为32字节
  15. #define MEM1_MAX_SIZE                               40*1024                                                                //最大管理内存 40K
  16. #define MEM1_ALLOC_TABLE_SIZE    MEM1_MAX_SIZE/MEM1_BLOCK_SIZE          //内存表大小

  17. //mem2内存参数设定.mem2的内存池处于外部SRAM里面
  18. #define MEM2_BLOCK_SIZE                             32                                                                       //内存块大小为32字节
  19. #define MEM2_MAX_SIZE                               928*1024                                                     //最大管理内存960K
  20. #define MEM2_ALLOC_TABLE_SIZE           MEM2_MAX_SIZE/MEM2_BLOCK_SIZE    //内存表大小

  21. /* 类型定义 ------------------------------------------------------------------*/
  22. //内存管理控制器
  23. struct _m_mallco_dev
  24. {
  25.         void    ( * init ) ( uint8_t );                                 //初始化
  26.         uint8_t ( * perused ) ( uint8_t );                 //内存使用率
  27.         uint8_t   * membase [ SRAMBANK ];                   //内存池 管理SRAMBANK个区域的内存
  28.         uint16_t  * memmap  [ SRAMBANK ];                    //内存管理状态表
  29.         uint8_t     memrdy [ SRAMBANK ];                          //内存管理是否就绪
  30. };       

  31. /* 扩展变量 ------------------------------------------------------------------*/
  32. extern struct _m_mallco_dev mallco_dev;         //在mallco.c里面定义

  33. /* 函数声明 ------------------------------------------------------------------*/
  34. void mymemset(void *s,uint8_t c,uint32_t count);            //设置内存
  35. void mymemcpy(void *des,void *src,uint32_t n);        //复制内存     
  36. void my_mem_init(uint8_t memx);                                                //内存管理初始化函数(外/内部调用)
  37. uint32_t my_mem_malloc(uint8_t memx,uint32_t size);          //内存分配(内部调用)
  38. uint8_t my_mem_free(uint8_t memx,uint32_t offset);                //内存释放(内部调用)
  39. uint8_t my_mem_perused(uint8_t memx);                                          //获得内存使用率(外/内部调用)

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

  44. #endif /* __BSP_MALLOC_H__ */

  45. /*************************************** 硬石嵌入式开发团队 *****END OF FILE****/


bsp_malloc.c文件内容
  1. /**
  2.   ******************************************************************************
  3.   * 文件名程: bsp_malloc.c
  4.   * 作    者: 硬石嵌入式开发团队
  5.   * 版    本: V1.0
  6.   * 编写日期: 2015-10-04
  7.   * 功    能: 动态内存分配管理实现
  8.   ******************************************************************************
  9.   * 说明:
  10.   * 本例程配套硬石stm32开发板YS-F1Pro使用。
  11.   *
  12.   * 淘宝:
  13.   * 论坛:ing10bbs
  14.   *
  15.   ******************************************************************************
  16.   */
  17. /* 包含头文件 ----------------------------------------------------------------*/
  18. #include "malloc/bsp_malloc.h"
  19. #include "exSRAM/bsp_exSRAM.h"

  20. /* 私有宏定义 ----------------------------------------------------------------*/
  21. /* 私有变量 ------------------------------------------------------------------*/
  22. #if defined ( __CC_ARM )  // 使用Keil编译环境

  23. //内存池(4字节对齐)
  24. __align(4) uint8_t mem1base[MEM1_MAX_SIZE];                                                                                                        //内部SRAM内存池
  25. __align(4) uint8_t mem2base[MEM2_MAX_SIZE] __attribute__((at(EXSRAM_BANK_ADDR)));                                        //外部SRAM内存池

  26. //内存管理表
  27. uint16_t mem1mapbase[MEM1_ALLOC_TABLE_SIZE];                                                                                                        //内部SRAM内存池MAP
  28. uint16_t mem2mapbase[MEM2_ALLOC_TABLE_SIZE] __attribute__((at(EXSRAM_BANK_ADDR+MEM2_MAX_SIZE)));        //外部SRAM内存池MAP

  29. #elif defined ( __ICCARM__ ) // 使用IAR编译环境

  30. //内存池(4字节对齐)
  31. #pragma pack(4)
  32. uint8_t mem1base[MEM1_MAX_SIZE];                                                                                                        //内部SRAM内存池

  33. #pragma location=EXSRAM_BANK_ADDR
  34. #pragma pack(4)
  35. uint8_t mem2base[MEM2_MAX_SIZE];      //外部SRAM内存池

  36. //内存管理表
  37. uint16_t mem1mapbase[MEM1_ALLOC_TABLE_SIZE];        //内部SRAM内存池MAP

  38. #pragma location=(EXSRAM_BANK_ADDR+MEM2_MAX_SIZE)
  39. uint16_t mem2mapbase[MEM2_ALLOC_TABLE_SIZE];        //外部SRAM内存池MAP

  40. #endif

  41. //内存管理参数          
  42. const uint32_t memtblsize[SRAMBANK]={MEM1_ALLOC_TABLE_SIZE,MEM2_ALLOC_TABLE_SIZE};                        //内存表大小
  43. const uint32_t memblksize[SRAMBANK]={MEM1_BLOCK_SIZE,MEM2_BLOCK_SIZE};                                                      //内存分块大小
  44. const uint32_t memsize[SRAMBANK]={MEM1_MAX_SIZE,MEM2_MAX_SIZE};                                                                          //内存总大小

  45. /* 私有类型定义 --------------------------------------------------------------*/
  46. //内存管理控制器
  47. struct _m_mallco_dev mallco_dev=
  48. {
  49.         my_mem_init,                                             //内存初始化
  50.         my_mem_perused,                                           //内存使用率
  51.         mem1base,mem2base,                                 //内存池
  52.         mem1mapbase,mem2mapbase,               //内存管理状态表
  53.         0,0,                                                                  //内存管理未就绪
  54. };

  55. /* 扩展变量 ------------------------------------------------------------------*/
  56. /* 私有函数原形 --------------------------------------------------------------*/
  57. /* 函数体 --------------------------------------------------------------------*/

  58. //复制内存
  59. //*des:目的地址
  60. //*src:源地址
  61. //n:需要复制的内存长度(字节为单位)
  62. void mymemcpy(void *des,void *src,uint32_t n)  
  63. {  
  64.         uint8_t *xdes=des;
  65.         uint8_t *xsrc=src;        
  66.         while(n--)*xdes++=*xsrc++;  
  67. }  

  68. //设置内存
  69. //*s:内存首地址
  70. //c :要设置的值
  71. //count:需要设置的内存大小(字节为单位)
  72. void mymemset(void *s,uint8_t c,uint32_t count)  
  73. {  
  74.         uint8_t *xs = s;  
  75.         while(count--)*xs++=c;  
  76. }          

  77. //内存管理初始化  
  78. //memx:所属内存块
  79. void my_mem_init(uint8_t memx)  
  80. {  
  81.         mymemset(mallco_dev.memmap[memx], 0,memtblsize[memx]*2);//内存状态表数据清零  
  82.         mymemset(mallco_dev.membase[memx], 0,memsize[memx]);        //内存池所有数据清零  
  83.         mallco_dev.memrdy[memx]=1;                                                                //内存管理初始化OK  
  84. }  

  85. //获取内存使用率
  86. //memx:所属内存块
  87. //返回值:使用率(0~100)
  88. uint8_t my_mem_perused(uint8_t memx)  
  89. {  
  90.         uint32_t used=0;  
  91.         uint32_t i;  
  92.        
  93.         for(i=0;i<memtblsize[memx];i++)  
  94.         {  
  95.                 if(mallco_dev.memmap[memx][i])used++;
  96.         }
  97.         return (used*100)/(memtblsize[memx]);  
  98. }  


  99. //内存分配(内部调用)
  100. //memx:所属内存块
  101. //size:要分配的内存大小(字节)
  102. //返回值:0XFFFFFFFF,代表错误;其他,内存偏移地址
  103. uint32_t my_mem_malloc(uint8_t memx,uint32_t size)  
  104. {  
  105.         signed long offset=0;  
  106.         uint32_t nmemb;        //需要的内存块数  
  107.         uint32_t cmemb=0;//连续空内存块数
  108.         uint32_t i;  
  109.        
  110.         if(!mallco_dev.memrdy[memx])mallco_dev.init(memx);//未初始化,先执行初始化
  111.        
  112.         if(size==0)
  113.                 return 0XFFFFFFFF;//不需要分配
  114.        
  115.         nmemb=size/memblksize[memx];          //获取需要分配的连续内存块数
  116.        
  117.         if(size%memblksize[memx])nmemb++;
  118.        
  119.         for(offset=memtblsize[memx]-1;offset>=0;offset--)//搜索整个内存控制区  
  120.         {     
  121.                 if(!mallco_dev.memmap[memx][offset])cmemb++;//连续空内存块数增加
  122.                 else cmemb=0;                                                                //连续内存块清零
  123.                
  124.                 if(cmemb==nmemb)                                                        //找到了连续nmemb个空内存块
  125.                 {
  126.                         for(i=0;i<nmemb;i++)                                          //标注内存块非空
  127.                         {  
  128.                                         mallco_dev.memmap[memx][offset+i]=nmemb;  
  129.                         }  
  130.                         return (offset*memblksize[memx]);//返回偏移地址  
  131.                 }
  132.         }  
  133.         return 0XFFFFFFFF;//未找到符合分配条件的内存块  
  134. }  


  135. //释放内存(内部调用)
  136. //memx:所属内存块
  137. //offset:内存地址偏移
  138. //返回值:0,释放成功;1,释放失败;  
  139. uint8_t my_mem_free(uint8_t memx,uint32_t offset)  
  140. {  
  141.         int i;  
  142.   
  143.         if(!mallco_dev.memrdy[memx])//未初始化,先执行初始化
  144.         {
  145.         mallco_dev.init(memx);   
  146.                         return 1;//未初始化  
  147.         }  

  148.         if(offset<memsize[memx])//偏移在内存池内.
  149.         {  
  150.                         int index=offset/memblksize[memx];                        //偏移所在内存块号码  
  151.                         int nmemb=mallco_dev.memmap[memx][index];        //内存块数量
  152.                         for(i=0;i<nmemb;i++)                                                  //内存块清零
  153.                         {  
  154.                                         mallco_dev.memmap[memx][index+i]=0;  
  155.                         }  
  156.                         return 0;  
  157.         }
  158.         else
  159.                 return 2;//偏移超区了.  
  160. }  


  161. //释放内存(外部调用)
  162. //memx:所属内存块
  163. //ptr:内存首地址
  164. void myfree(uint8_t memx,void *ptr)  
  165. {  
  166.         uint32_t offset;   
  167.        
  168.         if(ptr==NULL)return;//地址为0.  
  169.         offset=(uint32_t)ptr-(uint32_t)mallco_dev.membase[memx];     
  170.         my_mem_free(memx,offset);        //释放内存     
  171. }  

  172. //分配内存(外部调用)
  173. //memx:所属内存块
  174. //size:内存大小(字节)
  175. //返回值:分配到的内存首地址.
  176. void *mymalloc(uint8_t memx,uint32_t size)  
  177. {  
  178.         uint32_t offset;   

  179.         offset=my_mem_malloc(memx,size);                      
  180.        
  181.         if(offset==0XFFFFFFFF)return NULL;  
  182.         else return (void*)((uint32_t)mallco_dev.membase[memx]+offset);  
  183. }  

  184. //重新分配内存(外部调用)
  185. //memx:所属内存块
  186. //*ptr:旧内存首地址
  187. //size:要分配的内存大小(字节)
  188. //返回值:新分配到的内存首地址.
  189. void *myrealloc(uint8_t memx,void *ptr,uint32_t size)  
  190. {  
  191.         uint32_t offset;   
  192.        
  193.         offset=my_mem_malloc(memx,size);          
  194.         if(offset==0XFFFFFFFF)return NULL;     
  195.         else  
  196.         {                                                                            
  197.                 mymemcpy((void*)((uint32_t)mallco_dev.membase[memx]+offset),ptr,size);        //拷贝旧内存内容到新内存   
  198.                 myfree(memx,ptr);                                                                                                            //释放旧内存
  199.                 return (void*)((uint32_t)mallco_dev.membase[memx]+offset);                                  //返回新内存首地址
  200.         }  
  201. }

  202. /***************************************硬石嵌入式开发团队 *****END OF FILE****/

串口调试助手截图.jpg


mmuuss586 发表于 2016-6-16 10:16 | 显示全部楼层
谢谢分享
您需要登录后才可以回帖 登录 | 注册

本版积分规则

122

主题

216

帖子

48

粉丝
快速回复 在线客服 返回列表 返回顶部