emmnn 发表于 2022-7-26 17:02

【国民技术低功耗系列N32L43x测评】4、SPI-FLASH驱动+fatfs文件系统移植+USB驱动模...

本帖最后由 emmnn 于 2022-7-26 17:02 编辑



# 前言
距离上篇帖子过去也有两个星期的时间了,今天主要分享的内容是W25Q128 SPI-FLASH的驱动,以及如何通过usb驱动的移植,实现SPI-FLASH模拟U盘的功能。在移植好的SPI-FLASH上,我们可以很方便的通过电脑的USB接口存储我们项目开发所需要的字库文件,ui图片资源文件等,从而解决因片上flash空间不够而无法存储项目所需资源文件的问题。
# 一、SPI-FLASH (W25Q128驱动)

引脚定义

引脚功能说明

首先是SPI-FLASH(W25Q128)驱动,关于这部分的驱动代码,在网上可以找到很多,我这边是直接把野火的源码拷贝过来更改使用的,以下是源码中关于引脚定义及初始化部分(完整源码请查看附件)
```c
//#definesFLASH_ID            0xEF3015   //W25X16
//#definesFLASH_ID            0xEF4015       //W25Q16
#definesFLASH_ID            0XEF4018   //W25Q128
//#definesFLASH_ID            0XEF4017    //W25Q64

#define   SPI_FLASH_PERIPH                  SPI1
#define   SPI_FLASH_RCC_PERIPH                RCC_APB2_PERIPH_SPI1
#define   SPI_FLASH_GPIO_PERIPH               RCC_APB2_PERIPH_GPIOA

//SCK引脚
#define   SPI_FLASH_SCK_PORT                  GPIOA
#define   SPI_FLASH_SCK_PIN                   GPIO_PIN_5
//MOSI引脚
#define   SPI_FLASH_MOSI_PORT               GPIOA
#define   SPI_FLASH_MOSI_PIN                  GPIO_PIN_7
//MISO引脚
#define   SPI_FLASH_MISO_PORT               GPIOA
#define   SPI_FLASH_MISO_PIN                  GPIO_PIN_6
//CS(NSS)引脚 片选选普通GPIO即可
#define   SPI_FLASH_CS_PORT                   GPIOA
#define   SPI_FLASH_CS_PIN                  GPIO_PIN_4

#define   SPI_FLASH_CS_LOW()                           SPI_FLASH_CS_PORT->PBC = SPI_FLASH_CS_PIN
#define   SPI_FLASH_CS_HIGH()                              SPI_FLASH_CS_PORT->PBSC = SPI_FLASH_CS_PIN
```
```c
/**
* @briefSPI_FLASH初始化
* @param无
* @retval 无
*/
void SPI_FLASH_Init(void)
{
    GPIO_InitType GPIO_InitStructure;
    SPI_InitType SPI_InitStructure;

    /* Enable the GPIO Clock */
    RCC_EnableAPB2PeriphClk(SPI_FLASH_GPIO_PERIPH|RCC_APB2_PERIPH_AFIO, ENABLE);
    /*!< SPI1 Periph clock enable */
    RCC_EnableAPB2PeriphClk(SPI_FLASH_RCC_PERIPH, ENABLE);

    /* Configure the GPIO pin */
    GPIO_InitStruct(&GPIO_InitStructure);
    GPIO_InitStructure.Pin      = SPI_FLASH_CS_PIN;
    GPIO_InitStructure.GPIO_Current = GPIO_DC_4mA;
    GPIO_InitStructure.GPIO_Pull    = GPIO_Pull_Up;
    GPIO_InitStructure.GPIO_Mode= GPIO_Mode_Out_PP;
    GPIO_InitPeripheral(SPI_FLASH_CS_PORT, &GPIO_InitStructure);

        /*!< Configure SPI1 pins: SCK */
    GPIO_InitStructure.Pin      = SPI_FLASH_SCK_PIN;
    GPIO_InitStructure.GPIO_Mode= GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Alternate = GPIO_AF0_SPI1;
    GPIO_InitPeripheral(SPI_FLASH_SCK_PORT, &GPIO_InitStructure);

    /*!< Configure SPI1 pins: MOSI */
    GPIO_InitStructure.Pin = SPI_FLASH_MOSI_PIN;
    GPIO_InitPeripheral(SPI_FLASH_MOSI_PORT, &GPIO_InitStructure);

    /*!< Configure SPI1 pins: MISO */
    GPIO_InitStructure.Pin = SPI_FLASH_MISO_PIN;
    GPIO_InitPeripheral(SPI_FLASH_MISO_PORT, &GPIO_InitStructure);

    /* 停止信号 FLASH: CS引脚高电平*/
    SPI_FLASH_CS_HIGH();

    /*!< SPI configuration */
    SPI_InitStructure.DataDirection = SPI_DIR_DOUBLELINE_FULLDUPLEX;
    SPI_InitStructure.SpiMode       = SPI_MODE_MASTER;
    SPI_InitStructure.DataLen       = SPI_DATA_SIZE_8BITS;
    SPI_InitStructure.CLKPOL      = SPI_CLKPOL_HIGH;
    SPI_InitStructure.CLKPHA      = SPI_CLKPHA_SECOND_EDGE;
    SPI_InitStructure.NSS         = SPI_NSS_SOFT;

    SPI_InitStructure.BaudRatePres = SPI_BR_PRESCALER_2;

    SPI_InitStructure.FirstBit = SPI_FB_MSB;
    SPI_InitStructure.CRCPoly= 7;
    SPI_Init(SPI_FLASH_PERIPH, &SPI_InitStructure);

    /*!< Enable the SPI_PERIPH*/
    SPI_Enable(SPI_FLASH_PERIPH, ENABLE);
}
```
# 二、fatfs文件系统移植
搞定SPI-FLASH的驱动程序后,接下来要弄的就是文件系统的移植。fatfs是一款通用的文件系统,被广泛地应用在小型的嵌入式系统中。fatfs具有代码量少,占用资源量小,可移植性高等特点,因此在嵌入式设备中被广泛使用。
fatfs下载链接:(http://elm-chan.org/fsw/ff/00index_e.htmll)

在官网上可以看到,目前该版本已更新到R0.14b,我们就以这个版本为基准简单介绍下该文件系统的移植。

下载后解压缩,有两个文件夹documents和source,fatfs源码就在source目录下。

将所有.c文件添加到我们的工程项目中,同时配置好编译路径。

源码文件我们只需要更改diskio.c这个文件就可以了,更改如下:
```c
#include "ff.h"                        /* Obtains integer types */
#include "diskio.h"                /* Declarations of disk functions */
#include "bsp_spi_flash.h"

/* Definitions of physical drive number for each drive */
#define DEV_SPI_FLASH 0        /* Map SPI_FLASH to physical drive 0 */

#define FLASH_SECTOR_SIZE 512
#define FLASH_BLOCK_SIZE        8
#define FLASH_SECTOR_COUNT 2048*16

/*-----------------------------------------------------------------------*/
/* Get Drive Status                                                      */
/*-----------------------------------------------------------------------*/

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

        if (pdrv == DEV_SPI_FLASH)
        {
                /* SPI Flash状态检测:读取SPI Flash 设备ID */
                if(sFLASH_ID == SPI_FLASH_ReadID())
                {
                        /* 设备ID读取结果正确 */
                        stat &= ~STA_NOINIT;
                }
                else
                {
                        /* 设备ID读取结果错误 */
                        stat = STA_NOINIT;
                }
        }
        return stat;
}



/*-----------------------------------------------------------------------*/
/* Inidialize a Drive                                                    */
/*-----------------------------------------------------------------------*/

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

        if (pdrv == DEV_SPI_FLASH)
        {
                /* 初始化SPI Flash */
                SPI_FLASH_Init();

                /* 延时一小段时间 */
                i=500;
                while(--i);       
                /* 唤醒SPI Flash */
                SPI_Flash_WAKEUP();
                /* 获取SPI Flash芯片状态 */
                stat=disk_status(pdrv);
        }
        return stat;
}



/*-----------------------------------------------------------------------*/
/* Read Sector(s)                                                      */
/*-----------------------------------------------------------------------*/

DRESULT disk_read (
        BYTE pdrv,                /* Physical drive nmuber to identify the drive */
        BYTE *buff,                /* Data buffer to store read data */
        LBA_t sector,        /* Start sector in LBA */
        UINT count                /* Number of sectors to read */
)
{
        DRESULT res = RES_PARERR;
        if (pdrv == DEV_SPI_FLASH)
        {
                while(count--)
                {
                        SPI_FLASH_BufferRead(buff, sector*FLASH_SECTOR_SIZE, FLASH_SECTOR_SIZE);
                        sector++;
                        buff+=FLASH_SECTOR_SIZE;
                }
                res = RES_OK;
        }
        return res;
}



/*-----------------------------------------------------------------------*/
/* Write Sector(s)                                                       */
/*-----------------------------------------------------------------------*/

#if FF_FS_READONLY == 0

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 = RES_PARERR;
        if (pdrv == DEV_SPI_FLASH)
        {
                while(count --)
                {
                        SPI_FLASH_SectorErase(sector*FLASH_SECTOR_SIZE);
                        SPI_FLASH_BufferWrite((uint8_t *)buff,sector*FLASH_SECTOR_SIZE,FLASH_SECTOR_SIZE);
                        sector++;
                        buff+=FLASH_SECTOR_SIZE;
                }
                res = RES_OK;
        }

        return res;
}

#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 = RES_PARERR;

        if (pdrv == DEV_SPI_FLASH)
        {
                switch (cmd)
                {
                        case CTRL_SYNC:
                                break;
                        case GET_SECTOR_COUNT:
                                *(DWORD * )buff = FLASH_SECTOR_COUNT;       
                        break;
                        /* 扇区大小*/
                        case GET_SECTOR_SIZE :
                                *(WORD * )buff = FLASH_SECTOR_SIZE;
                        break;
                        /* 同时擦除扇区个数 */
                        case GET_BLOCK_SIZE :
                                *(DWORD * )buff = FLASH_BLOCK_SIZE;
                        break;      
              }
                res = RES_OK;
        }

        return res;
}

__weak DWORD get_fattime(void) {
        /* 返回当前时间戳 */
        return          ((DWORD)(2015 - 1980) << 25)        /* Year 2015 */
                        | ((DWORD)1 << 21)                                /* Month 1 */
                        | ((DWORD)1 << 16)                                /* Mday 1 */
                        | ((DWORD)0 << 11)                                /* Hour 0 */
                        | ((DWORD)0 << 5)                                  /* Min 0 */
                        | ((DWORD)0 >> 1);                                /* Sec 0 */
}

```
此外还有ffconf.h文件,这个文件都是一些宏定义,可根据我们的需要去更改对应的宏来开启或关闭相应的功能,这里我们主要更改下面这两个地方
```c
#define FF_USE_MKFS                1
/* This option switches f_mkfs() function. (0:Disable or 1:Enable) */
/*---------------------------------------------------------------------------/
/ Locale and Namespace Configurations
/---------------------------------------------------------------------------*/

#define FF_CODE_PAGE        936
/* This option specifies the OEM code page to be used on the target system.
/Incorrect code page setting can cause a file open failure.
/
/   437 - U.S.
/   720 - Arabic
/   737 - Greek
/   771 - KBL
/   775 - Baltic
/   850 - Latin 1
/   852 - Latin 2
/   855 - Cyrillic
/   857 - Turkish
/   860 - Portuguese
/   861 - Icelandic
/   862 - Hebrew
/   863 - Canadian French
/   864 - Arabic
/   865 - Nordic
/   866 - Russian
/   869 - Greek 2
/   932 - Japanese (DBCS)
/   936 - Simplified Chinese (DBCS)
/   949 - Korean (DBCS)
/   950 - Traditional Chinese (DBCS)
/   0 - Include all code pages above and configured by f_setcp()
*/
```
最后我们可以写下测试代码测试下移植后的功能
```c
    #if 1
    /*----------------------- 格式化测试 -----------------*/
    /* 如果没有文件系统就格式化创建创建文件系统 */
    if(res_flash == FR_NO_FILESYSTEM)
    {
      /* 格式化 */                                               
      res_flash = f_mkfs("0:", 0, work, sizeof(work));

      if(res_flash == FR_OK)
      {
            PRO_LOG(LOG_DEBUG, "f_mkfs success. \r\n");
            /* 格式化后,先取消挂载 */
            res_flash = f_mount(NULL,"0:",1);                       
            /* 重新挂载        */                       
            res_flash = f_mount(&fs,"0:",1);
      }
      else
      {
            PRO_LOG(LOG_DEBUG, "f_mkfs failed.\r\n");
      }
    }
    else if(res_flash!=FR_OK)
    {
      PRO_LOG(LOG_DEBUG, "f_mount failed. (%d). \r\n", res_flash);
    }
    else
    {
      PRO_LOG(LOG_DEBUG, "f_mount init success, then start write and read test. \r\n");
    }
    /*----------------------- 写测试 -----------------*/
    /* 打开文件,每次都以新建的形式打开,属性为可写 */
    PRO_LOG(LOG_DEBUG, "\r\n****** FATFS START WRITE... ******\r\n");       
    if(!f_open(&fp,"0:你好.txt",FA_CREATE_ALWAYS | FA_WRITE))
    {
      PRO_LOG(LOG_DEBUG, "open file success!\n");
    }
    else
    {
      PRO_LOG(LOG_DEBUG, "open file failure!\n");
    }

    if(!f_write(&fp,(char*)write_text,strlen(write_text),&write_bytes))
    {
      PRO_LOG(LOG_DEBUG, "write success,write_bytes=%d\n",write_bytes);
    }
    else
    {
      PRO_LOG(LOG_DEBUG, "write failure!\n");
    }
    if(!f_close(&fp))
    {
      PRO_LOG(LOG_DEBUG, "close success!\n");
    }
    else
    {
      PRO_LOG(LOG_DEBUG, "close failure!\n");
    }
    /*----------------------- 读测试 -----------------*/
    PRO_LOG(LOG_DEBUG, "\r\n****** FATFS START READ... ******\r\n");
    if(!f_open(&fp,"0:你好.txt",FA_READ))
    {
      PRO_LOG(LOG_DEBUG, "open file success!\n");
    }
    else
    {
      PRO_LOG(LOG_DEBUG, "open file failure!\n");
    }
    if(!f_read(&fp,(char*)read_buff,sizeof(read_buff),&read_bytes))
    {
      PRO_LOG(LOG_DEBUG, "read success,read_bytes=%d\n",read_bytes);
      PRO_LOG(LOG_DEBUG, "test.txt content is :%s\n",read_buff);
    }
    else
    {
      PRO_LOG(LOG_DEBUG, "read failure!\n");
    }
    if(!f_close(&fp))
    {
      PRO_LOG(LOG_DEBUG, "close success!\n");
    }
    else
    {
      PRO_LOG(LOG_DEBUG, "close failure!\n");
    }
    #endif
```
编译烧录,上电运行:

# 三、usb--SPI-FLASH模拟U盘
关于USB驱动的移植,国民技术官方也有提供移植好的例程供我们参考,官方提供的例程是通过USB访问片上flash的,我们只需要把官方的例程拿过来稍微改下

将USB-lib添加到我们的工程中

将USB-DEVICE部分代码拷贝到我们工程中,一个文件夹统一管理

更改mass_mal.c文件
```c
/*****************************************************************************
* Copyright (c) 2019, Nations Technologies Inc.
*
* All rights reserved.
* ****************************************************************************
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Nations' name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ****************************************************************************/

/**
* @file mass_mal.c
* @author Nations
* @version v1.0.0
*
* @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved.
*/
/* Includes ------------------------------------------------------------------*/


#include "mass_mal.h"
#include "n32l43x_flash.h"
#include "bsp_spi_flash.h"

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define FLASH_SECTOR_SIZE       512
#define FLASH_BLOCK_SIZE          8
#define FLASH_SECTOR_COUNT      2048*16

#define sFLASH_ID               0XEF4018    //W25Q128

/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
uint32_t Mass_Memory_Size;
uint32_t Mass_Block_Size;
uint32_t Mass_Block_Count;

/* logic unit count; the first is 0 */
uint32_t Max_Lun = 0;

/**
* @brief   Initializes the Media on the Nations.
* @param   lun: logical unit.
* @returnMAL_FAIL.
*/
uint16_t MAL_Init(uint8_t lun)
{
    uint16_t status = MAL_OK;
    SPI_FLASH_Init();
    if(SPI_FLASH_ReadID()==sFLASH_ID)
    {
      //printf("flash init succsee\n");
      status = MAL_OK;
    }
    else
      status = MAL_FAIL;
    return status;
}

/**
* @brief   Write sectors.
* @param   lun: logical unit.
* @param   Memory_Offset: memory offset.
* @param   Writebuff: write buff pointer.
* @param   Transfer_Length: transfer data length.
* @returnMAL_OK or MAL_FAIL.
*/
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:
      W25QXX_Write((uint8_t*)Writebuff, Memory_Offset, Transfer_Length);
      break;
    case 1:
      break;
    default:
      return MAL_FAIL;
    }
    return MAL_OK;
}

/**
* @brief   Write sectors.
* @param   lun: logical unit.
* @param   Memory_Offset: memory offset.
* @param   Readbuff: read buff pointer.
* @param   Transfer_Length: transfer data length.
* @returnMAL_OK or MAL_FAIL.
*/
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:
      SPI_FLASH_BufferRead((uint8_t *)Readbuff, Memory_Offset, Transfer_Length);
      break;
    case 1:
      break;
    default:
      return MAL_FAIL;
    }
    return MAL_OK;
}

/**
* @brief   Get status.
* @param   lun: logical unit.
* @returnMAL_OK or MAL_FAIL.
*/
uint16_t MAL_GetStatus (uint8_t lun)
{
    if (lun == 0)
    {
      Mass_Block_Count = FLASH_SECTOR_COUNT;
      Mass_Block_Size =FLASH_SECTOR_SIZE;
      Mass_Memory_Size = FLASH_SECTOR_COUNT*FLASH_SECTOR_SIZE;
      return MAL_OK;
    }

    return MAL_FAIL;
}
```
中断处理
```c
/**
* @briefThis function handles USB_LP_IRQHandler Handler.
*/
void USB_LP_IRQHandler(void)
{
    USB_Istr();
}
```
测试代码
```c
FATFS fs;//文件系统对象
FIL fp;//文件对象
char *write_text="FATFS test success!";
unsigned int write_bytes=0;
char read_buff;
unsigned int read_bytes=0;
BYTE work;

static void main_thread_entry(void * para)
{
    FRESULT res_flash;
    res_flash = f_mount(&fs,"0:",1);
    #if 1
    /*----------------------- 格式化测试 -----------------*/
    /* 如果没有文件系统就格式化创建创建文件系统 */
    if(res_flash == FR_NO_FILESYSTEM)
    {
      /* 格式化 */                                               
      res_flash = f_mkfs("0:", 0, work, sizeof(work));

      if(res_flash == FR_OK)
      {
            PRO_LOG(LOG_DEBUG, "f_mkfs success. \r\n");
            /* 格式化后,先取消挂载 */
            res_flash = f_mount(NULL,"0:",1);                       
            /* 重新挂载        */                       
            res_flash = f_mount(&fs,"0:",1);
      }
      else
      {
            PRO_LOG(LOG_DEBUG, "f_mkfs failed.\r\n");
      }
    }
    else if(res_flash!=FR_OK)
    {
      PRO_LOG(LOG_DEBUG, "f_mount failed. (%d). \r\n", res_flash);
    }
    else
    {
      PRO_LOG(LOG_DEBUG, "f_mount init success, then start write and read test. \r\n");
    }
    /*----------------------- 写测试 -----------------*/
    /* 打开文件,每次都以新建的形式打开,属性为可写 */
    PRO_LOG(LOG_DEBUG, "\r\n****** FATFS START WRITE... ******\r\n");       
    if(!f_open(&fp,"0:test.txt",FA_CREATE_ALWAYS | FA_WRITE))
    {
      PRO_LOG(LOG_DEBUG, "open file success!\n");
    }
    else
    {
      PRO_LOG(LOG_DEBUG, "open file failure!\n");
    }

    if(!f_write(&fp,(char*)write_text,strlen(write_text),&write_bytes))
    {
      PRO_LOG(LOG_DEBUG, "write success,write_bytes=%d\n",write_bytes);
    }
    else
    {
      PRO_LOG(LOG_DEBUG, "write failure!\n");
    }
    if(!f_close(&fp))
    {
      PRO_LOG(LOG_DEBUG, "close success!\n");
    }
    else
    {
      PRO_LOG(LOG_DEBUG, "close failure!\n");
    }
    /*----------------------- 读测试 -----------------*/
    PRO_LOG(LOG_DEBUG, "\r\n****** FATFS START READ... ******\r\n");
    if(!f_open(&fp,"0:test.txt",FA_READ))
    {
      PRO_LOG(LOG_DEBUG, "open file success!\n");
    }
    else
    {
      PRO_LOG(LOG_DEBUG, "open file failure!\n");
    }
    if(!f_read(&fp,(char*)read_buff,sizeof(read_buff),&read_bytes))
    {
      PRO_LOG(LOG_DEBUG, "read success,read_bytes=%d\n",read_bytes);
      PRO_LOG(LOG_DEBUG, "test.txt content is :%s\n",read_buff);
    }
    else
    {
      PRO_LOG(LOG_DEBUG, "read failure!\n");
    }
    if(!f_close(&fp))
    {
      PRO_LOG(LOG_DEBUG, "close success!\n");
    }
    else
    {
      PRO_LOG(LOG_DEBUG, "close failure!\n");
    }
    #endif
   

    if(USB_Config(SYSCLK_VALUE_96MHz) == SUCCESS)
    {
      USB_Init();
      while (bDeviceState != CONFIGURED)
      {
            rt_thread_delay(50);
      }
    }

    while(1)
    {
      rt_thread_delay(1000);
    }
}
```
这里还有个地方需要注意下,在调USB这块驱动时,网上看到相关资料说这一块的时钟必须配置成不大于48MHz(有些说必须配置成48MHz,所以我这边就直接给配置成48MHz了),因此时钟这一块也需要重新配置下,具体配置可以看源码。

可以看到我们移植后基本是OK的。
# 四、问题点总结
最后就是问题点的总结,暂时也还没花时间去搞明白,要是有熟悉这方面的朋友希望能指点下:
**问题1:**我在我的程序中创建一个中文名文件时,在pc端查看,中文名会变成乱码;

**问题2:**在测试过程中发现,我通过USB往flash写入文件(就是往flash里面拉文件),这速度非常缓慢(只有几十kb/s),用官方的例程测试速度有1-2M/s,当然官方的例程写片上的flash是会快一点的,想问下有人知道这部分怎么优化。:tw-Ac2:
#附件
最后,附件如下

nmg 发表于 2022-8-1 18:21

<p><img height="48" src="https://bbs.eeworld.com.cn/static/editor/plugins/hkemoji/sticker/facebook/loveliness.gif" width="48" />这个usb速度的问题,是不是和你那种类似 @RCSN </p>

沧桑小草 发表于 2022-8-1 22:57

<p>第一个问题,应该是Fatfs文件系统的问题,可以参考下网上的做法,转下格式</p>

<p>第二个问题,我理解你是USB先传输文件到mcu,不是知道是ram还是片上flash,然后再通过spi传输到W25Q128。那这样的话,放到mcu ram中是比较好点的,另外spi速率提高看看,剩下的部分就是逻辑上的优化了,包括但不局限于提升软件优化等级,直接操作寄存器等方式。</p>

emmnn 发表于 2022-8-1 23:07

沧桑小草 发表于 2022-8-1 22:57
第一个问题,应该是Fatfs文件系统的问题,可以参考下网上的做法,转下格式

第二个问题,我理解你是USB先 ...

<p>感谢指导,抽时间会再看看这个问题,最近一段时间较忙,后续解决了会继续发帖补充解决方法<img height="48" src="https://bbs.eeworld.com.cn/static/editor/plugins/hkemoji/sticker/facebook/handshake.gif" width="48" /></p>
页: [1]
查看完整版本: 【国民技术低功耗系列N32L43x测评】4、SPI-FLASH驱动+fatfs文件系统移植+USB驱动模...