金牌会员 
   
	- 积分
 - 2107
 
        - 金钱
 - 2107 
 
       - 注册时间
 - 2017-2-11
 
      - 在线时间
 - 307 小时
 
 
 
 | 
 
 本帖最后由 jiangyy 于 2020-9-29 14:13 编辑  
 
  HAL库也是目前比较流行的MDK开发包,但很多朋友一直在用KEIL5软件,但是后续使用HAL库开发,编译速度大大降低,好处是大家用习惯了,很上手。但是意法半导体后期主打STM32CUBEIDE软件,面向图形界面开发编程,一键生成代码,减小开发周期和开发难度,大大缩小项目开发成本和时间,而且还有一点是,HAL库对代码的严谨性特别强,这点是编程工作者不能忽略的。今天特意在这里说一下关于图形化生成FATFS文件系统,挂载SD卡。我的软件版本是STM32CubeIDE Version: 1.4.2,库包版本是STM32CubeIDE FW_F4 V1.25.1,应该算是最新的了。目前基本上已调通(这里好多坑,填补了不少),只是有一个地方出问题,就是FRESULT f_getfree (const TCHAR* path, DWORD* nclst, FATFS** fatfs); 获取剩余容量和总容量错误。我把bsp_fatfs.c代码贴出来- /*
 
 -  * bsp_fatfs.c
 
 -  *
 
 -  *  Created on: Sep 26, 2020
 
 -  *      Author: jiangyuanyuan
 
 -  */
 
  
- #include "bsp_fatfs.h"
 
 - FATFS fs;                 //工作空间
 
 - FIL fil;                  // 文件项目
 
 - uint32_t byteswritten;    // 写文件计数
 
 - uint32_t bytesread;       // 读文件计数
 
 - uint8_t wtext[] = "This is a 8G Card!!!"; // 写的内容
 
 - uint8_t rtext[1024];             // 读取的buff
 
 - char filename[] = "FATFS.txt"; // 文件名
 
  
- //得到磁盘剩余容量
 
 - //drv:磁盘编号("0:"/"1:")
 
 - //total:总容量         (单位KB)
 
 - //free:剩余容量         (单位KB)
 
 - //返回值:0,正常.其他,错误代码
 
 - vu8 exf_getfree(u8 *drv,u32 *total,u32 *free)
 
 - {
 
 -         FATFS *fs1;
 
 -         vu8 res;
 
 -     u32 fre_clust=0, fre_sect=0, tot_sect=0;
 
  
-     //得到磁盘信息及空闲簇数量
 
 -     res = f_getfree((const TCHAR*)drv, (DWORD*)&fre_clust, fs1);
 
 -     if(res==0)
 
 -         {
 
 -             tot_sect=(fs1->n_fatent-2)*fs1->csize;        //得到总扇区数
 
 -             fre_sect=fre_clust*fs1->csize;                        //得到空闲扇区数
 
 - #if _MAX_SS!=512                                                                  //扇区大小不是512字节,则转换为512字节
 
 -                 tot_sect*=fs1->ssize/512;
 
 -                 fre_sect*=fs1->ssize/512;
 
 - #endif
 
 -                 *total=tot_sect>>1;        //单位为KB
 
 -                 *free=fre_sect>>1;        //单位为KB
 
 -          }
 
 -         return res;
 
 - }
 
  
