OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 4226|回复: 5

fatfs 移植挂载不上,底层驱动都是好的

[复制链接]

1

主题

5

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
303
金钱
303
注册时间
2016-8-23
在线时间
49 小时
发表于 2016-8-24 09:22:08 | 显示全部楼层 |阅读模式
5金钱
用的STM32F207VET6,flash用的MX25L25735F,底层读写都没问题,但是f_mount(); 会在if (LD_WORD(&fs->win[BS_55AA]) != 0xAA55)返回数据,显示没有文件系统?这怎么处理

最佳答案

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

1

主题

5

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
303
金钱
303
注册时间
2016-8-23
在线时间
49 小时
 楼主| 发表于 2016-8-24 09:22:09 | 显示全部楼层
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165524
金钱
165524
注册时间
2010-12-1
在线时间
2116 小时
发表于 2016-8-24 20:32:51 | 显示全部楼层
检查底层代码就可以了。可以参考下我们的W25Qxx的例程(作为文件系统用,FATFS)
回复

使用道具 举报

1

主题

5

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
303
金钱
303
注册时间
2016-8-23
在线时间
49 小时
 楼主| 发表于 2016-8-25 08:57:21 | 显示全部楼层
正点原子 发表于 2016-8-24 20:32
检查底层代码就可以了。可以参考下我们的W25Qxx的例程(作为文件系统用,FATFS)

多谢,我的就是根据你们的例程写的代码,可是不行。。。
//擦除一个扇区
//eraseAddr:扇区地址 根据实际容量设置
//擦除一个山区的最少时间
void MX25XX_Erase_Sector(u32 eraseAddr)
{
    uint8_t   cmd = 0;

    cmd = sFLASH_MX_4kB_SECTOR_ERASE;
    eraseAddr &= sFLASH_4kB_SECTOR_ALIGN;

    SpiFlashWriteEn();

    SpiFlashWaitReady();

    sFLASH_CS_LOW();

    SpiFlashSendByte(cmd);
    SpiFlashSendByte((eraseAddr >> 24) & 0xFF);
    SpiFlashSendByte((eraseAddr >> 16) & 0xFF);
    SpiFlashSendByte((eraseAddr >> 8) & 0xFF);
    SpiFlashSendByte(eraseAddr & 0xFF);

    sFLASH_CS_HIGH();

    SpiFlashWaitReady();
}

//读取SPI FLASH
//在指定地址开始读取指定长度的数据
//pBuffer:数据存储区
//ReadAddr:开始读取的地址(32bit)
//NumByteToRead:要读取的字节数(最大65535)
void MX25XX_Read(u8* pBuffer,u32 ReadAddr,u16 NumByteToRead)
{
    uint32_t  i = 0;

    sFLASH_CS_LOW();

    SpiFlashSendByte((uint8_t)sFLASH_MX_READ_MEMORY_ARRAY);

    SpiFlashSendByte((ReadAddr >> 24) & 0xFF);
    SpiFlashSendByte((ReadAddr >> 16) & 0xFF);
    SpiFlashSendByte((ReadAddr >> 8) & 0xFF);
    SpiFlashSendByte(ReadAddr & 0xFF);
    // 写数据
    for (i = 0; i < NumByteToRead; i++)
    {
        while ((sFLASH_SPI->SR & SPI_I2S_FLAG_TXE) == (uint16_t)RESET);
        // 数据发送
        sFLASH_SPI->DR = sFLASH_DUMMY_BYTE;
        // 等待数据接收
        while ((sFLASH_SPI->SR & SPI_I2S_FLAG_RXNE) == (uint16_t)RESET);
        // 数据接收
        pBuffer = sFLASH_SPI->DR;
    }

    sFLASH_CS_HIGH();
}

//SPI在一页(0~65535)内写入少于256个字节的数据
//在指定地址开始写入最大256字节的数据
//pBuffer:数据存储区
//WriteAddr:开始写入的地址(32bit)
//NumByteToWrite:要写入的字节数(最大256),该数不应该超过该页的剩余字节数!!!
void MX25XX_Write_Page(u8* pBuffer,u32 WriteAddr,u16 NumByteToWrite)
{
    u16 i;
    SpiFlashWriteEn();
    sFLASH_CS_LOW();

    SpiFlashSendByte(sFLASH_MX_PAGE_PROGRAM);
    SpiFlashSendByte((WriteAddr >> 24) & 0xFF);
    SpiFlashSendByte((WriteAddr >> 16) & 0xFF);
    SpiFlashSendByte((WriteAddr >> 8) & 0xFF);
    SpiFlashSendByte(WriteAddr & 0xFF);

    for (i = 0; i < NumByteToWrite; i++)
    {
        SpiFlashSendByte(pBuffer);
    }

    sFLASH_CS_HIGH();

    SpiFlashWaitReady();
}

