第六章為重用外設(shè)驅(qū)動(dòng)代碼,本文內(nèi)容為6.2 SPI NOR Flash 存儲(chǔ)器。
6.2 SPI NOR Flash 存儲(chǔ)器
SPI NOR Flash 是一種SPI 接口的非易失閃存芯片,本節(jié)以***旺宏電子的MX25L1606為例詳細(xì)介紹在AMetal 中如何使用類似的Flash 存儲(chǔ)器。
>>>6.2.1 基本功能
MX25L1606 總?cè)萘繛?6M(16×1024×1024)bits,即2M字節(jié)。每個(gè)字節(jié)對(duì)應(yīng)一個(gè)存儲(chǔ)地址,因此其存儲(chǔ)數(shù)據(jù)的地址范圍為0x000000 ~ 0x1FFFFF。
在MX25L1606 中,存儲(chǔ)器有塊(block)、扇區(qū)(sector)和頁(page)的概念。頁大小為256 字節(jié),每個(gè)扇區(qū)包含16頁,扇區(qū)大小為4K(4096)字節(jié),每個(gè)塊包含16 個(gè)扇區(qū),塊的大小為64K(65536)字節(jié),其組織結(jié)構(gòu)示意圖詳見表6.5。
表6.5 MX25L1606 存儲(chǔ)器組織結(jié)構(gòu)
MX25L1606 的通信接口為標(biāo)準(zhǔn)4 線SPI 接口(支持模式0 和模式3),即CS、MOSI、MISO、CLK,詳見圖6.3。其中,CS(#1)、SO(#2)、SI(#5)、SCLK(#6)分別為SPI 的CS、MISO、MOSI 和CLK 信號(hào)引腳。特別地,WP(#3)用于寫保護(hù),HOLD(#7)用于暫停數(shù)據(jù)傳輸。一般來說,這兩個(gè)引腳不會(huì)使用,可通過上拉電阻上拉至高電平。MicroPort-NorFlash 模塊通過MicroPort 接口與AM824-Core 相連。
圖6.3 SPI Flash 電路原理圖
>>>6.2.2 初始化
AMetal 提供了支持常見的MX25L8006、MX25L1606……等系列SPI Flash 器件的驅(qū)動(dòng)函數(shù),使用其它各功能函數(shù)前必須先完成初始化,其函數(shù)原型(am_mx25xx.h)為:
該函數(shù)意在獲取器件的實(shí)例句柄mx25xx_handle。其中,p_dev 為指向am_mx25xx_dev_t類型實(shí)例的指針,p_devinfo 為指向am_mx25xx_devinfo_t 類型實(shí)例信息的指針。
(1)實(shí)例
定義am_mx25xx_dev_t 類型(am_mx25xx.h)實(shí)例如下:
其中,g_mx25xx_dev 為用戶自定義的實(shí)例,其地址作為p_dev 的實(shí)參傳遞。
(2)實(shí)例信息
實(shí)例信息主要描述了具體器件的固有信息,即使用的SPI 片選引腳、SPI 模式、SPI 速率和器件具體型號(hào)等,其類型am_mx25xx_devinfo_t 的定義(am_mx25xx.h)如下:
其中,spi_mode 為SPI 模式,MX25L1606 支持模式0(AM_SPI_MODE_0)和模式3(AM_SPI_MODE_3)。spi_cs_pin 為與實(shí)際電路相關(guān)的片選引腳,MicroPort-NorFlash 模塊通過MicroPort 接口與AM824-Core 相連時(shí),默認(rèn)片選引腳為PIO0_1。spi_speed 為時(shí)鐘信號(hào)的頻率,針對(duì)MX25L1606,其支持的最高頻率為86MHz,因此可以將該值直接設(shè)置為86000000。但由于LPC824 芯片的主頻為30MHz,所以SPI 最大速率僅30MHz。type 為具體器件的型號(hào),其包含了具體型號(hào)相關(guān)的信息,比如,頁大小信息等,當(dāng)前已經(jīng)支持的器件型號(hào)詳見am_mx25xx.h 中對(duì)應(yīng)的宏,MX25L1606 對(duì)應(yīng)的宏為:AM_MX25XX_MX25L1606。
基于以上信息,實(shí)例信息定義如下:
其中,g_mx25xx_devinfo 為用戶自定義的實(shí)例信息,其地址作為p_devinfo 的實(shí)參傳遞。
(3)SPI 句柄spi_handle
若使用LPC824 的SPI0 與MX25L1606 通信,則通過LPC82x 的SPI0 實(shí)例初始化函數(shù)am_lpc82x_spi0_inst_init()獲得SPI 句柄。即:
SPI 句柄即可直接作為spi_handle 的實(shí)參傳遞。
(4)實(shí)例句柄
MX25L1606 初始化函數(shù)am_mx25xx_init ()的返回值MX25L1606 實(shí)例的句柄,作為其它功能接口(擦除、讀、寫)的第一個(gè)參數(shù)(handle)的實(shí)參。
其類型am_mx25xx_handle_t(am_mx25xx.h)定義如下:
若返回值為NULL,說明初始化失敗;若返回值不為NULL,說明返回了有效的handle。
基于模塊化編程思想,將初始化相關(guān)的實(shí)例、實(shí)例信息等的定義存放到對(duì)應(yīng)的配置文件中,通過頭文件引出實(shí)例初始化函數(shù)接口,源文件和頭文件的程序范例分別詳見程序清單6.14 和程序清單6.15。
程序清單6.14 實(shí)例初始化函數(shù)范例程序(am_hwconf_mx25xx.c)
程序清單6.15 實(shí)例初始化函數(shù)接口(am_hwconf_mx25xx.h)
后續(xù)只需要使用無參數(shù)的實(shí)例初始化函數(shù),即可獲取到MX25xx 的實(shí)例句柄。即:
注意,spi_handle 用于區(qū)分SPI0、SPI1,mx25xx_handle 用于區(qū)分同一系統(tǒng)中的多個(gè)MX25xx 器件。
>>>6.2.3 接口函數(shù)
SPI Flash 比較特殊,在寫入數(shù)據(jù)前必須確保相應(yīng)的地址單元已經(jīng)被擦除,因此除讀寫函數(shù)外,還有一個(gè)擦除函數(shù),其接口函數(shù)詳見表6.6。
表6.6 MX25xx 接口函數(shù)
各API 的返回值含義都是相同的:AM_OK 表示成功,負(fù)值表示失敗,失敗原因可根據(jù)具體的值查看am_errno.h 文件中相對(duì)應(yīng)的宏定義。正值的含義由各API 自行定義,無特殊說明時(shí),表明不會(huì)返回正值。
1. 擦除
擦除就是將數(shù)據(jù)全部重置為0xFF,即所有存儲(chǔ)單元的位設(shè)置為1。擦除操作并不能直接擦除某個(gè)單一地址單元,擦除的最小單元為扇區(qū),即每次只能擦除單個(gè)或多個(gè)扇區(qū)。擦除一段地址空間的函數(shù)原型為:
其中,handle 為MX25L1606 的實(shí)例句柄,addr 為待擦除區(qū)域的首地址,由于擦除的最小單元為扇區(qū),因此該地址必須為某扇區(qū)的起始地址0x000000(0)、0x001000(4096)、0x002000(2×4096)……同時(shí),擦除長度必須為扇區(qū)大小的整數(shù)倍。
如果返回AM_OK,說明擦除成功,反之失敗。假定需要從0x001000 地址開始,連續(xù)擦除2 個(gè)扇區(qū),范例程序詳見程序清單6.16。
程序清單6.16 擦除范例程序
0x001000 ~ 0x3FFF 空間被擦除了,即可向該段地址空間內(nèi)寫入數(shù)據(jù)。
2. 寫入數(shù)據(jù)
在寫入數(shù)據(jù)前,需確保寫入地址已被擦除。即將需要變?yōu)? 的位清0,但寫入操作無法將0 變?yōu)?。比如,寫入數(shù)據(jù)0x55 就是將bit1、bit3、bit5、bit7 清0,其余位的值保持不變。若存儲(chǔ)的數(shù)據(jù)已經(jīng)是0x55,再寫入0xAA(寫入0xAA 實(shí)際上就是將bit0、bit2、bit4、bit6清0,其余位不變),則最終存儲(chǔ)的數(shù)據(jù)將變?yōu)?x00,而不是后面再寫入的0xAA。因此為了保證正常寫入數(shù)據(jù),寫入數(shù)據(jù)前必須確保相應(yīng)的地址段已經(jīng)被擦除了。
從指定的起始地址開始寫入一段數(shù)據(jù)的函數(shù)原型為:
如果返回AM_OK,說明寫入數(shù)據(jù)成功,反之失敗。假定從0x001000 地址開始,連續(xù)寫入128 字節(jié)數(shù)據(jù),范例程序詳見程序清單6.17。
程序清單6.17 寫入數(shù)據(jù)范例程序
雖然只寫入了128 字節(jié)數(shù)據(jù),但由于擦除的最小單元為扇區(qū),因此擦除了4096 字節(jié)(一個(gè)扇區(qū))。已經(jīng)擦除的區(qū)域后續(xù)可以直接寫入數(shù)據(jù),而不必再次擦除,比如,緊接著寫入128字節(jié)數(shù)據(jù)后的地址,再寫入128 字節(jié)數(shù)據(jù),詳見程序清單6.18。
程序清單6.18 寫入數(shù)據(jù)范例程序
若需要再次從0x001000 地址連續(xù)寫入128 字節(jié)數(shù)據(jù),由于之前已經(jīng)寫入過數(shù)據(jù),因此必須重新擦除后方可再次寫入。
3. 讀取數(shù)據(jù)
從指定的起始地址開始讀取一段數(shù)據(jù)的函數(shù)原型為:
如果返回值為AM_OK,則說明讀取成功,反之失敗。假定從0x001000 地址開始,連續(xù)讀取128 字節(jié)數(shù)據(jù),詳見程序清單6.19。
程序清單6.19 讀取數(shù)據(jù)范例程序
范例程序的實(shí)現(xiàn)和接口詳見程序清單6.20 和程序清單6.21。
程序清單6.20 MX25XX 測試程序?qū)崿F(xiàn)(app_test_mx25xx.c)
由于讀寫數(shù)據(jù)需要的緩存空間較大(128 字節(jié)),因此在緩存的定義前增加了static 修飾符,使其內(nèi)存空間從全局?jǐn)?shù)據(jù)區(qū)域中分配。如果直接從函數(shù)的運(yùn)行棧中分配128 字節(jié)空間,則完全有可能導(dǎo)致棧溢出,進(jìn)而系統(tǒng)崩潰。
程序清單6.21 MX25XX 測試程序接口聲明(app_test_mx25xx.h)
相應(yīng)的范例程序詳見程序清單6.22。
程序清單6.22 MX25L1602 讀寫范例程序
由于app_test_mx25xx()的參數(shù)為MX25XX 的實(shí)例handle,與MX25xx 器件具有依賴關(guān)系,因此無法實(shí)現(xiàn)跨平臺(tái)調(diào)用。
>>>6.2.4 MTD 通用接口函數(shù)
由于MX25L1606 是典型的FLASH 存儲(chǔ)器件,因此將其抽象為一個(gè)讀寫MX25L1606的MTD(Memory Technology Device),使之與具體器件無關(guān),實(shí)現(xiàn)跨平臺(tái)調(diào)用,其函數(shù)原型詳見表6.7。
表6.7 MTD 通用接口函數(shù)
1 MTD 初始化函數(shù)
MTD 初始化函數(shù)意在獲取MTD 實(shí)例句柄,其函數(shù)原型為:
其中,MX25L1606 實(shí)例句柄(mx25xx_handle)作為實(shí)參傳遞給handle,p_mtd 為指向am_mtd_serv_t 類型實(shí)例的指針,reserved_nblks 作為實(shí)例信息,表明保留的塊數(shù)。
實(shí)例(MTD 存儲(chǔ)設(shè)備)
定義am_mtd_serv_t 類型(am_mtd.h)實(shí)例如下:
其中,g_mx25xx_mtd 為用戶自定義的實(shí)例,其地址作為p_mtd 的實(shí)參傳遞。
實(shí)例信息
reserved_nblks 表示實(shí)例相關(guān)的信息,用于MX25L1606 保留的塊數(shù),這些保留的塊不會(huì)被MTD 標(biāo)準(zhǔn)接口使用。保留的塊從器件的起始?jí)K開始計(jì)算,若該值為5,則MX25XX 器件的塊0~塊4 將不會(huì)被MTD 使用,MTD 讀寫數(shù)據(jù)將從塊5 開始。如果沒有特殊需求,則該值設(shè)置為0。
將MTD 初始化函數(shù)的調(diào)用存放到配置文件中,引出對(duì)應(yīng)的實(shí)例初始化接口,詳見程序清單6.23 和程序清單6.24。
程序清單6.23 新增MTD 實(shí)例初始化函數(shù)(am_hwconf_mx25xx.c)
程序清單6.24 am_hwconf_mx25xx.h 文件內(nèi)容更新(1)
am_mx25xx_mtd_inst_init()函數(shù)無任何參數(shù),與其相關(guān)實(shí)例和實(shí)例信息的定義均在文件內(nèi)部完成,因此直接調(diào)用該函數(shù)即可獲得MTD 句柄。即:
這樣一來,在后續(xù)使用其它MTD 通用接口函數(shù)時(shí),均可使用該函數(shù)的返回值mtd_handle作為第一個(gè)參數(shù)(handle)的實(shí)參傳遞。
顯然,若使用MX25XX 接口,則調(diào)用am_mx25xx_inst_init()獲取MX25XX 實(shí)例句柄;若使用MTD 通用接口,則調(diào)用am_mx25xx_mtd_inst_init()獲取MTD 實(shí)例句柄。
2. 擦除
寫入數(shù)據(jù)前需要確保相應(yīng)地址已經(jīng)被擦除,其函數(shù)原型為:
擦除單元的大小可以使用宏AM_MTD_ERASE_UNIT_SIZE_GET()獲得。比如:
其中的addr 表示擦除區(qū)域的首地址,必須為擦除單元大小的整數(shù)倍。同樣地,len 也必須為擦除單元大小的整數(shù)倍。由于MX25L1606 擦除單元的大小與扇區(qū)大?。?096)一樣,因此addr 必須為某扇區(qū)的起始地址0x000000(0)、0x001000(4096)、0x002000(2×4096)……
如果返回AM_OK,說明擦除成功,反之失敗。假定從0x001000 地址開始,連續(xù)擦除2個(gè)扇區(qū),范例程序詳見程序清單6.25。
程序清單6.25 擦除范例程序
使用該段程序后,地址空間0x001000 ~ 0x3FFF 即被擦除了,后續(xù)即可向該段地址空間內(nèi)寫入數(shù)據(jù)。
3. 寫入數(shù)據(jù)
寫入數(shù)據(jù)前需要確保寫入地址已被擦除,其函數(shù)原型為:
如果返回AM_OK,說明寫入數(shù)據(jù)成功,反之失敗。假定從0x001000 地址開始,連續(xù)寫入128 字節(jié)數(shù)據(jù)的范例程序詳見程序清單6.26。
程序清單6.26 寫入數(shù)據(jù)范例程序
4. 讀取數(shù)據(jù)
從指定的起始地址開始讀取一段數(shù)據(jù)的函數(shù)原型為:
如果返回值為AM_OK,則說明讀取成功,反之失敗。假定從0x001000 地址開始,連續(xù)讀取128 字節(jié)數(shù)據(jù)的范例程序詳見程序清單6.27。
程序清單6.27 讀取數(shù)據(jù)范例程序
MTD 通用接口測試程序和接口分別詳見程序清單6.28 和程序清單6.29。
程序清單6.28 MTD 測試程序?qū)崿F(xiàn)(app_test_mtd.c)
程序清單6.29 接口聲明(app_test_mtd.h)
由于該程序只需要MTD 句柄,因此與具體器件無關(guān),可以實(shí)現(xiàn)跨平臺(tái)復(fù)用。若讀寫數(shù)據(jù)的結(jié)果完全相等,則返回AM_OK,反之返回AM_ERROR,范例程序詳見程序清單6.30。
程序清單6.30 MTD 讀寫范例程序
>>>6.2.5 FTL 通用接口函數(shù)
由于此前的接口需要在每次寫入數(shù)據(jù)前,確保相應(yīng)的存儲(chǔ)空間已經(jīng)被擦除,則勢必會(huì)給編程帶來很大的麻煩。與此同時(shí),由于MX25L1606 的某一地址段擦除次數(shù)超過10 萬次的上限,則在相應(yīng)段地址空間存儲(chǔ)數(shù)據(jù)將不再可靠。
假設(shè)將用戶數(shù)據(jù)存放到0x001000~0x001FFF 連續(xù)的4K 地址中,則每次更新這些數(shù)據(jù)都要重新擦除該地址段。而其它存儲(chǔ)空間完全沒有使用過,MX25L1606 的使用壽命大打折扣。AMetal 提供了FTL(Flash Translation Layer)通用接口供用戶使用,其函數(shù)原型詳見表6.8。
表6.8 FTL 通用接口函數(shù)(am_ftl.h)
1. FTL 初始化函數(shù)
FTL 初始化函數(shù)意在獲取FTL 實(shí)例句柄,其函數(shù)原型為:
其中,p_ftl 為指向am_ftl_serv_t 類型實(shí)例的指針,p_buf 和len 作為實(shí)例信息,為FTL驅(qū)動(dòng)程序提供必要的RAM 空間,MTD 初始化函數(shù)獲得mtd_handle 為MTD 實(shí)例句柄。
(1)實(shí)例
定義am_ftl_serv_t 類型(am_mtd.h)實(shí)例如下:
其中,g_ftl 為用戶自定義的實(shí)例,其地址作為p_ftl 的實(shí)參傳遞。
(2)實(shí)例信息
FTL 驅(qū)動(dòng)程序需要使用一定的RAM 空間,這也是使用FTL 通用接口所要付出的代價(jià)。由于該空間的大小與具體器件的容量大小、擦除單元大小相關(guān),因此該內(nèi)存空間由用戶根據(jù)實(shí)際情況提供。需要的內(nèi)存大?。ㄗ止?jié)數(shù))由下面的公式得到:
其中,sizeerase 為擦除單元的大小,對(duì)于MX25L1606,其為扇區(qū)大小,即4096。sizemtd_chip為MTD 實(shí)例的總?cè)萘?。MX25L1606 對(duì)應(yīng)的MTD 實(shí)例,其大小為除去保留塊的總?cè)萘浚舯A魤K為0,就是MX25L1606 的容量大小,即2M。需要的內(nèi)存容量大小為:
對(duì)于MX25L1606,若使用FTL,則需要大約2.5KB 的RAM。顯然對(duì)于一些小型嵌入式系統(tǒng)來說,RAM 的耗費(fèi)實(shí)在“太大”了,所以要根據(jù)實(shí)際情況選擇是否使用FTL。若RAM充足,而又比較在意Flash 的使用壽命,可以選擇使用FTL。容量大小使用am_ftl.h 中的宏:
該宏根據(jù)器件總?cè)萘亢筒脸龁卧笮?,自?dòng)計(jì)算實(shí)際需要的RAM 大小。
若使用FTL 通用接口操作MX25L1606,則需要定義如下內(nèi)存空間供FTL 使用。即:
其中,g_ftl_buf 為內(nèi)存空間的首地址,其作為p_buf 的實(shí)參傳遞,內(nèi)存空間的大?。磾?shù)組元素的個(gè)數(shù))作為len 的實(shí)參傳遞。
(3)MTD 句柄mtd_handle
該MTD 句柄可以通過MTD 實(shí)例初始化函數(shù)獲得。即:
獲得的MTD 句柄即可直接作為mtd_handle 的實(shí)參傳遞。
(4)實(shí)例句柄
FTL 初始化函數(shù)am_ftl_init ()的返回值為FTL 實(shí)例句柄,該句柄將作為讀寫接口第一個(gè)參數(shù)(handle)的實(shí)參。其類型am_ftl_handle_t(am_ftl.h)定義如下:
若返回值為NULL,說明初始化失??;若返回值不為NULL,說明返回了有效的handle。
將FTL 初始化函數(shù)的調(diào)用存放到配置文件中,引出對(duì)應(yīng)的實(shí)例初始化接口,詳見程序清單6.31 和程序清單6.32。
程序清單6.31 新增FTL 實(shí)例初始化函數(shù)(am_hwconf_mx25xx.c)
程序清單6.32 am_hwconf_mx25xx.h 文件內(nèi)容更新(2)
am_mx25xx_ftl_inst_init()無任何參數(shù),與其相關(guān)實(shí)例和實(shí)例信息的定義均在文件內(nèi)部完成,因此直接調(diào)用該函數(shù)即可獲得FTL 句柄。即:
這樣一來,在后續(xù)使用其它FTL 通用接口函數(shù)時(shí),均可使用該函數(shù)的返回值ftl_handle作為第一個(gè)參數(shù)(handle)的實(shí)參傳遞。
2. 寫入數(shù)據(jù)
當(dāng)調(diào)用FTL 通用接口時(shí),讀寫數(shù)據(jù)都是以塊為單位,每塊數(shù)據(jù)的字節(jié)數(shù)固定為512 字節(jié)。其函數(shù)原型為:
為了延長Flash 的使用壽命,在實(shí)際寫入時(shí),會(huì)數(shù)據(jù)寫入到擦除次數(shù)最少的區(qū)域。因此lbn 只是一個(gè)邏輯塊序號(hào),與實(shí)際的存儲(chǔ)地址沒有關(guān)系。邏輯塊只是一個(gè)抽象的概念,每個(gè)邏輯塊的大小固定為512 字節(jié),與MX25L1606 的物理存儲(chǔ)塊沒有任何關(guān)系。
由于MX25L1606 每個(gè)邏輯塊固定為512 字節(jié),因此理論上邏輯塊的個(gè)數(shù)為4096(2×1024×1024÷512),lbn 的有效值為0 ~ 4095。但實(shí)際上擦除每個(gè)單元都要耗費(fèi)一個(gè)邏輯塊,MX25L1606 擦除單元的大小為4096,即512 個(gè)擦除單元,因此FTL 消耗了512 個(gè)邏輯塊,則可用的邏輯塊為3584(4096~512)個(gè),lbn 的有效值為0~3583。
由此可見,F(xiàn)TL 不僅要占用2.5K RAM,還要占用256K 的MX25L1606 存儲(chǔ)空間(512個(gè)邏輯塊,每個(gè)邏輯塊大小為512 字節(jié)),這也是使用FTL 要付出的“代價(jià)”。如果返回AM_OK,說明寫入數(shù)據(jù)成功,反之失敗。假定寫入一塊數(shù)據(jù)(512 字節(jié))至邏輯塊2 中,其范例程序詳見程序清單6.33。
程序清單6.33 寫入數(shù)據(jù)范例程序
3. 讀取數(shù)據(jù)
讀取一塊數(shù)據(jù)的函數(shù)原型為:
如果返回值為AM_OK,則說明讀取成功,反之失敗。假定從邏輯塊2 中讀取一塊(512字節(jié))數(shù)據(jù),其范例程序詳見程序清單6.34。
程序清單6.34 讀取數(shù)據(jù)范例程序
FTL 通用接口測試程序和接口分別詳見程序清單6.35 和程序清單6.36。
程序清單6.35 FTL 測試程序?qū)崿F(xiàn)(app_test_ftl.c)
程序清單6.36 FTL 測試接口聲明(app_test_ftl.h)
由于寫入前無需再執(zhí)行擦除操作,則編寫應(yīng)用程序更加便捷。同樣,由于應(yīng)用程序僅僅只需要FTL 句柄,則所有接口也全部為FTL 通用接口,因此應(yīng)用程序是可以跨平臺(tái)復(fù)用的,范例程序詳見程序清單6.37。
程序清單6.37 FTL 讀寫范例程序
>>>6.2.6 微型數(shù)據(jù)庫
由于哈希表所使用的鏈表頭數(shù)組空間、關(guān)鍵字和記錄值等都存儲(chǔ)在malloc 分配的動(dòng)態(tài)空間中,這些信息在程序結(jié)束或系統(tǒng)掉電后都會(huì)丟失。在實(shí)際的應(yīng)用中,往往希望將信息存儲(chǔ)在非易失存儲(chǔ)器中。典型的應(yīng)用是將信息存儲(chǔ)在文件中,從本質(zhì)上來看,只要掌握了哈希表的原理,無論信息存儲(chǔ)在什么地方,操作的方式都是一樣的。
在AMetal 中,基于非易失存儲(chǔ)器實(shí)現(xiàn)了一套可以直接使用的哈希表接口,由于數(shù)據(jù)不會(huì)因?yàn)榈綦娀虺绦蚪K止而丟失,因此可以將其視為一個(gè)微型數(shù)據(jù)庫,相關(guān)接口詳見表6.9。
表6.9 數(shù)據(jù)庫接口(hash_kv.h)
顯然,除命名空間由 hash_db_*修改為了hash_kv_*(為了與之前的程序進(jìn)行區(qū)分)外,僅僅是初始化函數(shù)中,多了一個(gè)文件名參數(shù),即內(nèi)部不再使用malloc 分配空間存儲(chǔ)記錄信息,而是使用該文件名指定的文件存儲(chǔ)相關(guān)信息。如此一來記錄存儲(chǔ)在文件中,信息不會(huì)因掉電或程序終止而丟失。其中,hash_kv_t 為數(shù)據(jù)庫結(jié)構(gòu)體類型,使用數(shù)據(jù)庫前,應(yīng)使用該類型定義一個(gè)數(shù)據(jù)庫實(shí)例,比如,“hash_kv_t hash;”。
由于各個(gè)函數(shù)的功能與《程序設(shè)計(jì)與數(shù)據(jù)結(jié)構(gòu)》一書中介紹的哈希表的各個(gè)函數(shù)的功能完全一致,因此可以使用如程序清單6.38 所示的代碼進(jìn)行測試驗(yàn)證。
程序清單6.38 數(shù)據(jù)庫綜合范例程序
-
FlaSh
+關(guān)注
關(guān)注
10文章
1633瀏覽量
147935 -
SPI
+關(guān)注
關(guān)注
17文章
1706瀏覽量
91498 -
外設(shè)驅(qū)動(dòng)器
+關(guān)注
關(guān)注
0文章
3瀏覽量
3420 -
ametal
+關(guān)注
關(guān)注
2文章
24瀏覽量
11398
原文標(biāo)題:周立功:重用外設(shè)驅(qū)動(dòng)代碼——SPI NOR Flash 存儲(chǔ)器
文章出處:【微信號(hào):Zlgmcu7890,微信公眾號(hào):周立功單片機(jī)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論