- //通过串口打印SD卡相关信息
 
 - void show_sdcard_info(void)
 
 - {
 
 -         int sdcard_status = 0;
 
 -         HAL_SD_CardCIDTypeDef SDCard_CID;
 
 -         uint64_t CardCap;        //SD卡容量
 
  
-         HAL_SD_GetCardCID(&hsd,&SDCard_CID);                    //获取CID
 
 -         sdcard_status = HAL_SD_GetCardState(&hsd);
 
 -         switch(hsd.SdCard.CardType)
 
 -         {
 
 -                 case CARD_SDSC:
 
 -                 {
 
 -                         if(hsd.SdCard.CardVersion == CARD_V1_X)
 
 -                                 printf("Card Type:SDSC V1\r\n");
 
 -                         else if(hsd.SdCard.CardVersion == CARD_V2_X)
 
 -                                 printf("Card Type:SDSC V2\r\n");
 
 -                 }
 
 -                 break;
 
 -                 case CARD_SDHC_SDXC:printf("Card Type:SDHC\r\n");break;
 
 -         }
 
  
-         if(sdcard_status == HAL_SD_CARD_TRANSFER)
 
 -         {
 
 -             //打印SD卡基本信息
 
 -             CardCap = (uint64_t)hsd.SdCard.BlockSize*(uint64_t)hsd.SdCard.BlockNbr;                                                                                                        //计算SD卡容量
 
 -             printf("CardCapacity: %ld MB\r\n",(uint64_t)(hsd.SdCard.BlockSize*hsd.SdCard.BlockNbr));                        //显示容量
 
 -             printf("Card ManufacturerID:%ld \r\n",(u32)SDCard_CID.ManufacturerID);                                                                //制造商ID
 
 -             printf("Card RCA:%ld \r\n",hsd.SdCard.RelCardAdd);                                                                                                        //卡相对地址
 
 -             printf("LogBlockNbr:%ld \r\n",hsd.SdCard.LogBlockNbr);                                                                                                //显示逻辑块数量
 
 -             printf("LogBlockSize:%ld \r\n",hsd.SdCard.LogBlockSize);                                                                                        //显示逻辑块大小
 
 -             printf("Card Capacity:%ld MB\r\n",(u32)(CardCap>>20));                                                                                                //显示容量
 
 -             printf("Card BlockSize: %ld \r\n",hsd.SdCard.BlockSize);                                                                                        //显示块大小
 
 -         }
 
 -         else
 
 -         {
 
 -             printf("SD card init fail!\r\n" );
 
 -         }
 
 - }
 
  