//无检验写SPI FLASH
//必须确保所写的地址范围内的数据全部为0XFF,否则在非0XFF处写入的数据将失败!
//具有自动换页功能
//在指定地址开始写入指定长度的数据,但是要确保地址不越界!
//pBuffer:数据存储区
//WriteAddr:开始写入的地址(32bit)
//NumByteToWrite:要写入的字节数(最大65535)
//CHECK OK
void MX25XX_Write_NoCheck(u8* pBuffer,u32 WriteAddr,u16 NumByteToWrite)
{
    u16 pageremain;
    pageremain = sFLASH_PAGE_SIZE - WriteAddr%sFLASH_PAGE_SIZE; //单页剩余的字节数
    if(NumByteToWrite<=pageremain) pageremain = NumByteToWrite;//不大于256个字节
    while(1)
    {
        MX25XX_Write_Page(pBuffer,WriteAddr,pageremain);
        if(NumByteToWrite == pageremain) break;//写入结束了
        else //NumByteToWrite>pageremain
        {
            pBuffer += pageremain;
            WriteAddr += pageremain;

            NumByteToWrite -= pageremain;                          //减去已经写入了的字节数
            if(NumByteToWrite>256) pageremain = 256; //一次可以写入256个字节
            else pageremain = NumByteToWrite;           //不够256个字节了
        }
    };
}

//写SPI FLASH
//在指定地址开始写入指定长度的数据
//该函数带擦除操作!
//pBuffer:数据存储区
//WriteAddr:开始写入的地址(32bit)
//NumByteToWrite:要写入的字节数(最大65535)
u8 MX25XX_BUFFER[4096];
void MX25XX_Write(u8* pBuffer,u32 WriteAddr,u16 NumByteToWrite)
{
    u32 secpos;
    u16 secoff;
    u16 secremain;
    u16 i;
    u8 * MX25XX_BUF;
    MX25XX_BUF = MX25XX_BUFFER;
    secpos = WriteAddr/4096;//扇区地址
    secoff = WriteAddr%4096;//在扇区内的偏移
    secremain = 4096-secoff;//扇区剩余空间大小
    //printf("ad:%X,nb:%X\r\n",WriteAddr,NumByteToWrite);//测试用
    if(NumByteToWrite <= secremain) secremain = NumByteToWrite;//不大于4096个字节
    while(1)
    {
        MX25XX_Read(MX25XX_BUF,secpos*4096,4096);//读出整个扇区的内容
        for(i=0; i<secremain; i++) //校验数据
        {
            if(MX25XX_BUF[secoff+i] != 0XFF)break;//需要擦除
        }
        if(i<secremain)//需要擦除
        {
            MX25XX_Erase_Sector(secpos);//擦除这个扇区
            for(i=0; i<secremain; i++)         //复制
            {
                MX25XX_BUF[i+secoff] = pBuffer;
            }
            MX25XX_Write_NoCheck(MX25XX_BUF,secpos*4096,4096);//写入整个扇区

        } else MX25XX_Write_NoCheck(pBuffer,WriteAddr,secremain);//写已经擦除了的,直接写入扇区剩余区间.
        if(NumByteToWrite == secremain)break;//写入结束了
        else//写入未结束
        {
            secpos++;//扇区地址增1
            secoff=0;//偏移位置为0

            pBuffer += secremain;  //指针偏移
            WriteAddr += secremain;//写地址偏移
            NumByteToWrite -= secremain;                                //字节数递减
            if(NumByteToWrite > 4096) secremain = 4096;        //下一个扇区还是写不完
            else secremain = NumByteToWrite;                        //下一个扇区可以写完了
        }
    };
}

#include "diskio.h"
#include "spi_flash.h"
#include "usbh_usr.h"
#include "malloc.h"

#define EX_FLASH 0        //外部flash,卷标为0
#define USB_DISK 1  //U盘,卷标为1


//对于MX25L25735F
//前28M字节给fatfs用,28M字节后,给客户自己用
#define FLASH_SECTOR_SIZE         512
u16        FLASH_SECTOR_COUNT = 2048*28;        //MX25L25735F,前28M字节给FATFS占用
#define FLASH_BLOCK_SIZE           8             //每个BLOCK有8个扇区       


//获得磁盘状态
DSTATUS disk_status (
    BYTE pdrv                /* Physical drive nmuber to identify the drive */
)
{
    return RES_OK;
}


//初始化磁盘
DSTATUS disk_initialize (
    BYTE pdrv                                /* Physical drive nmuber to identify the drive */
)
{
    u8 res=0;
    switch(pdrv)
    {
    case EX_FLASH:                //外部flash
        SpiFlashInit();  //MX25XX初始化
        break;
    case USB_DISK:                //U盘
        res=!USBH_UDISK_Status();//U盘连接成功,则返回1.否则返回0
        break;
    default:
        res=1;
    }
    if(res)return  STA_NOINIT;
    else return 0; //初始化成功
}


