野火电子论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 641|回复: 2

FATFS源码移植的问题

[复制链接]
回帖奖励 50 火花 回复本帖可获得 10 火花奖励! 每人限 1 次
发表于 2023-8-20 23:11:49 | 显示全部楼层 |阅读模式

文件系统的挂载和初始化都没问题,问题出在了f_open,f_open的错误码为FR_WRITE_PROTECTED

FR_WRITE_PROTECTED好像表示不能创建打开/写文件了

不知道问题出在哪里,求助各位大佬

main.c中有关FATFS的内容如下:

FATFS flash_fs;
FRESULT status;
BYTE work[FF_MAX_SS];
FIL file;
uint8_t write_buffer[] = "hehehehehehehehehehe";
UINT writtenbyte;

int main(void)
{
        HAL_Init();
        SystemClock_Config();
        MX_GPIO_Init();
        MX_SPI1_Init();
        MX_USART1_UART_Init();

    printf("\r\nFATFS 文件系统测试例程\r\n");

    /* 挂载和初始化文件系统 */
    status = f_mount(&flash_fs, "0:", 1);
    if(status == FR_NO_FILESYSTEM)
    {
        printf("文件系统挂载失败,原因是没有文件系统\n");
        printf("正在格式化文件系统\n");
        status = f_mkfs("0:", NULL, work, sizeof work);
        if(status != FR_OK)
        {
            printf("格式化文件系统失败,错误码为(%d)\n", status);
        }
        else
        {
            printf("格式化文件系统成功\n");
            f_mount(NULL, "0:", 1);
            f_mount(&flash_fs, "0:", 1);
        }
    }
    else if(status != FR_OK)
    {
        printf("文件系统挂载失败,失败码为(%d)\n", status);
    }
    else
    {
        printf("文件系统挂载成功,可以进行读写测试!\n");
    }

    /* 写文件测试 */
    printf("\r\n写文件测试\r\n");
    status = f_open(&file, "0:测试文档.txt", FA_CREATE_ALWAYS | FA_WRITE);
    if(status != FR_OK)
    {
        printf("文件打开/创建失败,失败码为(%d)\n", status);
    }
    else
    {
        printf("文件打开/创建成功\n");
        printf("开始写文件\n");
        status = f_write(&file, write_buffer, sizeof(write_buffer), &writtenbyte);
        if(status != FR_OK)
        {
            printf("写文件失败,失败码为(%d)\n", status);
        }
        else
        {
            printf("写文件成功\n");
            printf("写进文件的内容是%s,写了%d个字节\n", write_buffer, writtenbyte);
        }
    }
}

现象如下:

屏幕截图2023-08-20225909.png


diskio.c中有关内容如下:

#define DEV_FLASH       0

DSTATUS disk_status (
    BYTE pdrv       /* Physical drive nmuber to identify the drive */
)
{
    DSTATUS stat;
    int result;

    switch (pdrv) {

    case DEV_FLASH :
        result = Read_FLASH_JEDECID();

        // translate the reslut code here
        if(result == W25Q64_JEDECID)
        {
            stat &= ~ STA_NOINIT;
        }
        else
        {
            stat = STA_NOINIT;
        }

        return stat;
    }

    return STA_NOINIT;
}

DSTATUS disk_initialize (
    BYTE pdrv               /* Physical drive nmuber to identify the drive */
)
{
    DSTATUS stat;

    switch (pdrv) {

    case DEV_FLASH :
        WakeUp();
        stat = disk_status(pdrv);

        return stat;
    }

    return STA_NOINIT;
}

DRESULT disk_write (
    BYTE pdrv,          /* Physical drive nmuber to identify the drive */
    const BYTE *buff,   /* Data to be written */
    LBA_t sector,       /* Start sector in LBA */
    UINT count          /* Number of sectors to write */
)
{
    DRESULT res;
    uint32_t EraseCount;
    LBA_t sector_temp;

    switch (pdrv) {

    case DEV_FLASH :
        sector += (2048/4);
        sector_temp = sector;
        EraseCount = count;
        while(EraseCount--)
        {
            SectorErase(sector_temp*4096);
            sector_temp += 4096;
        }

        BufferWrite(sector*4096, count*4096, (BYTE *)buff);
        res = RES_OK;

        return res;
    }

    return RES_PARERR;
}

> 说明: > > disk_initialize中没有初始化flash是因为main函数中已经在使用文件系统前就已经初始化完成,所以就没再初始化flash


flash的bsp有关如下:

static uint8_t Read_And_Receive_Byte(uint8_t Byte)
{
    HAL_StatusTypeDef FunctionStatus;
    uint8_t TxData[1];
    uint8_t RxData[1];
    TxData[0] = Byte;
    FunctionStatus = HAL_SPI_TransmitReceive(&hspi1, TxData, RxData, 1, 0xFFF);
    if(FunctionStatus != HAL_OK)
    {
        return FunctionStatus;
    }
    return RxData[0];
}

void PageWrite(uint32_t PageAddress, uint32_t NumByteToWrite, uint8_t * WriteData)
{
    WriteEnable();
    FLASH_COMMUNICATE_START();
    Read_And_Receive_Byte(PageProgram_CODE);
    Read_And_Receive_Byte((PageAddress&0xFF0000)>>16);
    Read_And_Receive_Byte((PageAddress&0xFF00)>>8);
    Read_And_Receive_Byte(PageAddress&0xFF);
    if(NumByteToWrite > FLASH_PerPageWriteSize)
    {
        NumByteToWrite = FLASH_PerPageWriteSize;
        FLASH_INFO("Page Write Number is OverFlow");
    }
    while(NumByteToWrite--)
    {
        Read_And_Receive_Byte(*WriteData);
        WriteData++;
    }
    FLASH_COMMUNICATE_STOP();
    WaitForWriteEnd();
}