- void SD_Auto_NewFolder(void)
 
 - {
 
 -         unsigned long total,free;
 
 -         vu8 err;
 
 - //        u8 paddr[18];                                        //存放P Addr:+p地址的ASCII值
 
 - //        BYTE *work=0;/* Work area (larger is better for process time) */
 
  
-         printf("\r\n ****** FATFS SYSTEM ******\r\n\r\n");
 
 -         /*-1- 格式化SD卡*/
 
 - //        work = mymalloc(SRAMEX,_MAX_LEN);//外部内存池申请
 
 - //        if(work!=NULL)
 
 - //        {
 
 - //                sprintf((char*)paddr,"0X%08X",(u32)work);
 
 - //                printf("%s\r\n",paddr);
 
 - //        }
 
 - //
 
 - //        err=f_mkfs("0:", FM_FAT32, 0, work, _MAX_LEN);
 
 - //        if(err==0)
 
 - //        {
 
 - ////                f_setlabel((const TCHAR*)"0:JAYMIE");//设置Flash磁盘的名字为:ALIENTEK
 
 - //                printf("Flash Disk Format Finish\r\n");        //格式化完成
 
 - //        }else printf("Flash Disk Format Error\r\n");        //格式化失败
 
 - //
 
 - //        myfree(SRAMEX,work);//释放外部内存池内存
 
 - //        work = 0;                        //指向空地址
 
  
-         /*-2- 挂载文件系统*/
 
 -         retSD = f_mount(&fs, "0:", 0);
 
 -         if(retSD)
 
 -         {
 
 -                 printf(" mount error : %d \r\n",retSD);
 
 -                 Error_Handler();
 
 -         }
 
 -         else
 
 -                 printf(" mount sucess!!! \r\n");
 
  
-         /*-3-获取SD卡容量和信息*/
 
 -         err = exf_getfree("0:",&total,&free);
 
 -         if(err)
 
 -                 printf("SD Card Fatfs Error:%d!\r\n",err);
 
  
-         printf("total:%ld MB,free:%ld MB\r\n",total>>10,free>>10);//显示SD卡总容量 MB,剩余容量 MB
 
  
-         show_sdcard_info();
 
  
-         /*-4-创建新的文件并写入数据*/
 
 -         retSD = f_open(&fil, filename, FA_CREATE_ALWAYS | FA_WRITE);                //打开文件,权限包括创建、写(如果没有该文件,会创建该文件)
 
 -         if(retSD)                                                                                                                        //返回值不为0(出现问题)
 
 -                 printf(" open file error : %d\r\n",retSD);                                                //打印问题代码
 
 -         else
 
 -                 printf(" open file sucess!!! \r\n");
 
  
-         /*-5- 在txt文件中写入数据*/
 
 -         retSD = f_write(&fil, wtext, sizeof(wtext), (void *)&byteswritten);        //在文件内写入wtext内的内容
 
 -         if(retSD)                                                                                                                        //返回值不为0(出现问题)
 
 -                 printf(" write file error : %d\r\n",retSD);                                                //打印问题代码
 
 -         else
 
 -         {
 
 -                 printf(" write file sucess!!! \r\n");
 
 -                 printf(" write Data : %s\r\n",wtext);                                                        //打印写入的内容
 
 -         }
 
  
-         /*-6- 关闭txt文件*/
 
 -         retSD = f_close(&fil);                                                                                                //关闭该文件
 
 -         if(retSD)                                                                                                                        //返回值不为0(出现问题)
 
 -                 printf(" close error : %d\r\n",retSD);                                                        //打印问题代码
 
 -         else
 
 -                 printf(" close sucess!!! \r\n");
 
  
-         /*-7- 打开文件读取数据*/
 
 -         retSD = f_open(&fil, filename, FA_READ);                                                        //打开文件,权限为只读
 
 -         if(retSD)                                                                                                                        //返回值不为0(出现问题)
 
 -                 printf(" open file error : %d\r\n",retSD);                                                //打印问题代码
 
 -         else
 
 -                 printf(" open file sucess!!! \r\n");
 
  
-         /*-8- 读取txt文件数据*/
 
 -         retSD = f_read(&fil, rtext, sizeof(rtext), (UINT*)&bytesread);                //读取文件内容放到rtext中
 
 -         if(retSD)                                                                                                                        //返回值不为0(出现问题)
 
 -                 printf(" read error!!! %d\r\n",retSD);                                                        //打印问题代码
 
 -         else
 
 -         {
 
 -                 printf(" read sucess!!! \r\n");
 
 -                 printf(" read Data : %s\r\n",rtext);                                                        //打印读取到的数据
 
 -         }
 
  
-         /*-9- 关闭文件*/
 
 -         retSD = f_close(&fil);                                                                                                //关闭该文件
 
 -         if(retSD)                                                                                                                          //返回值不为0(出现问题)
 
 -                 printf(" close error!!! %d\r\n",retSD);                                                        //打印问题代码
 
 -         else
 
 -                 printf(" close sucess!!! \r\n");
 
  
-         /*-10- 读写一致性检测*/
 
 -         if(bytesread == byteswritten)                                                                                //如果读写位数一致
 
 -         {
 
 -                 printf(" FatFs is working well!!!\r\n");                                                //打印文件系统工作正常
 
 -         }
 
  
- }
 
  
  复制代码 
上面是应用层.c文件,在/*-3-获取SD卡容量和信息*/  这个地方,exf_getfree("0:",&total,&free);的内容是错误的,我也不知道是公式的问题,还是这个底层的问题,还是文件系统中间件的问题,反正我研究了很长时间,没搞出来,后面我继续优化一下。对了,这里移植正点原子的内存池管理这章节,也是废了不少时间移植成功(涉及到内存的映射和启动文件.ld的修改),网上的涉及到.ld的修改文章很少,有的虽然修改成功了,但是生成的.bin和.hex文件超级大,后面经过一个贴友的帮助,总算修改好了启动文件。先把启动文件.ld代码贴出来,自己可以看看新增的地方。 
- /**
 
 -  ******************************************************************************
 
 -  * @file      LinkerScript.ld
 
 -  * @author    Auto-generated by STM32CubeIDE
 
 -  * @brief     Linker script for STM32F407ZGTx Device from STM32F4 series
 
 -  *                      1024Kbytes FLASH
 
 -  *                      64Kbytes CCMRAM
 
 -  *                      128Kbytes RAM
 
 -  *
 
 -  *            Set heap size, stack size and stack location according
 
 -  *            to application requirements.
 
 -  *
 
 -  *            Set memory bank area and size if external memory is used
 
 -  ******************************************************************************
 
 -  * @attention
 
 -  *
 
 -  * <h2><center>© Copyright (c) 2020 STMicroelectronics.
 
 -  * All rights reserved.</center></h2>
 
 -  *
 
 -  * This software component is licensed by ST under BSD 3-Clause license,
 
 -  * the "License"; You may not use this file except in compliance with the
 
 -  * License. You may obtain a copy of the License at:
 
 -  *                        opensource.org/licenses/BSD-3-Clause
 
 -  *
 
 -  ******************************************************************************
 
 -  */
 
  
