spi nor flash驱动
生活随笔
收集整理的這篇文章主要介紹了
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驱动的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 计算机信息技术培训总结,信息技术培训学习
- 下一篇: 鼓风机行业现状分析及前景预测:行业分类、