void BufferWrite(uint32_t PageAddress, uint32_t NumByteToWrite, uint8_t * WriteData)
{
    // 在一个页的什么位置
    uint8_t WhichNumOfPage;
    // 距离下一个页还剩多少
    uint8_t NumToNextPage;
    // 需要写多少次整页
    uint8_t NumPageToWrite;
    // 写完所有整页后还剩写多少字节
    uint8_t NumByteToFinalWrite;
    WhichNumOfPage = PageAddress % FLASH_PageSize;
    NumToNextPage = FLASH_PageSize - WhichNumOfPage;
    NumPageToWrite = NumByteToWrite / FLASH_PageSize;
    NumByteToFinalWrite = NumByteToWrite % FLASH_PageSize;

    // 地址对齐
    if(WhichNumOfPage == 0)
    {
        // 不足写一整页
        if(NumPageToWrite == 0)
        {
            PageWrite(PageAddress, NumByteToWrite, WriteData);
        }
        // 足够写一页
        else
        {
            while(NumPageToWrite--)
            {
                PageWrite(PageAddress, FLASH_PageSize, WriteData);
                PageAddress += FLASH_PageSize;
                WriteData += FLASH_PageSize;
            }
            PageWrite(PageAddress, NumByteToFinalWrite, WriteData);
        }
    }
    // 地址未对齐
    else
    {
        // 不足写一整页
        if(NumPageToWrite == 0)
        {
            // 写的数量不足到下一页
            if(NumByteToWrite <= NumToNextPage)
            {
                PageWrite(PageAddress, NumByteToWrite, WriteData);
            }
            // 写的数量足够到下一页
            else
            {
                PageWrite(PageAddress, NumToNextPage, WriteData);
                PageAddress += NumToNextPage;
                WriteData += NumToNextPage;
                PageWrite(PageAddress, NumByteToWrite - NumToNextPage, WriteData);
            }
        }
        // 足够写一页
        else
        {
            PageWrite(PageAddress, NumToNextPage, WriteData);
            PageAddress += NumToNextPage;
            WriteData += NumToNextPage;
            NumByteToWrite -= NumToNextPage;

            NumPageToWrite = NumByteToWrite / FLASH_PageSize;
            NumByteToFinalWrite = NumByteToWrite % FLASH_PageSize;  

            while(NumPageToWrite--)
            {
                PageWrite(PageAddress, FLASH_PageSize, WriteData);
                PageAddress += FLASH_PageSize;
                WriteData += FLASH_PageSize;
            }
            PageWrite(PageAddress, NumByteToFinalWrite, WriteData);
        }
    }
}

个人觉得问题应该不存在flash的bsp中,因为bsp中的各个API都经过测试都是可以正常使用的

回复

使用道具 举报

 楼主| 发表于 2023-8-21 15:15:12 | 显示全部楼层

真相了,兄弟们,原因竟然真的出在了flash的bsp中

我们都知道大部分型号的FLASH都有着以下的编程要求:

  1. 擦除和写入前需要使能写入
  2. 写入数据前必须先擦除
  3. 擦除和写入后需要等待FLASH内部时序是否完成

这里报写保护的错误就出现在了擦除和写入后需要等待FLASH内部时序是否完成这一步

错误代码如下:

#define MAX_TimeOut (uint32_t)0x5000

static void WaitForWriteEnd(void)
{
    uint8_t RegStatus;
    uint32_t SPITimeout;
    FLASH_COMMUNICATE_START();
        SPITimeout = MAX_TimeOut;
    Read_And_Receive_Byte(ReadStatusRegister1_CODE);
    do
    {
        RegStatus = Read_And_Receive_Byte(Dummy_Byte);
        if((SPITimeout--) == 0)
        {
            printf("Wait For Write End Time out!\n");
            return ;
        }
    }
    while((RegStatus & 1) == SET);
    FLASH_COMMUNICATE_STOP();
}
  • 初看好像没有什么问题,问题出在这个SPITimeout的变量,这个变量好像会被优化掉,在函数内加__IO也不行,只能把它拿出来放在全局变量中,修改后如下:

  • #define MAX_TimeOut (uint32_t)0x5000
    
    static __IO uint32_t  SPITimeout = MAX_TimeOut;
    
    static void WaitForWriteEnd(void)
    {
      uint8_t RegStatus;
      SPITimeout = MAX_TimeOut;
      FLASH_COMMUNICATE_START();
      Read_And_Receive_Byte(ReadStatusRegister1_CODE);
      do
      {
          RegStatus = Read_And_Receive_Byte(Dummy_Byte);
          if((SPITimeout--) == 0)
          {
              FLASH_ERROR("Wait For Write End Time out!");
              return ;
          }
      }
      while((RegStatus & 1) == SET);
      FLASH_COMMUNICATE_STOP();
    }

不过,错误的等待FLASH内部时序是否完成的函数在SPI FLASH的实验中依然好使

但是还是不知道为什么等待FLASH内部时序是否完成出现错误就会导致FLASH的写保护?

对于这个问题,有懂的老哥可以讲一下吗?

回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-8-22 10:02:01 | 显示全部楼层
完蛋了,昨天还没问题,今天又开始出现Flash写保护了,求求大佬!!
回复 支持 反对

使用道具 举报

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

本版积分规则

联系站长|手机版|野火电子官网|野火淘宝店铺|野火电子论坛 ( 粤ICP备14069197号 ) 大学生ARM嵌入式2群

GMT+8, 2024-5-9 05:22 , Processed in 0.096652 second(s), 30 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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