- /* Entry Point */
 
 - ENTRY(Reset_Handler)
 
  
- /* Highest address of the user mode stack */
 
 - _estack = ORIGIN(RAM) + LENGTH(RAM);        /* end of "RAM" Ram type memory */
 
  
- _Min_Heap_Size = 0x200 ;        /* required amount of heap  */
 
 - _Min_Stack_Size = 0x1000 ;        /* required amount of stack */
 
  
- /* Memories definition */
 
 - MEMORY
 
 - {
 
 -   CCMRAM    (xrw)    : ORIGIN = 0x10000000,   LENGTH = 64K
 
 -   RAM    (xrw)    : ORIGIN = 0x20000000,   LENGTH = 128K
 
 -   FLASH    (rx)    : ORIGIN = 0x8000000,   LENGTH = 1024K
 
 -   SRAM   (rx)    : ORIGIN = 0x68000000,   LENGTH = 1024K
 
 - }
 
  
- /* Sections */
 
 - SECTIONS
 
 - {
 
 -   /* The startup code into "FLASH" Rom type memory */
 
 -   .isr_vector :
 
 -   {
 
 -     . = ALIGN(4);
 
 -     KEEP(*(.isr_vector)) /* Startup code */
 
 -     . = ALIGN(4);
 
 -   } >FLASH
 
  
-   /* The program code and other data into "FLASH" Rom type memory */
 
 -   .text :
 
 -   {
 
 -     . = ALIGN(4);
 
 -     *(.text)           /* .text sections (code) */
 
 -     *(.text*)          /* .text* sections (code) */
 
 -     *(.glue_7)         /* glue arm to thumb code */
 
 -     *(.glue_7t)        /* glue thumb to arm code */
 
 -     *(.eh_frame)
 
  
-     KEEP (*(.init))
 
 -     KEEP (*(.fini))
 
  
-     . = ALIGN(4);
 
 -     _etext = .;        /* define a global symbols at end of code */
 
 -   } >FLASH
 
  
-   /* Constant data into "FLASH" Rom type memory */
 
 -   .rodata :
 
 -   {
 
 -     . = ALIGN(4);
 
 -     *(.rodata)         /* .rodata sections (constants, strings, etc.) */
 
 -     *(.rodata*)        /* .rodata* sections (constants, strings, etc.) */
 
 -     . = ALIGN(4);
 
 -   } >FLASH
 
  
-   .ARM.extab   : { 
 
 -     . = ALIGN(4);
 
 -     *(.ARM.extab* .gnu.linkonce.armextab.*)
 
 -     . = ALIGN(4);
 
 -   } >FLASH
 
 -   
 
 -   .ARM : {
 
 -     . = ALIGN(4);
 
 -     __exidx_start = .;
 
 -     *(.ARM.exidx*)
 
 -     __exidx_end = .;
 
 -     . = ALIGN(4);
 
 -   } >FLASH
 
  
-   .preinit_array     :
 
 -   {
 
 -     . = ALIGN(4);
 
 -     PROVIDE_HIDDEN (__preinit_array_start = .);
 
 -     KEEP (*(.preinit_array*))
 
 -     PROVIDE_HIDDEN (__preinit_array_end = .);
 
 -     . = ALIGN(4);
 
 -   } >FLASH
 
 -   
 
 -   .init_array :
 
 -   {
 
 -     . = ALIGN(4);
 
 -     PROVIDE_HIDDEN (__init_array_start = .);
 
 -     KEEP (*(SORT(.init_array.*)))
 
 -     KEEP (*(.init_array*))
 
 -     PROVIDE_HIDDEN (__init_array_end = .);
 
 -     . = ALIGN(4);
 
 -   } >FLASH
 
 -   
 
 -   .fini_array :
 
 -   {
 
 -     . = ALIGN(4);
 
 -     PROVIDE_HIDDEN (__fini_array_start = .);
 
 -     KEEP (*(SORT(.fini_array.*)))
 
 -     KEEP (*(.fini_array*))
 
 -     PROVIDE_HIDDEN (__fini_array_end = .);
 
 -     . = ALIGN(4);
 
 -   } >FLASH
 
 -   
 
 -   /* Used by the startup to initialize data */
 
 -   _sidata = LOADADDR(.data);
 
  
-   /* Initialized data sections into "RAM" Ram type memory */
 
 -   .data : 
 
 -   {
 
 -     . = ALIGN(4);
 
 -     _sdata = .;        /* create a global symbol at data start */
 
 -     *(.data)           /* .data sections */
 
 -     *(.data*)          /* .data* sections */
 
  
-     . = ALIGN(4);
 
 -     _edata = .;        /* define a global symbol at data end */
 
 -     
 
 -   } >RAM AT> FLASH
 
  
-   /* Uninitialized data section into "RAM" Ram type memory */
 
 -   .ccmram(NOLOAD) :
 
 -   {
 
 -     . = ALIGN(4);
 
 -     _sccmram = .;       /* create a global symbol at ccmram start */
 
 -     *(.ccmram)
 
 -     *(.ccmram*)
 
 -     
 
 -     . = ALIGN(4);
 
 -     _eccmram = .;       /* create a global symbol at ccmram end */
 
 -   } >CCMRAM AT> FLASH /*新增*/
 
 -   
 
 -   . = ALIGN(4);
 
 -   .bss :
 
 -   {
 
 -     /* This is used by the startup in order to initialize the .bss section */
 
 -     _sbss = .;         /* define a global symbol at bss start */
 
 -     __bss_start__ = _sbss;
 
 -     *(.bss)
 
 -     *(.bss*)
 
 -     *(COMMON)
 
  
-     . = ALIGN(4);
 
 -     _ebss = .;         /* define a global symbol at bss end */
 
 -     __bss_end__ = _ebss;
 
 -   } >RAM
 
  
-   /* User_heap_stack section, used to check that there is enough "RAM" Ram  type memory left */
 
 -   ._user_heap_stack :
 
 -   {
 
 -     . = ALIGN(8);
 
 -     PROVIDE ( end = . );
 
 -     PROVIDE ( _end = . );
 
 -     . = . + _Min_Heap_Size;
 
 -     . = . + _Min_Stack_Size;
 
 -     . = ALIGN(8);
 
 -   } >RAM
 
  
-   .sram(NOLOAD) : 
 
 -   {
 
 -     . = ALIGN(4);
 
 -     _SRAM_SYMBOLS = .;      /* create a global symbol at data start */
 
 -     *(.sram)                           /* .data sections */
 
 -     *(.sram*)                          /* .data* sections */
 
  
-     . = ALIGN(4);
 
 -     _ESRAM_SYMBOLS = .;     /* define a global symbol at data end */
 
 -     
 
 -   } >SRAM /*新增*/
 
 -   /* Remove information from the compiler libraries */
 
 -   /DISCARD/ :
 
 -   {
 
 -     libc.a ( * )
 
 -     libm.a ( * )
 
 -     libgcc.a ( * )
 
 -   }
 
  
-   .ARM.attributes 0 : { *(.ARM.attributes) }
 
 - }
 
 
  复制代码 
