打印
[单片机芯片]

【CH32X035评估板测评】SPI flash+fatfa V0.15文件系统

[复制链接]
1287|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 xiaoqi976633690 于 2023-9-28 09:56 编辑

1、开发环境
开发板:CH32X035C-R0-1V2
IDE:MounRiver Studio
仿真器:WCHLINKE
flash :W25Q16fatfs:FatFs R0.15
http://elm-chan.org/fsw/ff/doc/mkfs.html
2、硬件配置
/*
*SPI interface operation flash peripheral routine:
*Master:SPI1_SCK(PA5)、SPI1_MISO(PA6)、SPI1_MOSI(PA7).
*This example demonstrates SPI operation Winbond W25Qxx SPIFLASH.
*
*pins:
*    CS   -- PA2
*    DO   -- PA6(SPI1_MISO)
*    WP   -- 3.3V
*    DI   -- PA7(SPI1_MOSI)
*    CLK  -- PA5(SPI1_SCK)
*    HOLD -- 3.3V
*
*/

3、代码实现


SPI底层 flash驱动官方已经写好了只要调用就好了。
a.fatfs移植

integer.h:文件中包含了一些数值类型定义。
diskio.c:包含底层存储介质的操作函数,这些函数需要用户自己实现,主要添加底层驱动函数。
ff.c:FatFs核心文件,文件管理的实现方法。该文件独立于底层介质操作文件的函数,利用这些函数实现文件的读写。(相当于C语言中的stdio.h)
cc936.c:本文在option目录下,是简体中文支持所需要添加的文件,包含了简体志文的GBK和Unicode相互转换功能函数。
ffconf.h:这个头文件包含了对FatFs功能配置的宏定义,通过修改这些宏定义就可以裁剪FatFs的功能。如需要支持简体中文,需要把ffconf.h中的_CODE_PAGE的宏改成936并把上面的cc936.c文件加入到工程之中。

diskio.c需要用户自己实现
user_diskio.c文件里主要是disk_initializedisk_statusdisk_readdisk_write 4个函数,后面两个函数容易出错,我是参考了正点原子的。
DSTATUS disk_status(
        BYTE pdrv /* Physical drive nmuber to identify the drive */
)
{

    if(pdrv==SPI_FLASH)
    {

        return RES_OK; //直接返回OK即可

    }
    else
        {
            printf("!!!disk_status ERR\r\n");
            return RES_PARERR;
        }

}
DSTATUS disk_initialize(
        BYTE pdrv /* Physical drive nmuber to identify the drive */
)
{
    if(pdrv == SPI_FLASH)
        {
            SPI_Flash_Init();//初始化 spi flash
           // printf("!!!SPI_Flash_Init OK\r\n");
            return RES_OK;
        }
        else
        {
            printf("!!!disk_initialize ERR\r\n");
            return RES_PARERR;
        }

}
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;
        //uart_printf("disk_read---sector:%d,count:%d\r\n",sector,count);
        if(pdrv == SPI_FLASH)
        {
            for(;count>0;count--)
            {
                SPI_Flash_Read(buff,sector*FLASH_SECTOR_SIZE,FLASH_SECTOR_SIZE);
                sector++;
                buff+=FLASH_SECTOR_SIZE;
            }
           // SPI_Flash_Read(buff,sector,count);//spi flash的读接口,注意函数参数类型一致性
            res = 0;
            return res;
        }
        else
        {
            printf("!!!disk_read ERR\r\n");
            return RES_PARERR;
        }

}


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;

        if(pdrv == SPI_FLASH)
        {
            for(;count>0;count--)
            {
                SPI_Flash_Write((u8*)buff,sector*FLASH_SECTOR_SIZE,FLASH_SECTOR_SIZE);
                sector++;
                buff+=FLASH_SECTOR_SIZE;
            }
            res=0;

            return res;
        }
        else
        {
            printf("!!!disk_write ERR\r\n");
            return RES_PARERR;
        }

}


DRESULT disk_ioctl(
        BYTE pdrv, /* Physical drive nmuber (0..) */
        BYTE cmd,  /* Control code */
        void *buff /* Buffer to send/receive control data */
)
{
    if (pdrv == SPI_FLASH)
        {
            switch (cmd)
            {
             case CTRL_SYNC:
                 return RES_OK;

             /* 扇区数量 1024*1024*1024 =4 (MB) */

             case GET_SECTOR_COUNT:

                 *(DWORD * )buff = 512;//W25Q32 有1024个大小为4k bytes 的扇区
                 return RES_OK;

             /* 扇区大小 */

             case GET_SECTOR_SIZE :

                 *(WORD * )buff = 2048;//spi flash的扇区大小是 4K Bytes
                 return RES_OK;

             /*块大小 */

             case GET_BLOCK_SIZE :
                 *(DWORD * )buff = 1;
                 return RES_OK;

             default:
                 return RES_PARERR;
             }
        }
        else
        {
            printf("!!!disk_ioctl ERR\r\n");
            return RES_PARERR;
        }

}
 DWORD get_fattime (void)
{
  return 0;
}
实现底层就可以开始了


