历史上的今天
今天是:2024年10月29日(星期二)
2020年10月29日 | STM32 USB 使用芯片内部flash模拟U盘
2020-10-29 来源:eefocus
这次是实现一个使用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无法格式化解决的那篇文章的调用代码。调用如下:
MAL_Read(lun , Offset , Data_Buffer, Mass_Block_Size[lun]);
MAL_Write(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 //操作等待时间
然后要编写MAL_Init()、MAL_Write()、MAL_Read()、MAL_GetStatus()这里不多做介绍,贴出代码:
#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 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 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 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; } 虽然说,我们上面定义了400KB留作空间,但,我们在电脑上只看见375K左右的空间,这属于正常现象。还有,之前在调代码的时候,又出现了无法格式化的问题,经过一番推敲,才发现是定义flash也的大小出现了问题,之前定义成1K,发现不想,修改成2K才成功,就是我们上面的 :# define FLASH_PAGE_SIZE 0x800。
史海拾趣
|
双绞线是将一对或一对以上的双绞线封装在一个绝缘外套中而形成的一种传输介质。 同轴电缆是由一根空心的外圆柱导体(铜网)和一根位于中心轴线的内导线(电缆铜芯)组成,并且内导线和圆柱导体及圆柱导体和外界之间都是用绝缘材料隔开。 ...… 查看全部问答> |
|
TI公司新出了Piccolo系列的C2000 DSC,大家觉得怎么样啊? 高效率32位CPU(TMS320C28xTM核) 具有40MHz/60MHz主频; 单周期执行一次32×32或两次16×16乘加(MAC); 改进型哈佛总线结构; 原子操作; 快速中断响应与处理; 统一的存储器设 ...… 查看全部问答> |
|
现在在职工作一年了,从事软件开发,经常和硬件打交道!算是一个嵌入式门口的程序员!发现在自己的能力增加到一定之后,对应用层代码的兴趣就没那么高啦。可是公司的产品很成熟,底层驱动都很稳定,不需要改动,所以平时也没有机会学到那方面知识, ...… 查看全部问答> |
|
AN900 ADI-DSP仿真器 - 支持BF561/BF54x/BF52x等ADI全系列DSP的仿真器 AnalogCN安诺电子 - http://www.analogcn.com 国内唯一专门针对ADI应用的中文技术网站 AN900 ADI-DSP仿真器 - 支持BF561/BF54x/BF52x等ADI全系列DSP的仿真器 http://www.analogcn.com/Shop/shop1/200801/20080102025545.html AN900 ADI-DSP仿真 ...… 查看全部问答> |
|
我毕业快要两年了,我们公司是工业仪表的计量产品的,我现在是做硬件,但是感觉基本上没我什么事可以做。PCB和软件搞定后才给我们了,我就是硬件调试和测试及维修工作,我现在基本和软件不沾边。数字芯片类的电路不比纯模拟电路,电路不用自己怎么 ...… 查看全部问答> |