内存池管理文件.c和.h 
- /*
 
 -  * bsp_malloc.c
 
 -  *
 
 -  *  Created on: Sep 24, 2020
 
 -  *      Author: jiangyuanyuan
 
 -  */
 
  
- #include "bsp_malloc.h"
 
  
- //内存池(32字节对齐)
 
 - __attribute__ ((aligned (32))) u8 mem1base[MEM1_MAX_SIZE];                                                                                        //内部SRAM内存池
 
 - __attribute__ ((aligned (32))) u8 mem2base[MEM2_MAX_SIZE] __attribute__((section(".sram")));            //外部SRAM内存池
 
 - __attribute__ ((aligned (32))) u8 mem3base[MEM3_MAX_SIZE] __attribute__((section(".ccmram")));                 //内部CCM内存池
 
  
- //内存管理表
 
 - u16 mem1mapbase[MEM1_ALLOC_TABLE_SIZE];                                                                                //内部SRAM内存池MAP
 
 - u16 mem2mapbase[MEM2_ALLOC_TABLE_SIZE] __attribute__((section(".sram")));        //外部SRAM内存池MAP
 
 - u16 mem3mapbase[MEM3_ALLOC_TABLE_SIZE] __attribute__((section(".ccmram")));        //内部CCM内存池MAP
 
 - //内存管理参数
 
 - const u32 memtblsize[SRAMBANK]={MEM1_ALLOC_TABLE_SIZE,MEM2_ALLOC_TABLE_SIZE,MEM3_ALLOC_TABLE_SIZE};        //内存表大小
 
 - const u32 memblksize[SRAMBANK]={MEM1_BLOCK_SIZE,MEM2_BLOCK_SIZE,MEM3_BLOCK_SIZE};                                        //内存分块大小
 
 - const u32 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,                           //内存管理未就绪
 
 - };
 
  
