日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

spi nor flash驱动

發布時間:2024/1/18 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 spi nor flash驱动 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

嵌入式系統中flash的作用相當于PC上的硬盤來存放永久的數據,不像內存那樣掉電數據就會消失。而我們使用的是nor flash,操作也比較簡單,直接讀取flash的地址就可以將數據通過memcpy到內存(當然是需要給相關寄存器配一些值),然后傳給上層使用。

專用SPI控制器主要有CTRL,CMD,DATA,ADDR,STATUS寄存器。

相關命令

/* Command Value N Description Addr Dummy Data */#define MX25L_WREN 0x06 /* 1 Write Enable 0 0 0 */#define MX25L_WRDI 0x04 /* 1 Write Disable 0 0 0 */#define MX25L_RDID 0x9f /* 1 Read Identification 0 0 1-3 */#define MX25L_RDSR 0x05 /* 1 Read Status Register 0 0 >=1 */#define MX25L_WRSR 0x01 /* 1 Write Status Register 0 0 1 */#define MX25L_READ 0x03 /* 1 Read Data Bytes 3 0 >=1 */#define MX25L_FAST_READ 0x0b /* 1 Higher speed read 3 1 >=1 */#define MX25L_PP 0x02 /* 1 Page Program 3 0 1-256 */#define MX25L_SE 0x20 /* 1 Sector Erase 3 0 0 */#define MX25L_BE 0xd8 /* 1 Block Erase 3 0 0 */#define MX25L_CE 0xc7 /* 1 chip Erase 0 0 0 */#define MX25L_DP 0xb9 /* 2 Deep power down 0 0 0 */#define MX25L_RES 0xab /* 2 Read Electronic Signature 0 3 >=1 */#define MX25L_NOP 0x00 /* 2 No operation */

首先是對專門的SPI控制器進行初始化,也就是控制寄存器中設置分頻系數和片選端,地址和命令寄存器中全部寫0.并且提前寫好扇區大小,頁數等相關值,這些值放在一個全局結構體變量中,會被后面所用到。

#define MX25L_MX25L6433f_SECTOR_SHIFT 12 /* block size 1 << 12 = 4k */#define MX25L_MX25L6433f_NSECTORS 2048 // 8M #define MX25L_MX25L6433f_PAGE_SHIFT 9 /* Page size 1 << 9 = */#define MX25L_MX25L6433f_NPAGES 8192*2

然后注冊一些回調函數,主要是讀寫相關,上層最終調用的還是這些函數。

<span style="white-space:pre"> </span> priv->mtd.erase = drv_porting_flash_erase;priv->mtd.bread = drv_porting_flash_bread;priv->mtd.bwrite = drv_porting_flash_bwrite;priv->mtd.read = drv_porting_flash_read;priv->mtd.ioctl = drv_porting_flash_ioctl;
flash屬于一個塊設備,所以也就會有分區的概念,這些分區信息(分幾個區,每個區的起始地址和大小),是在config文件里面就事先寫好的。

創建分區的函數

FAR struct mtd_dev_s *mtd_partition(FAR struct mtd_dev_s *mtd, off_t firstblock,off_t nblocks) 該函數,主要是創建相關結構體, 并且把相關回調函數注冊好

part->child.erase = part_erase;part->child.bread = part_bread;part->child.bwrite = part_bwrite;part->child.read = mtd->read ? part_read : NULL;part->child.ioctl = part_ioctl;#ifdef CONFIG_MTD_BYTE_WRITEpart->child.write = mtd->write ? part_write : NULL;#endifpart->parent = mtd;part->firstblock = erasestart * blkpererase;part->neraseblocks = eraseend - erasestart;part->blocksize = geo.blocksize;part->blkpererase = blkpererase; 這些函數最終還是會調用到剛剛之前注冊號的最底層的SPI控制器相關的回調函數中去。

Note:Nor flash介質和內核之間還有一個FTL(flash translation layer)中間層,這么做的主要原因還是因為SPI每次寫之前是需要擦除的,所以也就是flash的讀寫次數是有壽命的,中間的ftl轉換層,作為一個緩沖可以增加flash的使用壽命。

所以需要調用ftl相關函數

int ftl_initialize(int minor, FAR struct mtd_dev_s *mtd) 該函數最主要的還是創建ftl相關結構體,并且注冊塊設備函數。

register_blockdriver(devname, &g_bops, 0, dev);相關注冊函數

static const struct block_operations g_bops ={ftl_open, /* open */ftl_close, /* close */ftl_read, /* read */#ifdef CONFIG_FS_WRITABLEftl_write, /* write */#elseNULL, /* write */#endifftl_geometry, /* geometry */ftl_ioctl /* ioctl */};
當然,flash也可以做一個字符設備,也就可以調用字符設備注冊的相關函數。

int bchdev_register(FAR const char *blkdev, FAR const char *chardev,bool readonly)
該函數主要完成兩步:

/* Setup the BCH lib functions */ ret = bchlib_setup(blkdev, readonly, &handle);/* Then setup the character device */ret = register_driver(chardev, &bch_fops, 0666, handle);
相關回調函數和注冊塊設備的是相同的。

總的來說,也就是相當于注冊了三次回調函數,然后最上層開始一層一層調用,一般都是類似****_i_node->read()的方式來調用的。



總結

以上是生活随笔為你收集整理的spi nor flash驱动的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。