文件系统
从硬盘这一类的硬件操作,比如读地址,写地址,这种简单的硬件读写,到上层文件系统,串口对文件的读写操作,是个什么流程?
先看个底层SD卡的驱动程序
//SD¿¨CSD¼Ä´æÆ÷Êý¾Ý
typedef struct
{
u8 CSDStruct; /*!< CSD structure */
u8 SysSpecVersion; /*!< System specification version */
u8 Reserved1; /*!< Reserved */
u8 TAAC; /*!< Data read access-time 1 */
u8 NSAC; /*!< Data read access-time 2 in CLK cycles */
u8 MaxBusClkFrec; /*!< Max. bus clock frequency */
u16 CardComdClasses; /*!< Card command classes */
u8 RdBlockLen; /*!< Max. read data block length */
u8 PartBlockRead; /*!< Partial blocks for read allowed */
u8 WrBlockMisalign; /*!< Write block misalignment */
u8 RdBlockMisalign; /*!< Read block misalignment */
u8 DSRImpl; /*!< DSR implemented */
u8 Reserved2; /*!< Reserved */
u32 DeviceSize; /*!< Device Size */
u8 MaxRdCurrentVDDMin; /*!< Max. read current @ VDD min */
u8 MaxRdCurrentVDDMax; /*!< Max. read current @ VDD max */
u8 MaxWrCurrentVDDMin; /*!< Max. write current @ VDD min */
u8 MaxWrCurrentVDDMax; /*!< Max. write current @ VDD max */
u8 DeviceSizeMul; /*!< Device size multiplier */
u8 EraseGrSize; /*!< Erase group size */
u8 EraseGrMul; /*!< Erase group size multiplier */
u8 WrProtectGrSize; /*!< Write protect group size */
u8 WrProtectGrEnable; /*!< Write protect group enable */
u8 ManDeflECC; /*!< Manufacturer default ECC */
u8 WrSpeedFact; /*!< Write speed factor */
u8 MaxWrBlockLen; /*!< Max. write data block length */
u8 WriteBlockPaPartial; /*!< Partial blocks for write allowed */
u8 Reserved3; /*!< Reserded */
u8 ContentProtectAppli; /*!< Content protection application */
u8 FileFormatGrouop; /*!< File format group */
u8 CopyFlag; /*!< Copy flag (OTP) */
u8 PermWrProtect; /*!< Permanent write protection */
u8 TempWrProtect; /*!< Temporary write protection */
u8 FileFormat; /*!< File Format */
u8 ECC; /*!< ECC code */
u8 CSD_CRC; /*!< CSD CRC */
u8 Reserved4; /*!< always 1*/
} SD_CSD;
一堆寄存器,按顺序排列开。
//SD卡信息,包括CSD,CID等数据
typedef struct
{
SD_CSD SD_csd;
SD_CID SD_cid;
long long CardCapacity; //SD卡容量,单位;字节,最大支持2^64字节大小的卡
u32 CardBlockSize; //SD卡块大小
u16 RCA; //卡相对地址
u8 CardType; //卡类型
} SD_CardInfo;
extern SD_CardInfo SDCardInfo;//SD卡信息
又构成了一个SD卡信息的结构体,里面包括所有SD卡的信息,
//得到卡信息
//cardinfo:卡信息存储区
//返回值:错误状态
SD_Error SD_GetCardInfo(SD_CardInfo *cardinfo)
{
SD_Error errorstatus=SD_OK;
u8 tmp=0;
cardinfo->CardType=(u8)CardType; //¿¨ÀàÐÍ
cardinfo->RCA=(u16)RCA; //¿¨RCAÖµ
tmp=(u8)((CSD_Tab[0]&0xFF000000)>>24);
cardinfo->SD_csd.CSDStruct=(tmp&0xC0)>>6; //CSD½á¹¹
cardinfo->SD_csd.SysSpecVersion=(tmp&0x3C)>>2; //2.0ÐÒ黹û¶¨ÒåÕⲿ·Ö(Ϊ±£Áô),Ó¦¸ÃÊǺóÐøÐÒ鶨ÒåµÄ
cardinfo->SD_csd.Reserved1=tmp&0x03; //2¸ö±£Áôλ
tmp=(u8)((CSD_Tab[0]&0x00FF0000)>>16); //µÚ1¸ö×Ö½Ú
cardinfo->SD_csd.TAAC=tmp; //Êý¾Ý¶Áʱ¼ä1
tmp=(u8)((CSD_Tab[0]&0x0000FF00)>>8); //µÚ2¸ö×Ö½Ú
cardinfo->SD_csd.NSAC=tmp; //Êý¾Ý¶Áʱ¼ä2
tmp=(u8)(CSD_Tab[0]&0x000000FF); //µÚ3¸ö×Ö½Ú
一系列的初始化硬件操作
return errorstatus;//返回错误状态
}
接下来的初始化磁盘,读写磁盘
//初始化磁盘
DSTATUS disk_initialize (
BYTE pdrv /* Physical drive nmuber (0..) */
)
{
u8 res=0;
switch(pdrv)
{
case SD_CARD://SD¿¨
res=SD_Init();//SD卡初始化
break;
case EX_FLASH://外部FLASH
W25QXX_Init();
FLASH_SECTOR_COUNT=2048*12;//W25Q1218,前12M字节给FATFS占用
break;
default:
res=1;
}
if(res)return STA_NOINIT;
else return 0; //初始化成功
}
注意看FLASH_SECTOR_COUNT=2048*12;//W25Q1218,前12M字节给FATFS占用
这句话,这里面前12M字节就是给文件系统准备的,里面肯定包含了后面文件的所有信息,比如有多少文件,文件大小,文件类型等等等等。
到这里也复习了前面的内容,接下来讲我今天想通的一个事情,不是很复杂,Linux中使用secureCRT登录到ARM9开发板上,怎么就可以串口可以操作了呢?
其实这个很简单,就是把串口读上来的字符串作一个解析,要不然C语言里学字符串是干嘛的,还有去BAT大厂都要求操作字符串这种的,很重要,比如我从键盘输入一串“1:/system”,那我这里需要他打开盘符为1,目录为system的文件夹,我只需要把串口的数据后面加个\0,把这个作为目录进行操作,就像这样
while(1)
{
if(read_write_flag == 1)//дÎļþ
{
printf("The string is %s !\r\n",&USART_RX_BUF[1]);
//len = f_open( fp, "1:/text", FA_READ | FA_WRITE|FA_CREATE_ALWAYS);
len = f_mkdir(&USART_RX_BUF[1]);//1:/text
USART_SendData(USART1, (len+0x30)); //向串口1发送数据,创建目录后返回值,发送到串口上
if (len == 0 )
{
LED1 = !LED1;
delay_ms(1000);
LED1 = !LED1;
}
//f_unlink("1:/text");
read_write_flag = 0;
}
if(read_write_flag == 2)//输出目录下所有文件
{
printf("%d\r\n",readdir_list(&USART_RX_BUF[1]));
LED1 = !LED1;
delay_ms(1000);
LED1 = !LED1;
read_write_flag = 0;
}
char readdir_list( const u8 *path )
{
DIR dp;
FILINFO fno;
printf("%p\r\n",&dp);
if (f_opendir (&dp, path) == FR_OK)
{
while ( f_readdir ( &dp , &fno ) == FR_OK)
{
if ( !fno.fname[0] ) break;
printf("%s\r\n",fno.fname);
}
f_closedir ( &dp );
return 1;
}
return 2;
}
void usmart_scan(void)
{
u8 sta,len;
if(USART_RX_STA&0x8000)//串口接收完成?
{
if(USART_RX_BUF[0] == 0x31) read_write_flag = 1;
if(USART_RX_BUF[0] == 0x32) read_write_flag = 2;
len=USART_RX_STA&0x3fff; //得到此次接收到的数据长度
USART_RX_BUF[len]='\0'; //在末尾加入结束符
······
}
}
串口数据放在USART_RX_BUF里面,在usmart_scan里面,我判断第一个字符是什么,如果是1,则while(1)里执行创建目录,如果是2,则执行输出目录下所有文件,然后我接着数字后面就是目录1:/system,把这个目录接在
printf("%d\r\n",readdir_list(&USART_RX_BUF[1]));
里面,这样我就可以从串口发送21:/system就可以打开system目录里面的内容。
到这里,我就可以通过串口发送上来的数据对硬盘进行操作了,接下来就是做功能了,可以做Linux里面的ls命令,读上来之后,写个功能就可以,类似上面我写的那样。
需要做的就是把硬盘底层驱动做好,型号不同读写方式也不同,SD卡和内存芯片读写方式都不一样,把硬件连接到文件系统上
DSTATUS disk_initialize (
BYTE pdrv /* Physical drive nmuber (0..) */
)
{
u8 res=0;
switch(pdrv)
{
case SD_CARD://SD¿¨
res=SD_Init();//SD¿¨³õʼ»¯
break;
case EX_FLASH://Íⲿflash
W25QXX_Init();
FLASH_SECTOR_COUNT=2048*12;//W25Q1218,Ç°12M×Ö½Ú¸øFATFSÕ¼ÓÃ
break;
default:
res=1;
}
if(res)return STA_NOINIT;
else return 0; //³õʼ»¯³É¹¦
}
比如这个磁盘初始化这里,文件为diskio.c,这个是连接文件系统和硬盘的中间文件,文件系统内部如何实现的我不去理解,我的工作也不是写文件系统,我只需要知道它提供给我文件操作函数,如何配置硬盘底层硬件,就完事。
到此,文件系统可以完结了,没有过多的内容了,剩下的就是做功能,以后经验积累吧,
附加:我研究生实验台用的无纸记录仪,就是这么做的,功能是插上U盘就可以自动把数据写入U盘里面,形成一个.dat文件,这个就设计到文件系统了,我怀疑它里面跑的是ucos或者FreeRTos,现在看来,我的专业知识可以自己独立完成里面程序的编写了,非常不错,那一个仪表32路的3000块钱呢,老贵了,PCB虽然会画点,还没到能找工作的地步,只能自己看懂罢了,越来越觉得自己有价值,越来越值钱啦,接下来可能会学点WIFI模块,或者图形界面,驱动这一部分感觉自己已经两只脚踏进来了,哈哈哈