//读扇区
//pdrv:磁盘编号0~9
//*buff:数据接收缓冲首地址
//sector:扇区地址
//count:需要读取的扇区数
DRESULT disk_read (
    BYTE pdrv,                /* Physical drive nmuber to identify the drive */
    BYTE *buff,                /* Data buffer to store read data */
    DWORD sector,        /* Sector address in LBA */
    UINT count                /* Number of sectors to read */
)
{
    u8 res=0;
    if (!count)return RES_PARERR;//count不能等于0,否则返回参数错误
    switch(pdrv)
    {
    case EX_FLASH:        //外部flash
        for(; count>0; count--)
        {
            MX25XX_Read(buff,sector*FLASH_SECTOR_SIZE,FLASH_SECTOR_SIZE);
            sector++;
            buff+=FLASH_SECTOR_SIZE;
        }
        res = 0;
        break;
    case USB_DISK:        //U盘
        res = USBH_UDISK_Read(buff,sector,count);
        break;
    default:
        res = 1;
    }
    //处理返回值,将SPI_SD_driver.c的返回值转成ff.c的返回值
    if(res==0x00)return RES_OK;
    else return RES_ERROR;
}


//写扇区
//pdrv:磁盘编号0~9
//*buff:发送数据首地址
//sector:扇区地址
//count:需要写入的扇区数
DRESULT disk_write (
    BYTE pdrv,                        /* Physical drive nmuber to identify the drive */
    const BYTE *buff,        /* Data to be written */
    DWORD sector,                /* Sector address in LBA */
    UINT count                        /* Number of sectors to write */
)
{
    u8 res=0;
    if (!count)return RES_PARERR;//count不能等于0,否则返回参数错误
    switch(pdrv)
    {
    case EX_FLASH:        //外部flash
        for(; count>0; count--)
        {
            MX25XX_Write((u8*)buff,sector*FLASH_SECTOR_SIZE,FLASH_SECTOR_SIZE);
            sector++;
            buff+=FLASH_SECTOR_SIZE;
        }
        res=0;
        break;
    case USB_DISK:        //U盘
        res=USBH_UDISK_Write((u8*)buff,sector,count);
        break;
    default:
        res=1;
    }
    //处理返回值,将SPI_SD_driver.c的返回值转成ff.c的返回值
    if(res == 0x00)return RES_OK;
    else return RES_ERROR;
}


//其他表参数的获得
//pdrv:磁盘编号0~9
//ctrl:控制代码
//*buff:发送/接收缓冲区指针
DRESULT disk_ioctl (
    BYTE pdrv,                /* Physical drive nmuber (0..) */
    BYTE cmd,                /* Control code */
    void *buff                /* Buffer to send/receive control data */
)
{
    DRESULT res;
    if(pdrv==EX_FLASH)        //外部FLASH
    {
        switch(cmd)
        {
        case CTRL_SYNC:
            res = RES_OK;
            break;
        case GET_SECTOR_SIZE:
            *(WORD*)buff = FLASH_SECTOR_SIZE;
            res = RES_OK;
            break;
        case GET_BLOCK_SIZE:
            *(WORD*)buff = FLASH_BLOCK_SIZE;
            res = RES_OK;
            break;
        case GET_SECTOR_COUNT:
            *(DWORD*)buff = FLASH_SECTOR_COUNT;
            res = RES_OK;
            break;
        default:
            res = RES_PARERR;
            break;
        }
    } else if(pdrv==USB_DISK)        //U盘
    {
        switch(cmd)
        {
        case CTRL_SYNC:
            res = RES_OK;
            break;
        case GET_SECTOR_SIZE:
            *(WORD*)buff=512;
            res = RES_OK;
            break;
        case GET_BLOCK_SIZE:
            *(WORD*)buff=512;
            res = RES_OK;
            break;
        case GET_SECTOR_COUNT:
            *(DWORD*)buff=USBH_MSC_Param.MSCapacity;
            res = RES_OK;
            break;
        default:
            res = RES_PARERR;
            break;
        }
    } else res=RES_ERROR;//其他的不支持
    return res;
}


//获得时间
//User defined function to give a current time to fatfs module      */
//31-25: Year(0-127 org.1980), 24-21: Month(1-12), 20-16: Day(1-31) */
//15-11: Hour(0-23), 10-5: Minute(0-59), 4-0: Second(0-29 *2) */
DWORD get_fattime (void)
{
    return 0;
}


//动态分配内存
void *ff_memalloc (UINT size)
{
    return (void*)mymalloc(size);
}


//释放内存
void ff_memfree (void* mf)
{
    myfree(mf);
}
回复

使用道具 举报

19

主题

66

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
211
金钱
211
注册时间
2015-12-6
在线时间
47 小时
发表于 2016-8-30 22:19:57 | 显示全部楼层
你好,我也遇到了这个问题,请问是怎么解决这个问题的
回复

使用道具 举报

19

主题

66

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
211
金钱
211
注册时间
2015-12-6
在线时间
47 小时
发表于 2016-8-30 22:21:27 | 显示全部楼层

你好啊,我也在纠结这个问题,同样是格式化显示成功,但是f_mount()显示的是没有文件系统
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-5-29 05:54

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表