void fs_test(void)
{
           /* Filesystem object */
    FIL fil;            /* File object */
    FRESULT res;  /* API result code */
    UINT bw;            /* Bytes written */
    BYTE work[FF_MAX_SS]; /* Work area (larger is better for processing time) */
    BYTE mm[50];//读缓存
    UINT i;

    printf("file system start:\r\n");
    fs = malloc(sizeof (FATFS));
    res = f_mount(fs, "0:",1);
    printf("res=%d\n\r",res);
    /* 格式化文件系统 */
    if(res!=0)
        {
            res = f_mkfs("0:",0,work,sizeof work );
            /* 卸载文件系统 */
            f_mount(NULL,"0:",1);
            /* 挂载文件系统 */
            res = f_mount(fs, "0:",1);

        }
    if(res==0) printf("mkfs is success!%d\n\r",res);
    else printf("mkfs is fail!%d\n\r",res);
   
    if(res==0) printf("f_mount is success!%d\n\r",res);
    else printf("f_mount is fail!%d\n\r",res);

    /* Create a file as new */
    res = f_open(&fil, "0:/1.txt", FA_CREATE_NEW | FA_WRITE | FA_READ);
    if (res)
    {
        printf("open file fail.id=%d\r\n",res);

    }
    else
    {
        printf("open file success.\r\n");
    }
    /* Write a message */
    res = f_write(&fil, "Hello,World!", 12, &bw);
    //printf("res write:%d\r\n",res);
    if (bw == 12)
    {
        printf("writing ok!\r\n");
    }
    else
    {
        printf("writing fail!\r\n");
    }
    res = f_size(&fil);
    printf("file size:%d Bytes.\r\n",res);
    memset(mm,0x0,50);
    f_lseek(&fil,0);
    res = f_read(&fil,mm,12,&i);
    if (res == FR_OK)
    {
        printf("read file ok!\r\n");
        printf("read file lengh:%d Bytes.\r\n",i);
    }
    else
    {
        printf("read fail\r\n");
    }
    printf("read file:\r\n");

    printf("%s\n\r",mm);

    /* Close the file */
    f_close(&fil);
    /*卸载文件系统*/
    f_mount(0, "0:", 0);
    free(fs);
    printf("file system down.\r\n");
}
int main(void)
{
    u8  datap[SIZE];
    u16 Flash_Model;
    FRESULT res;
    FATFS * fs;

    SystemCoreClockUpdate();
    Delay_Init();
    USART_Printf_Init(115200);
    printf("SystemClk:%d\r\n", SystemCoreClock);
    printf( "ChipID:%08x\r\n", DBGMCU_GetCHIPID() );

   // SPI_Flash_Init();
    disk_initialize(0);
    Flash_Model = SPI_Flash_ReadID();

    switch(Flash_Model)
    {
        case W25Q80:
            printf("W25Q80 OK!\r\n");

            break;

        case W25Q16:
            printf("W25Q16 OK!\r\n");

            break;

        case W25Q32:
            printf("W25Q32 OK!\r\n");

            break;

        case W25Q64:
            printf("W25Q64 OK!\r\n");

            break;

        case W25Q128:
            printf("W25Q128 OK!\r\n");

            break;

        default:
            printf("Fail!\r\n");

            break;
    }

↑↑↑↑↑↑↑main函数老是复制不上来↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓接上面↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
 Delay_Ms(1000);
    fs_test();

    while(1)
    {
            Delay_Ms(1000);
        fs = malloc(sizeof (FATFS));
        res = f_mount(fs, "0:",1);
        printf("mount=%d\n\r",res);
        get_fatfs_free();
        Delay_Ms(500);

            res=f_mount(0, "0:", 0);
        free(fs);
            printf("un mount=%d\n\r",res);


//        printf("Start Read W25Qxx....\r\n");
//        SPI_Flash_Read(datap, 0x0, SIZE);
//        printf("%s\r\n", datap);

    }
}



4、实验效果




每次上电都要格式化,百度必应了半天也没有解决。
后来发现是例程的扇区擦除函数没有删掉。
排查了老半天!!!!


    //printf("Start Erase W25Qxx....\r\n");
    //SPI_Flash_Erase_Sector(0);
   // printf("W25Qxx Erase Finished!\r\n");
附件:
SPI_FLASH.zip (3.27 MB) https://bbs.21ic.com/forum.php?mod=attachment&aid=MjE2NjMyNHwyNmRiZDhmOTQxNWMwMmZlYWM0ODM1NzliYWUwYWI1Y3wxNzMyMzgyNzg5&request=yes&_f=.zip


使用特权

评论回复
沙发
dvacos| | 2023-10-8 12:36 | 只看该作者
学习!

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

34

主题

187

帖子

2

粉丝