这次是实现一个使用STM32内部的flash模拟一个U盘。我使用的STM32芯片是STM32F103ZE,该芯片有512K的内部flash,本次工程,我准备用最后的400K空间来模拟一个U盘。本次的工程在之前用NAND或SD卡模拟U盘的工程基础上进行修改。

首次要做的是在外设库组中添加stm32f10x_flash.c文件,因为涉及到内部flash,所以必须添加此文件。接下去,需要修改的文件只有mass_mal.c和memory.c两个了。



先来讲讲memory.c,这个文件修改量很小。在函数的前面,我们可以看到有个:uint32_t Data_Buffer[];数组的定义,该数组的数组元素个数,跟大家所使用的存储器的块大小有关。比如说,在NNAD工程里,带数组这样定义:uint32_t Data_Buffer[BULK_MAX_PACKET_SIZE *2];( BULK_MAX_PACKET_SIZE  =64 )可以看到总共有128个字,也就是512字节;在SD卡的程序中也是512字节;为这次我们使用内部的flash,需要定义成2K字节:uint32_t Data_Buffer[BULK_MAX_PACKET_SIZE *8]。还有需要注意下,在Write_Memory()和Read_Memory()中MAL层读写函数我们使用官方例程上的调用代码,而不是之前我们讲过的NAND无法格式化解决的那篇文章的调用代码。调用如下:

Offset , 
  Data_Buffer, 
 Mass_Block_Size[lun]);
 
W_Offset - Mass_Block_Size[lun], 
  Data_Buffer, 
  Mass_Block_Size[lun]);



接着是mass_mal.c这个文件修改量比较大。首先,得在该文件的最前面需要定义一些与flash相关的宏定义:



#define     FLASH_START_ADDR        0x08016000    // Flash start address 
#define     FLASH_SIZE              0x64000  	  // 400K 的U盘 
#define     FLASH_PAGE_SIZE         0x800         // 2k Bytes per page,只有2K才能格式化
#define     FLASH_WAIT_TIMEOUT      100000        //操作等待时间


#include "mass_mal.h"

#define     FLASH_START_ADDR        0x08016000    // Flash start address 
#define     FLASH_SIZE              0x64000  	  // 400K 的U盘 
#define     FLASH_PAGE_SIZE         0x800         // 2k Bytes per page,只有2K才能格式化
#define     FLASH_WAIT_TIMEOUT      100000

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
uint32_t Mass_Memory_Size[2];
uint32_t Mass_Block_Size[2];
uint32_t Mass_Block_Count[2];
__IO uint32_t Status = 0;

/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/*******************************************************************************
* Function Name  : MAL_Init
* Description    : 初始化STM32的媒体设备
* Input          : lun
* Output         : None
* Return         : None
*******************************************************************************/
uint16_t MAL_Init(uint8_t lun)
{
  u16 status = MAL_OK;

  switch (lun)
  {
    case 0:  
		FLASH_Unlock(); 
             break;
    default:
             return MAL_FAIL;
  }
  return status;
}
/*******************************************************************************
* Function Name  : MAL_Write
* Description    : 写扇区
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
uint16_t MAL_Write(uint8_t lun, uint32_t Memory_Offset, uint32_t *Writebuff, uint16_t Transfer_Length)
{
  uint16_t i;
  switch (lun)
  {
    case 0:     
		for(i=0;i<Transfer_Length;i+=FLASH_PAGE_SIZE)
		{
			if(FLASH_WaitForLastOperation(FLASH_WAIT_TIMEOUT)!=FLASH_TIMEOUT)
			{
				FLASH_ClearFlag(FLASH_FLAG_EOP|FLASH_FLAG_PGERR|FLASH_FLAG_WRPRTERR);
			}
			FLASH_ErasePage(FLASH_START_ADDR + Memory_Offset + i); 			
		}
		for(i=0;i<Transfer_Length;i+=4)
		{
			if(FLASH_WaitForLastOperation(FLASH_WAIT_TIMEOUT)!=FLASH_TIMEOUT)
			{
				FLASH_ClearFlag(FLASH_FLAG_EOP|FLASH_FLAG_PGERR|

FLASH_FLAG_WRPRTERR);
			}
			FLASH_ProgramWord(FLASH_START_ADDR + Memory_Offset + i , Writebuff[i>>2]);
		}
      			break;
    default:
      return MAL_FAIL;
  }
  return MAL_OK;
}

/*******************************************************************************
* Function Name  : MAL_Read
* Description    : 读取扇区
* Input          : None
* Output         : None
* Return         : Buffer pointer
*******************************************************************************/
uint16_t MAL_Read(uint8_t lun, uint32_t Memory_Offset, uint32_t *Readbuff, uint16_t Transfer_Length)
{
  uint16_t i;
  switch (lun)
  {
    case 0:  
		for(i=0;i<Transfer_Length;i+=4)
		{
			Readbuff[i>>2] = ((vu32*)(FLASH_START_ADDR + Memory_Offset))[i>>2];
		}
             break;
    default:
      return MAL_FAIL;
  }
  return MAL_OK;
}

/*******************************************************************************
* Function Name  : MAL_GetStatus
* Description    : 获取状态
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
uint16_t MAL_GetStatus (uint8_t lun)
{
   	if (lun == 0)
   	{
  		Mass_Block_Count[0] = FLASH_SIZE/FLASH_PAGE_SIZE; 
		Mass_Block_Size[0] = FLASH_PAGE_SIZE;                    
		Mass_Memory_Size[0] = FLASH_SIZE;
		LED2_ON();
		return MAL_OK;
	}
  	LED2_OFF();
 
  	return MAL_FAIL;
}




define FLASH_PAGE_SIZE 0x800。





写速度如下,读速度无法测,因为空间太小,能存放的文件也太小,拷贝数据简直就是一瞬间的事: