基于Xilinx平台MicroBlaze的SPI方式FatFs移植
FatFs是面向小型嵌入式系统的一种通用的FAT文件系统。它完全是由AISI C语言编写并且完全独立于底层的I/O介质。因此它可以很容易地不加修改地移植到其他的处理器当中,如8051、PIC、AVR、SH、Z80、H8、ARM等。FatFs支持FAT12、FAT16、FAT32等格式。
FatFs源码下载FatFs - Generic FAT Filesystem Module
下载下来后,目录结构由帮助文档(doc)和文件系统源码(src)构成:
打开源码我们会看到如下几个文件:
integer.h:文件中包含了一些数值类型定义。
diskio.c:包含底层存储介质的操作函数,这些函数需要用户自己实现,主要添加底层驱动函数。
ff.c:FatFs核心文件,文件管理的实现方法。该文件独立于底层介质操作文件的函数,利用这些函数实现文件的读写。(相当于C语言中的stdio.h)
ffconf.h:这个头文件包含了对FatFs功能配置的宏定义,通过修改这些宏定义就可以裁剪FatFs的功能。
在Xilinx平台MicroBlaze没有SD卡,所以我们只能以SPI的方式来进行移植。
移植步骤如下:
1.diskio.c中需要修改如下几个函数
1.
DSTATUS disk_status (
BYTE pdrv /* Physical drive nmuber to identify the drive */
)
{
DSTATUS stat;
int result;
switch (pdrv) {
case DEV_SPI :
result = spi_flash_status();
stat = RES_OK;
return stat;
case DEV_MMC :
return stat;
case DEV_USB :
return stat;
}
return STA_NOINIT;
}
2.
DSTATUS disk_initialize (
BYTE pdrv /* Physical drive nmuber to identify the drive */
)
{
DSTATUS stat;
int result;
switch (pdrv) {
case DEV_SPI :
result = spi_flash_init((u32)pdrv);
stat = RES_OK;
return stat;
case DEV_MMC :
return stat;
case DEV_USB :
return stat;
}
return STA_NOINIT;
}
3.
DRESULT disk_read (
BYTE pdrv, /* Physical drive nmuber to identify the drive */
BYTE *buff, /* Data buffer to store read data */
DWORD sector, /* Start sector in LBA */
UINT count /* Number of sectors to read */
)
{
DRESULT res;
int result;
switch (pdrv) {
case DEV_SPI :
sector+=1536;
result = spi_flash_read(sector*4096,count*4096,(u8*)buff);
res = RES_OK;
return res;
case DEV_MMC :
return res;
case DEV_USB :
return res;
}
return RES_PARERR;
}
4.
DRESULT disk_write (
BYTE pdrv, /* Physical drive nmuber to identify the drive */
const BYTE *buff, /* Data to be written */
DWORD sector, /* Start sector in LBA */
UINT count /* Number of sectors to write */
)
{
DRESULT res;
int result;
switch (pdrv) {
case DEV_SPI :
sector += 1536;
spi_flash_sector_erase(sector*4096);
result = spi_flash_write(sector*4096,count*4096,(u8*)buff);
res = RES_OK;
return res;
case DEV_MMC :
return res;
case DEV_USB :
return res;
}
return RES_PARERR;
}
5.
DRESULT disk_ioctl (
BYTE pdrv, /* Physical drive nmuber (0..) */
BYTE cmd, /* Control code */
void *buff /* Buffer to send/receive control data */
)
{
DRESULT res;
int result;
switch (pdrv) {
case DEV_SPI:
switch(cmd)
{
case GET_SECTOR_COUNT:
*(DWORD *) buff = 512;
break;
case GET_SECTOR_SIZE:
*(DWORD *) buff = 4096;
break;
case GET_BLOCK_SIZE:
*(DWORD *) buff = 1;
break;
}
res = RES_OK;
return res;
case DEV_RAM :
return res;
case DEV_MMC :
return res;
case DEV_USB :
return res;
}
return RES_PARERR;
}
6.
DWORD get_fattime(void)
{
return ((DWORD)(2022 - 1980) << 25) //YEAR
| ((DWORD)12 << 21) //MONTH
| ((DWORD)20 << 16) //DAY
| ((DWORD)7 << 11) //HOUR
| ((DWORD)20 << 5) //MINUTE
| ((DWORD)30 << 1); //SECOND
}
完整代码如下:
#include "ff.h" /* Obtains integer types */
#include "diskio.h" /* Declarations of disk functions */
#include "spi_flash.h"/* Definitions of physical drive number for each drive */
#define DEV_SPI 0 /* Example: Map Ramdisk to physical drive 0 */
#define DEV_RAM 1 /* Example: Map MMC/SD card to physical drive 1 */
#define DEV_MMC 2 /* Example: Map USB MSD to physical drive 2 */
#define DEV_USB 3 /* Example: Map USB MSD to physical drive 2 *//*-----------------------------------------------------------------------*/
/* Get Drive Status */
/*-----------------------------------------------------------------------*/DSTATUS disk_status (BYTE pdrv /* Physical drive nmuber to identify the drive */
)
{DSTATUS stat;int result;switch (pdrv) {case DEV_SPI ://result = RAM_disk_status();result = spi_flash_status();// translate the reslut code herestat = RES_OK;return stat;case DEV_MMC ://result = MMC_disk_status();// translate the reslut code herereturn stat;case DEV_USB ://result = USB_disk_status();// translate the reslut code herereturn stat;}return STA_NOINIT;
}/*-----------------------------------------------------------------------*/
/* Inidialize a Drive */
/*-----------------------------------------------------------------------*/DSTATUS disk_initialize (BYTE pdrv /* Physical drive nmuber to identify the drive */
)
{DSTATUS stat;int result;switch (pdrv) {case DEV_SPI :result = spi_flash_init((u32)pdrv);// translate the reslut code herestat = RES_OK;return stat;case DEV_MMC ://result = MMC_disk_initialize();// translate the reslut code herereturn stat;case DEV_USB ://result = USB_disk_initialize();// translate the reslut code herereturn stat;}return STA_NOINIT;
}/*-----------------------------------------------------------------------*/
/* Read Sector(s) */
/*-----------------------------------------------------------------------*/DRESULT disk_read (BYTE pdrv, /* Physical drive nmuber to identify the drive */BYTE *buff, /* Data buffer to store read data */DWORD sector, /* Start sector in LBA */UINT count /* Number of sectors to read */
)
{DRESULT res;int result;switch (pdrv) {case DEV_SPI :// translate the arguments heresector+=1536;result = spi_flash_read(sector*4096,count*4096,(u8*)buff);//result = RAM_disk_read(buff, sector, count);// translate the reslut code hereres = RES_OK;return res;case DEV_MMC :// translate the arguments here//result = MMC_disk_read(buff, sector, count);// translate the reslut code herereturn res;case DEV_USB :// translate the arguments here//result = USB_disk_read(buff, sector, count);// translate the reslut code herereturn res;}return RES_PARERR;
}/*-----------------------------------------------------------------------*/
/* Write Sector(s) */
/*-----------------------------------------------------------------------*/#if FF_FS_READONLY == 0DRESULT disk_write (BYTE pdrv, /* Physical drive nmuber to identify the drive */const BYTE *buff, /* Data to be written */DWORD sector, /* Start sector in LBA */UINT count /* Number of sectors to write */
)
{DRESULT res;int result;switch (pdrv) {case DEV_SPI :// translate the arguments heresector += 1536;spi_flash_sector_erase(sector*4096);result = spi_flash_write(sector*4096,count*4096,(u8*)buff);// translate the reslut code hereres = RES_OK;return res;case DEV_MMC :// translate the arguments here//result = MMC_disk_write(buff, sector, count);// translate the reslut code herereturn res;case DEV_USB :// translate the arguments here//result = USB_disk_write(buff, sector, count);// translate the reslut code herereturn res;}return RES_PARERR;
}#endif/*-----------------------------------------------------------------------*/
/* Miscellaneous Functions */
/*-----------------------------------------------------------------------*/DRESULT disk_ioctl (BYTE pdrv, /* Physical drive nmuber (0..) */BYTE cmd, /* Control code */void *buff /* Buffer to send/receive control data */
)
{DRESULT res;int result;switch (pdrv) {case DEV_SPI:switch(cmd){case GET_SECTOR_COUNT:*(DWORD *) buff = 512;break;case GET_SECTOR_SIZE:*(DWORD *) buff = 4096;break;case GET_BLOCK_SIZE:*(DWORD *) buff = 1;break;}res = RES_OK;return res;case DEV_RAM :// Process of the command for the RAM drivereturn res;case DEV_MMC :// Process of the command for the MMC/SD cardreturn res;case DEV_USB :// Process of the command the USB drivereturn res;}return RES_PARERR;
}DWORD get_fattime(void)
{return ((DWORD)(2022 - 1980) << 25) //YEAR| ((DWORD)12 << 21) //MONTH| ((DWORD)20 << 16) //DAY| ((DWORD)7 << 11) //HOUR| ((DWORD)20 << 5) //MINUTE| ((DWORD)30 << 1); //SECOND
}
#include "spi_flash.h"代码
#ifndef __SPI_FLASH_H_
#define __SPI_FLASH_H_#include "xparameters.h"
#include "xspi.h"
#include "xil_exception.h"#define SPI_DEVICE_ID XPAR_QSPI_FLASH_DEVICE_ID
#define SPI_SELECT 0x01
#define SPI_WRITE 0x02
#define SPI_READ 0x03
#define SPI_RDSR1 0x05
#define SPI_WREN 0x06
#define SPI_SE 0xD8
#define SPI_RDID 0x9F#define READ_WRITE_EXTRA_BYTES 4
#define RDSR1_BYTES 2
#define WREN_BYTES 1
#define SE_BYTES 4
#define FLASH_SR_IS_READY_MASK 0x01
#define PAGE_SIZE 256#define SPI_DATA_REG 0
#define SPI_CTRL_REG 1
#define SPI_STS_REG 2#define SPI_CTRL_RXRST 0x01
#define SPI_CTRL_TXRST 0x02#define SPI_STS_RDV 0x01
#define SPI_STS_WRV 0x02
#define SPI_STS_WRB 0x04#define STAT_OK 0x0A
#define STAT_ERR 0x11
#define CMD_SET_FPWM 0x01
#define CMD_SET_SPWM 0x02
#define CMD_SET_SCDAC 0x03
#define CMD_SET_SVDAC 0x04
#define CMD_RD_V_DCDC 0x05
#define CMD_RD_V_OUT 0x06
#define CMD_RD_I_OUT 0x07
#define CMD_RD_I_SEN 0x08
#define CMD_RD_SW 0x09#define SPI_DRV_CS 0x100
#define SPI_DRV_RD 0x200
#define SPI_FLASH_SS 0x400
#define SPI_IO_SS 0x800int spi_flash_init(u32 dev_id);
int spi_flash_read(u32 addr, u32 count, u8* buf);
int spi_flash_read_l(u32 Addr, u32 ByteCount);
int spi_flash_wait(void);
void spi_flash_sector_erase(u8 sector);
void spi_flash_set_write_enable(void);
int spi_flash_write(u32 spi_addr, u32 count, u8* buf);
int spi_flash_get_id(void);#endif
spi_flash.c代码:
#include "spi_flash.h"
#include "xspi_l.h"static XSpi Spi;
static u8 ReadBuffer[PAGE_SIZE + READ_WRITE_EXTRA_BYTES + 4];
static u8 WriteBuffer[PAGE_SIZE + READ_WRITE_EXTRA_BYTES];int spi_flash_init(u32 dev_id){int Status;XSpi_Config *ConfigPtr;ConfigPtr = XSpi_LookupConfig(dev_id);if (ConfigPtr == NULL)return XST_DEVICE_NOT_FOUND;Status = XSpi_CfgInitialize(&Spi, ConfigPtr, ConfigPtr->BaseAddress);if (Status != XST_SUCCESS)return XST_FAILURE;Status = XSpi_SetOptions(&Spi, XSP_MASTER_OPTION |XSP_MANUAL_SSELECT_OPTION);if(Status != XST_SUCCESS)return XST_FAILURE;Status = XSpi_SetSlaveSelect(&Spi, SPI_SELECT);if(Status != XST_SUCCESS)return XST_FAILURE;XSpi_Start(&Spi);XSpi_IntrGlobalDisable(&Spi); // Pooled modereturn XST_SUCCESS;
}
/******************************************************************************** Read data from SPI Flash* @param u32 Address* @param u32 Count* @param u8* Buffer* @return Operation Status******************************************************************************/
int spi_flash_read(u32 spi_addr, u32 count, u8* buf){u32 i, block_size, page_rem, buf_rem;u32 buf_addr = 0;while(buf_addr < count){page_rem = 0x0100 - (spi_addr & 0x00ff);buf_rem = count - buf_addr;block_size = (buf_rem > page_rem) ? page_rem : buf_rem;if(spi_flash_read_l(spi_addr, block_size) != XST_SUCCESS)return XST_FAILURE;for(i = 0; i < block_size; i++)buf[buf_addr + i] = ReadBuffer[i + READ_WRITE_EXTRA_BYTES];spi_addr += block_size;buf_addr += block_size;}return XST_SUCCESS;
}int spi_flash_read_l(u32 Addr, u32 ByteCount){int Status;Status = spi_flash_wait();if(Status != XST_SUCCESS)return XST_FAILURE;WriteBuffer[0] = SPI_READ;WriteBuffer[1] = (u8) (Addr >> 16);WriteBuffer[2] = (u8) (Addr >> 8);WriteBuffer[3] = (u8) Addr;return XSpi_Transfer(&Spi, WriteBuffer, ReadBuffer,(ByteCount + READ_WRITE_EXTRA_BYTES));
}
/******************************************************************************** Read flash status register* @param Spi Driver Instance* @return Status register contents******************************************************************************/
int spi_flash_status(void){WriteBuffer[0] = SPI_RDSR1;return XSpi_Transfer(&Spi, WriteBuffer, ReadBuffer, RDSR1_BYTES);
}int spi_flash_wait(void){while(1) {if(spi_flash_status() != XST_SUCCESS)return XST_FAILURE;if((ReadBuffer[1] & FLASH_SR_IS_READY_MASK) == 0)break;}return XST_SUCCESS;
}void spi_flash_set_write_enable(void){WriteBuffer[0] = SPI_WREN;XSpi_Transfer(&Spi, WriteBuffer, NULL, WREN_BYTES);
}void spi_flash_sector_erase(u8 sector){spi_flash_set_write_enable();WriteBuffer[0] = SPI_SE;WriteBuffer[1] = sector;WriteBuffer[2] = 0;WriteBuffer[3] = 0;XSpi_Transfer(&Spi, WriteBuffer, ReadBuffer, SE_BYTES);spi_flash_wait();}int spi_flash_write_buf(u32 spi_addr, u32 count, u8* buf){int i;spi_flash_wait();spi_flash_set_write_enable();WriteBuffer[0] = SPI_WRITE;WriteBuffer[1] = (spi_addr >> 16) & 0xFF;WriteBuffer[2] = (spi_addr >> 8) & 0xFF;WriteBuffer[3] = spi_addr & 0xFF;for(i = 0; i < count; i++){WriteBuffer[4 + i] = buf[i];}XSpi_Transfer(&Spi, WriteBuffer, NULL, (count + READ_WRITE_EXTRA_BYTES));return XST_SUCCESS;
}int spi_flash_write(u32 spi_addr, u32 count, u8* buf){u32 cnt = count;u32 pointer = 0;u32 page_rem, block_size;u32 cur_addr = spi_addr;while(cnt){if((cur_addr & 0xFFFF) == 0x0000){spi_flash_sector_erase(cur_addr >> 16);}page_rem = PAGE_SIZE - (cur_addr & 0xFF);block_size = (cnt > page_rem) ? page_rem : cnt;spi_flash_write_buf((cur_addr+pointer), block_size, (buf+pointer));pointer += block_size;cnt -= block_size;}return XST_SUCCESS;
}int spi_flash_get_id(void){u32 id;WriteBuffer[0] = SPI_RDID;XSpi_Transfer(&Spi, WriteBuffer, ReadBuffer, 4);id = (ReadBuffer[1] << 16) | (ReadBuffer[2] << 8) | ReadBuffer[3];return id;
}
2.修改ffconf.h
#define FF_MAX_SS 4096
3.测试FatFs
#include "xparameters.h" /* SDK generated parameters */
#include "FatFs/spi_flash.h"
#include "xil_printf.h"
#include "FatFs/ff.h"
#include "xil_cache.h"
#include "xplatform_info.h"/************************** Constant Definitions *****************************//**************************** Type Definitions *******************************//***************** Macros (Inline Functions) Definitions *********************//************************** Function Prototypes ******************************/
int FfsSdPolledExample(void);/************************** Variable Definitions *****************************/
static FIL fil; /* File object */
static FATFS fatfs;
/** To test logical drive 0, FileName should be "0:/<File name>" or* "<file_name>". For logical drive 1, FileName should be "1:/<file_name>"*/
static char FileName[32] = "Test.bin";
static char *SD_File;#ifdef __ICCARM__
#pragma data_alignment = 32
u8 DestinationAddress[10*1024];
#pragma data_alignment = 32
u8 SourceAddress[10*1024];
#else
u8 DestinationAddress[10*1024] __attribute__ ((aligned(32)));
u8 SourceAddress[10*1024] __attribute__ ((aligned(32)));
#endif#define TEST 7/*****************************************************************************/
/**
*
* Main function to call the SD example.
*
* @param None
*
* @return XST_SUCCESS if successful, otherwise XST_FAILURE.
*
* @note None
*
******************************************************************************/
int main(void)
{int Status;xil_printf("SD Polled File System Example Test \r\n");Status = FfsSdPolledExample();if (Status != XST_SUCCESS) {xil_printf("SD Polled File System Example Test failed \r\n");return XST_FAILURE;}xil_printf("Successfully ran SD Polled File System Example Test \r\n");return XST_SUCCESS;}/*****************************************************************************/
/**
*
* File system example using SD driver to write to and read from an SD card
* in polled mode. This example creates a new file on an
* SD card (which is previously formatted with FATFS), write data to the file
* and reads the same data back to verify.
*
* @param None
*
* @return XST_SUCCESS if successful, otherwise XST_FAILURE.
*
* @note None
*
******************************************************************************/
int FfsSdPolledExample(void)
{FRESULT Res;UINT NumBytesRead;UINT NumBytesWritten;u32 BuffCnt;BYTE work[FF_MAX_SS];u32 FileSize = (8*1024);/** To test logical drive 0, Path should be "0:/"* For logical drive 1, Path should be "1:/"*/TCHAR *Path = "0:/";for(BuffCnt = 0; BuffCnt < FileSize; BuffCnt++){SourceAddress[BuffCnt] = TEST + BuffCnt;}/** Register volume work area, initialize device*/Res = f_mount(&fatfs, Path, 0);if (Res != FR_OK) {return XST_FAILURE;}/** Path - Path to logical driver, 0 - FDISK format.* 0 - Cluster size is automatically determined based on Vol size.*/Res = f_mkfs(Path, FM_FAT, 0, work, sizeof work);if (Res != FR_OK) {return XST_FAILURE;}/** Open file with required permissions.* Here - Creating new file with read/write permissions. .* To open file with write permissions, file system should not* be in Read Only mode.*/SD_File = (char *)FileName;Res = f_open(&fil, SD_File, FA_CREATE_ALWAYS | FA_WRITE | FA_READ);if (Res) {return XST_FAILURE;}/** Pointer to beginning of file .*/Res = f_lseek(&fil, 0);if (Res) {return XST_FAILURE;}/** Write data to file.*/Res = f_write(&fil, (const void*)SourceAddress, FileSize,&NumBytesWritten);if (Res) {return XST_FAILURE;}/** Pointer to beginning of file .*/Res = f_lseek(&fil, 0);if (Res) {return XST_FAILURE;}/** Read data from file.*/Res = f_read(&fil, (void*)DestinationAddress, FileSize,&NumBytesRead);if (Res) {return XST_FAILURE;}/** Data verification
// */
// for(BuffCnt = 0; BuffCnt < FileSize; BuffCnt++){
// if(SourceAddress[BuffCnt] != DestinationAddress[BuffCnt]){
// return XST_FAILURE;
// }
// }/** Close file.*/Res = f_close(&fil);if (Res) {return XST_FAILURE;}return XST_SUCCESS;
}
测试完成。
具体每个函数的参数和功能介绍参考:STM32F429入门(二十二):SPI-FatFs文件系统_郑烯烃快去学习的博客-CSDN博客
基于Xilinx平台MicroBlaze的SPI方式FatFs移植相关推荐
- linux gianfar 网口驱动源码,基于MPC8313ERDB平台的Marvell88E1111型网卡驱动移植(uboot+kernel)...
最近一个月挣扎于千兆网的设备驱动移植,现在终于弄出来了,虽然有点累但是收获还是挺多的. 进入主题前,首先要感谢网友gorilla0123,他的博客给了我很多启发,在此非常感谢.我建议做网卡驱动这方面的 ...
- 基于zynq7000平台的vxWorks6.9移植(上)
1 致谢 编写本文档的目的在于指导用户如何移植基于z7平台的vxWorks6.9系统.移植之前首先感谢西安迅尔电子嵌入式工程师庞国强,本次是基于前者总结资料的基础上进行的完善,帮助新手可以以更少的指导 ...
- 基于Xilinx XCZU9EG与ADRV9009 开源无线通信算法验证平台
**基于Xilinx XCZU9EG与ADRV9009 开源无线通信算法验证平台** 1.基于Xilinx XCZU9EG与ADRV9009 开源无线通信算法验证平台硬件介绍 小疆XJSOM是基于Xi ...
- 基于xilinx Zynq UltraScale MPSoC平台的核心板及开发板介绍-米尔科技
近日,米尔科技推出国内首款基于xilinx Zynq UltraScale+MPSoC 平台的核心板及开发板.其优势主要有:采用16纳米制程,相比Znyq7000系列每瓦性能提升5倍,且单芯片融合4核 ...
- 基于xilinx异构平台上视频采集分析
1.设备树结构 xilinx平台端 vcap_csi {compatible = "xlnx,video";dmas = <&Video_IN_1ch_v_frmbu ...
- 如何学习嵌入式系统(基于ARM平台)
一.嵌入式系统的概念 着重理解"嵌入"的概念 主要从三个方面上来理解. 1.从硬件上,将基于CPU的处围器件,整合到CPU芯片内部,比如早期基于X86体系结构 ...
- 基于Xilinx Kintex-7系列FPGA高端设计的TLK7-EVM评估板简介
TLK7-EVM评估板简介 创龙科技TLK7-EVM是一款基于Xilinx Kintex-7系列FPGA设计的高端评估板,由核心板和评估底板组成.核心板经过专业的PCB Layout和高低温测试验证, ...
- C6678信号处理板资料保存:基于Xilinx Virtex-6 XC6VLX240T 和TI DSP TMS320C6678的信号处理板204
基于Xilinx Virtex-6 XC6VLX240T 和TI DSP TMS320C6678的信号处理板 1.板卡概述 板卡由我公司自主研发,基于VPX架构,主体芯片为两片 TI DSP TMS ...
- 基于Xilinx FPGA生态,加速提升视频处理质量
随着5G开启万物互联的崭新纪元,用户.流量.应用场景不断扩张,视频服务不仅会深入渗透全产业领域,也将为各行各业的产品应用增值赋能.不断提升的存储.传输与计算资源,从分辨率.码率.色彩与传输稳定性上全方 ...
最新文章
- vmware虚拟机启动centOs黑屏
- windows下利用sox批量将PCM转为WAV
- CSS清浮动处理(Clear与BFC)
- mysql 5.7.17 rpm安装_MySQL5.7.17 RPM方式安装
- redis数据结构小结
- japid-conf目录文件配置
- 白话讲解:消息队列到底解决了什么问题?
- C# 编译或者解释?
- 【语音识别】基于matlab隐马尔可夫模型(HMM)孤立字语音识别【含Matlab源码 576期】
- 虚拟机如何做服务器系统,sap虚拟机作为服务器(sap系统虚拟机)
- android apk自动安装包下载,Android 实现apk文件下载并自动安装
- win11系统完全使用ie浏览器的方法
- unity--常用物理公式
- 使用POI给word文档加水印
- 湖南省第十届蓝狐网络杯大学生计算机程序设计竞赛,2019年湖南省大学生计算机程序设计竞赛 (HNCPC2019) 简要题解...
- 图像识别VPU——易用的嵌入式AI支持深度学习平台介绍
- SE 的 ONNX 图
- 【ELM】动态自适应可变加权极限学习机ELM预测(Matlab代码实现)
- linux自学笔记(三)
- mac版思维导图软件,思维导图怎么画