- //复制内存
 
 - //*des:目的地址
 
 - //*src:源地址
 
 - //n:需要复制的内存长度(字节为单位)
 
 - void mymemcpy(void *des,void *src,u32 n)
 
 - {
 
 -     u8 *xdes=des;
 
 -         u8 *xsrc=src;
 
 -     while(n--)*xdes++=*xsrc++;
 
 - }
 
 - //设置内存
 
 - //*s:内存首地址
 
 - //c :要设置的值
 
 - //count:需要设置的内存大小(字节为单位)
 
 - void mymemset(void *s,u8 c,u32 count)
 
 - {
 
 -     u8 *xs = s;
 
 -     while(count--)*xs++=c;
 
 - }
 
 - //内存管理初始化
 
 - //memx:所属内存块
 
 - void my_mem_init(u8 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)
 
 - u8 my_mem_perused(u8 memx)
 
 - {
 
 -     u32 used=0;
 
 -     u32 i;
 
 -     for(i=0;i<memtblsize[memx];i++)
 
 -     {
 
 -         if(mallco_dev.memmap[memx][i])used++;
 
 -     }
 
 -     return (used*100)/(memtblsize[memx]);
 
 - }
 
 - //内存分配(内部调用)
 
 - //memx:所属内存块
 
 - //size:要分配的内存大小(字节)
 
 - //返回值:0XFFFFFFFF,代表错误;其他,内存偏移地址
 
 - u32 my_mem_malloc(u8 memx,u32 size)
 
 - {
 
 -     signed long offset=0;
 
 -     u32 nmemb;        //需要的内存块数
 
 -         u32 cmemb=0;//连续空内存块数
 
 -     u32 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,释放失败;
 
 - u8 my_mem_free(u8 memx,u32 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(u8 memx,void *ptr)
 
 - {
 
 -         u32 offset;
 
 -         if(ptr==NULL)return;//地址为0.
 
 -          offset=(u32)ptr-(u32)mallco_dev.membase[memx];
 
 -     my_mem_free(memx,offset);        //释放内存
 
 - }
 
 - //分配内存(外部调用)
 
 - //memx:所属内存块
 
 - //size:内存大小(字节)
 
 - //返回值:分配到的内存首地址.
 
 - void *mymalloc(u8 memx,u32 size)
 
 - {
 
 -     u32 offset;
 
 -         offset=my_mem_malloc(memx,size);
 
 -     if(offset==0XFFFFFFFF)return NULL;
 
 -     else return (void*)((u32)mallco_dev.membase[memx]+offset);
 
 - }
 
 - //重新分配内存(外部调用)
 
 - //memx:所属内存块
 
 - //*ptr:旧内存首地址
 
 - //size:要分配的内存大小(字节)
 
 - //返回值:新分配到的内存首地址.
 
 - void *myrealloc(u8 memx,void *ptr,u32 size)
 
 - {
 
 -     u32 offset;
 
 -     offset=my_mem_malloc(memx,size);
 
 -     if(offset==0XFFFFFFFF)return NULL;
 
 -     else
 
 -     {
 
 -             mymemcpy((void*)((u32)mallco_dev.membase[memx]+offset),ptr,size);        //拷贝旧内存内容到新内存
 
 -         myfree(memx,ptr);                                                                                                            //释放旧内存
 
 -         return (void*)((u32)mallco_dev.membase[memx]+offset);                                  //返回新内存首地址
 
 -     }
 
 - }
 
  
- void Malloc_Test(void)
 
 - {
 
 -         u8 *p=0;
 
 -         u8 *tp=0;
 
 -         u8 paddr[18];                                        //存放P Addr:+p地址的ASCII值
 
  
- #ifndef __USE_SRAM
 
 -         p=mymalloc(SRAMIN,2048);//内部内存池申请2K字节
 
 -         if(p!=NULL)
 
 -         {
 
 -                 tp=p;
 
 -                 sprintf((char*)paddr,"0X%08X",(u32)tp);
 
 -                 sprintf((char*)p,"Memory SRAMIN ADDR:");//向p写入一些内容
 
 -                 printf("%s",p);
 
 -                 printf("%s\r\n",paddr);
 
 -         }
 
 -         myfree(SRAMIN,p);//释放内部内存池内存
 
 -         p=0;                        //指向空地址
 
  
-         p=mymalloc(SRAMCCM,2048);//CCM内存池申请2K字节
 
 -         if(p!=NULL)
 
 -         {
 
 -                 tp=p;
 
 -                 sprintf((char*)paddr,"0X%08X",(u32)tp);
 
 -                 sprintf((char*)p,"Memory SRAMCCM ADDR:");//向p写入一些内容
 
 -                 printf("%s",p);
 
 -                 printf("%s\r\n",paddr);
 
 -         }
 
 -         myfree(SRAMCCM,p);//释放CCM内存池内存
 
 -         p=0;                        //指向空地址
 
 - #endif
 
 -         p=mymalloc(SRAMEX,2048);//外部内存池申请2K字节
 
 -         if(p!=NULL)
 
 -         {
 
 -                 tp=p;
 
 -                 sprintf((char*)paddr,"0X%08X",(u32)tp);
 
 -                 sprintf((char*)p,"Memory SRAMEX ADDR:");//向p写入一些内容
 
 -                 printf("%s",p);
 
 -                 printf("%s\r\n",paddr);
 
 -         }
 
 -         myfree(SRAMEX,p);//释放外部内存池内存
 
 -         p=0;                        //指向空地址
 
 - }
 
 
  复制代码- /*
 
 -  * bsp_malloc.h
 
 -  *
 
 -  *  Created on: Sep 24, 2020
 
 -  *      Author: jiangyuanyuan
 
 -  */
 
  
- #ifndef INC_BSP_MALLOC_H_
 
 - #define INC_BSP_MALLOC_H_
 
  
- #include "stm32f4xx_hal.h"
 
 - #include "bsp_sys.h"
 
 - #include "stdio.h"
 
  
- #define __USE_SRAM
 
  
- //定义三个内存池
 
 - #define SRAMIN         0                //内部内存池
 
 - #define SRAMEX   1                //外部内存池
 
 - #define SRAMCCM  2                //CCM内存池(此部分SRAM仅仅CPU可以访问!!!)
 
  
- #define SRAMBANK         3        //定义支持的SRAM块数.
 
  
- #ifdef __USE_SRAM
 
 - //mem1内存参数设定.mem1完全处于内部SRAM里面.
 
 - #define MEM1_BLOCK_SIZE                        32                                                    //内存块大小为32字节
 
 - #define MEM1_MAX_SIZE                        0                                                          //最大管理内存 0K
 
 - #define MEM1_ALLOC_TABLE_SIZE        0                                                         //内存表大小
 
  
- //mem3内存参数设定.mem3处于CCM,用于管理CCM(特别注意,这部分SRAM,仅CPU可以访问!!)
 
 - #define MEM3_BLOCK_SIZE                        32                                                    //内存块大小为32字节
 
 - #define MEM3_MAX_SIZE                        0                                                          //最大管理内存0K
 
 - #define MEM3_ALLOC_TABLE_SIZE        0                                                         //内存表大小
 
 - #else
 
 - //mem1内存参数设定.mem1完全处于内部SRAM里面.
 
 - #define MEM1_BLOCK_SIZE                        32                                                            //内存块大小为32字节
 
 - #define MEM1_MAX_SIZE                        100*1024                                                  //最大管理内存 100K
 
 - #define MEM1_ALLOC_TABLE_SIZE        MEM1_MAX_SIZE/MEM1_BLOCK_SIZE         //内存表大小
 
  
- //mem3内存参数设定.mem3处于CCM,用于管理CCM(特别注意,这部分SRAM,仅CPU可以访问!!)
 
 - #define MEM3_BLOCK_SIZE                        32                                                            //内存块大小为32字节
 
 - #define MEM3_MAX_SIZE                        60 *1024                                                  //最大管理内存60K
 
 - #define MEM3_ALLOC_TABLE_SIZE        MEM3_MAX_SIZE/MEM3_BLOCK_SIZE         //内存表大小
 
 - #endif
 
  
- //mem2内存参数设定.mem2的内存池处于外部SRAM里面
 
 - #define MEM2_BLOCK_SIZE                        32                                                            //内存块大小为32字节
 
 - #define MEM2_MAX_SIZE                        960 *1024                                                  //最大管理内存960K
 
 - #define MEM2_ALLOC_TABLE_SIZE        MEM2_MAX_SIZE/MEM2_BLOCK_SIZE         //内存表大小
 
  
- //内存管理控制器
 
 - struct _m_mallco_dev
 
 - {
 
 -         void (*init)(u8);                                        //初始化
 
 -         u8 (*perused)(u8);                                      //内存使用率
 
 -         u8         *membase[SRAMBANK];                                //内存池 管理SRAMBANK个区域的内存
 
 -         u16 *memmap[SRAMBANK];                                 //内存管理状态表
 
 -         u8  memrdy[SRAMBANK];                                 //内存管理是否就绪
 
 - };
 
 - extern struct _m_mallco_dev mallco_dev;         //在mallco.c里面定义
 
  
- void mymemset(void *s,u8 c,u32 count);        //设置内存
 
 - void mymemcpy(void *des,void *src,u32 n);//复制内存
 
 - void my_mem_init(u8 memx);                                //内存管理初始化函数(外/内部调用)
 
 - u32 my_mem_malloc(u8 memx,u32 size);        //内存分配(内部调用)
 
 - u8 my_mem_free(u8 memx,u32 offset);                //内存释放(内部调用)
 
 - u8 my_mem_perused(u8 memx);                                //获得内存使用率(外/内部调用)
 
 - ////////////////////////////////////////////////////////////////////////////////
 
 - //用户调用函数
 
 - void myfree(u8 memx,void *ptr);                          //内存释放(外部调用)
 
 - void *mymalloc(u8 memx,u32 size);                        //内存分配(外部调用)
 
 - void *myrealloc(u8 memx,void *ptr,u32 size);//重新分配内存(外部调用)
 
 - void Malloc_Test(void);
 
 - #endif /* INC_BSP_MALLOC_H_ */
 
 
  复制代码 上面因为我只用到外部SRAM的使用,所以没用到内部内存池和内部RAM的申请,所以头文件加了一个条件编译。以下是我SD卡打印的信息: 
- sram:1024kb
 
 - Memory SRAMEX ADDR:0X680EF800
 
  
-  ****** FATFS SYSTEM ******
 
  
- 0X680E8000
 
 - Flash Disk Format Finish
 
 -  mount sucess!!! 
 
 - total:722900 MB,free:38131 MB
 
 - Card Type:SDHC
 
 - CardCapacity: 512 MB
 
 - Card ManufacturerID:3 
 
 - Card RCA:43690 
 
 - LogBlockNbr:15523840 
 
 - LogBlockSize:512 
 
 - Card Capacity:7580 MB
 
 - Card BlockSize: 512 
 
 -  open file sucess!!! 
 
 -  write file sucess!!! 
 
 -  write Data : This is a 8G Card!!!
 
 -  close sucess!!! 
 
 -  open file sucess!!! 
 
 -  read sucess!!! 
 
 -  read Data : This is a 8G Card!!!
 
 -  close sucess!!! 
 
 -  FatFs is working well!!!
 
  复制代码 从串口打印数据,可以看到total:722900 MB,free:38131 MB是错误的,但是HAL_SD_CardCIDTypeDef SDCard_CID 结构体成员的信息是对的 
有贴友知道err = exf_getfree("0:",&total,&free);获取错误的问题,请留言,谢谢。  
 
 
 |   
 
 
 
 |