zoukankan      html  css  js  c++  java
  • rtthread spi w25q128 sfud

    1:环境

    STM32H743板子上有一个W25Q128的flash芯片。通过SPI连接在一起

    W25Q128
    (128M-bit),被组织为65536个可编程的页,每页256bytes。擦除方式分为16页一组(即一个扇区4kbytes),128页一组(即8个扇区32kbytes),256页一组(即16个扇区或1个块64kbytes),或整个芯片擦除。该芯片有4096个可擦除扇区,或256个可擦除块。该芯片支持
    standard spi,Dual/Quad I/O SPI

    我们要做这样几件事,配置SPI来对这个flash进行读写,然后进行文件系统的设置,利用RT-thread上虚拟文件系统的接口来进行读写。

    2.注册SPI设备

    1. 在main文件中添加,在spi1总线上注册spi10设备的函数
      #include "drv_spi.h"
      
      int w25q_spi_device_init()
      {
          __HAL_RCC_GPIOB_CLK_ENABLE();
          return rt_hw_spi_device_attach("spi1", "spi10", GPIOB, GPIO_PIN_14);
      }
      INIT_DEVICE_EXPORT(w25q_spi_device_init);
    2. 编译执行后,可以查看shell下是否有设备出现
    3.  

    3:对W25Q128进行读写访问

      利用RT-Thread上提供的访问SPI设备的接口函数,来读写设备的ID。先写入0x90,然后再读,可以获得设备的ID数据
    下面采用了两种方式:第一种:rt_spi_send_then_recv 先发送后接收
    第二种:rt_spi_transfer_message 以链表结构体的方式发送

    #define W25Q_SPI_DEVICE_NAME     "spi10"
    
    static void spi_w25q_sample(int argc, char *argv[])
    {
        struct rt_spi_device *spi_dev_w25q;
        char name[RT_NAME_MAX];
        rt_uint8_t w25x_read_id = 0x90;
        rt_uint8_t id[5] = {0};
        
        if(argc == 2){
            rt_strncpy(name, argv[1], RT_NAME_MAX);
        } else {
            rt_strncpy(name, W25Q_SPI_DEVICE_NAME, RT_NAME_MAX);
        }
        
        spi_dev_w25q = (struct rt_spi_device *)rt_device_find(name);
        if(!spi_dev_w25q){
            rt_kprintf("spi sample run failed! can't find %s device!
    ", name);
        } else {
            
             struct rt_spi_configuration cfg;
             cfg.data_width = 8;
             cfg.mode = RT_SPI_MODE_0 | RT_SPI_MSB; /* SPI Compatible: Mode 0 and Mode 3 */
             cfg.max_hz = 50 * 1000 * 6 ; /* 50M */
             rt_spi_configure(spi_dev_w25q, &cfg);
            
            rt_spi_send_then_recv(spi_dev_w25q, &w25x_read_id, 1, id, 5);
            rt_kprintf("use rt_spi_send_then_recv() read w25q ID is %x%x
    ", id[3], id[4]);
            
            struct rt_spi_message msg1, msg2;
            msg1.send_buf = &w25x_read_id;
            msg1.recv_buf = RT_NULL;
            msg1.length = 1;
            msg1.cs_take = 1;
            msg1.cs_release = 0;
            msg1.next = &msg2;
            
            msg2.send_buf = RT_NULL;
            msg2.recv_buf = id;
            msg2.length = 5;
            msg2.cs_take = 0;
            msg2.cs_release = 1;
            msg2.next = RT_NULL;
            
            rt_spi_transfer_message(spi_dev_w25q, &msg1);
            rt_kprintf("use rt_spi_transfer_mesage() read w25q ID is :%x%x
    ", id[3], id[4]);
        }
        
    }
    MSH_CMD_EXPORT(spi_w25q_sample, spi_w25q_sample samole);

    结果:读到最后两位的值是 17 ef

     4.搭建文件系统

      1.选择使用虚拟系统,再flash上要部署elmfs 所以要使能

      2.进入elm-chan’s Fats中,把扇区配置为4096

      3. 使能libc

      4.DFS 框架的文件系统实现层需要存储设备驱动层提供驱动接口用于对接,本次使用的存储设备为 SPI Flash

    5.2:创建存储设备

      

    由于只有块设备类型的设备才能和文件系统对接,所以需要根据 SPI Device 找到 SPI Flash 设备,并创建与其对应的 Block Device。

    这里需要使用到万能 SPI Flash 驱动库:SFUD ,RT-Thread 已经集成了该组件,在上面的配置过程中我们已经开启这个功能。此时只需要使用 SFUD 提供的 rt_sfud_flash_probe 函数即可。该函数将执行如下操作:

    1. 根据名为 spi10 的 SPI Device 设备找到对应的 Flash 存储设备。

    2. 初始化 Flash 设备。

    3. 在 Flash 存储设备上创建名为 W25Q256 的 Block Device。

    如果开启了组件自动初始化功能,该函数会被自动执行,否则需要手动调用运行。

      

    static int rt_hw_spi_flash_with_sfud_init(void)
    {
        if (RT_NULL == rt_sfud_flash_probe("W25Q128", "spi10"))
        {
            return RT_ERROR;
        };
        
        return RT_EOK;
    }
    INIT_COMPONENT_EXPORT(rt_hw_spi_flash_with_sfud_init);

    6:文件系统初始化

    6.1 DFS 框架的初始化

    DFS 框架的初始化主要是对内部数据结构以及资源的初始化。这一过程包括初始化文件系统必须的数据表,以及互斥锁。该功能由如下函数完成。如果开启了组件自动初始化功能,该函数会被自动执行,否则需要手动调用运行。

      

    int dfs_init(void)
    {
        static rt_bool_t init_ok = RT_FALSE;
    
        if (init_ok)
        {
            rt_kprintf("dfs already init.
    ");
            return 0;
        }
    
        /* clear filesystem operations table */
        memset((void *)filesystem_operation_table, 0, sizeof(filesystem_operation_table));
        /* clear filesystem table */
        memset(filesystem_table, 0, sizeof(filesystem_table));
        /* clean fd table */
        memset(&_fdtab, 0, sizeof(_fdtab));
    
        /* create device filesystem lock */
        rt_mutex_init(&fslock, "fslock", RT_IPC_FLAG_FIFO);
    
    #ifdef DFS_USING_WORKDIR
        /* set current working directory */
        memset(working_directory, 0, sizeof(working_directory));
        working_directory[0] = '/';
    #endif
    
    #ifdef RT_USING_DFS_DEVFS
        {
            extern int devfs_init(void);
    
            /* if enable devfs, initialize and mount it as soon as possible */
            devfs_init();
    
            dfs_mount(NULL, "/dev", "devfs", 0, 0);
        }
    #endif
    
        init_ok = RT_TRUE;
    
        return 0;
    }
    INIT_PREV_EXPORT(dfs_init);

    6.2 中间层文件系统的初始化,初始化具体文件系统

    这一步的初始化主要是将 elm FatFS 的操作函数注册到 DFS 框架中。该功能由如下函数完成。如果开启了组件自动初始化功能,该函数会被自动执行,否则需要手动调用运行。

    int elm_init(void)
    {
        /* register fatfs file system */
        dfs_register(&dfs_elm);
    
        return 0;
    }
    INIT_COMPONENT_EXPORT(elm_init);

    7:文件系统挂载

    7.1 添加挂载函数

    再main中调用w25q128_mount(),可以把设备挂载再根目录下

    void w25q128_mount(void)
    {
        rt_device_t dev;
        dev = rt_device_find("W25Q128");
        if(dev != RT_NULL) {
        if(dfs_mount("W25Q128", "/", "elm", 0, 0) == 0){
                rt_kprintf("spi_flash mount to spi!
    ");
            } else {
                rt_kprintf("spi_flash mount to spi failed!
    ");
            }
        }
    }

    7.2初始化存储设备,在flash中创建文件系统

    第一次使用 SPI Flash 作为文件系统地存储设备时,如果我们直接重启开发板来挂载文件系统,就会看到 spi flash mount to /spi failed! 的提示。这是因为此时在 SPI Flash 中还没有创建相应类型的文件系统,这就用到了创建文件系统 shell 命令:mkfs。

    mkfs 命令的功能是在指定的存储设备上创建指定类型的文件系统。使用格式为:mkfs [-t type] device 。第一次挂载文件系统前需要使用 mkfs 命令在存储设备上创建相应的文件系统,否则就会挂载失败。如果要在 W25Q256 设备上创建 elm 类型的文件系统,就可以使用 mkfs -t elm W25Q256 命令,使用方法如下:mkfs -t elm W25Q128

    文件系统创建完成后需要重启设备。该过操作一次,就保存在flash中。感觉就像,第一次使用U盘要格式化,后面就直接可以用了

    显示:输入ls查看

     

    8:使用虚拟文件的系统接口读写内存

    static void readwrite_sample(void)
    {
        int fd;
        int size;
        char s[] = "RT-Thread Programmer!"; 
        char buffer[80];
        rt_kprintf("write string %s to test.txt
    ", s);
        
        fd = open("/text.txt", O_WRONLY | O_CREAT);
        if(fd >= 0){
            write(fd, s, sizeof(s));
            close(fd);
            rt_kprintf("Write done.
    ");
        }
        
        fd = open("/text.txt", O_RDONLY);
        if(fd >= 0){
            size = read(fd, buffer, sizeof(buffer));
            rt_kprintf("Read form file test.txt: %s
    ", buffer);
            if(size < 0)
                return;
        }
    }
    
    
    MSH_CMD_EXPORT(readwrite_sample, spi_w25q_sample samole);
  • 相关阅读:
    17、网卡驱动程序-DM9000举例
    16、NOR FLASH驱动框架
    15.1 linux操作系统下nand flash驱动框架2
    15、NAND FLASH驱动程序框架
    14、块设备驱动程序框架分析
    12.2 linux USB框架分析(详细注册match匹配过程)
    arm-linux-gcc: Command not found
    12、USB设备驱动程序
    POJ-2752 Seek the Name, Seek the Fame (KMP)
    POJ-2406 Power Strings (KMP)
  • 原文地址:https://www.cnblogs.com/wt88/p/14309722.html
Copyright © 2011-2022 走看看