<前言>
恭喜發財,本篇就一些改進apt-get指令的問題做研究,另外關於大檔案解壓縮還是存在問題,文末會附上編譯好的Kernel鏡像檔案uImage,可供小伙伴們替換用,將有效降低錯誤發生機率
<準備>
1. Nano Pi 2開發板
2. 5V 2A Adapter(電源)
3. MicroUSB傳輸線
4. 7吋觸控LCD, 有附
<修改的部分程式碼>
1. 關於mmc上的Bus共有三個,其中mmc0給開機用SD卡槽,mmc1給Wifi模塊用(SDIO),mmc2給擴充用的SD卡槽,以下是原理圖
SD卡使用mmc0作為開機,mmc2作為擴充
SD卡mmc0的電路圖
SD卡之mmc2的電路圖
Wifi模塊使用mmc1電路圖
2. 打開Kernel 3.4.39的source tree中的檔案linux-3.4.y/arch/arm/plat-s5p4418/nanopi2/device.c,這是官方提供Nano Pi 2的板級定義原始碼,找到關於mmc的外設定義,原始碼如下:
static struct dw_mci_board _dwmci0_data = { .quirks = DW_MCI_QUIRK_HIGHSPEED, .bus_hz = 100 * 1000 * 1000, .caps = MMC_CAP_4_BIT_DATA | MMC_CAP_CMD23, .caps2 = MMC_CAP2_BROKEN_VOLTAGE, .detect_delay_ms= 200, .cd_type = DW_MCI_CD_EXTERNAL, .clk_dly = DW_MMC_DRIVE_DELAY(0) | DW_MMC_SAMPLE_DELAY(0) | DW_MMC_DRIVE_PHASE(2) | DW_MMC_SAMPLE_PHASE(1), .init = _dwmci0_init, .get_cd = _dwmci0_get_cd, .get_ro = _dwmci_get_ro, .ext_cd_init = _dwmci_ext_cd_init, .ext_cd_cleanup = _dwmci_ext_cd_cleanup, #if defined (CONFIG_MMC_DW_IDMAC) && defined (CONFIG_MMC_NXP_CH0_USE_DMA) .mode = DMA_MODE, #else .mode = PIO_MODE, #endif }; static struct dw_mci_board _dwmci1_data = { .quirks = DW_MCI_QUIRK_BROKEN_CARD_DETECTION | DW_MCI_QUIRK_HIGHSPEED, .bus_hz = 100 * 1000 * 1000, .caps = MMC_CAP_4_BIT_DATA | MMC_CAP_CMD23 | MMC_CAP_NONREMOVABLE, .detect_delay_ms= 200, .cd_type = DW_MCI_CD_NONE, .pm_caps = MMC_PM_KEEP_POWER | MMC_PM_IGNORE_PM_NOTIFY, .clk_dly = DW_MMC_DRIVE_DELAY(0) | DW_MMC_SAMPLE_DELAY(0) | DW_MMC_DRIVE_PHASE(2) | DW_MMC_SAMPLE_PHASE(1), #if defined (CONFIG_MMC_DW_IDMAC) && defined (CONFIG_MMC_NXP_CH1_USE_DMA) .mode = DMA_MODE, #else .mode = PIO_MODE, #endif }; static struct dw_mci_board _dwmci2_data = { .quirks = DW_MCI_QUIRK_HIGHSPEED, .bus_hz = 100 * 1000 * 1000, .caps = MMC_CAP_4_BIT_DATA | MMC_CAP_CMD23 | MMC_CAP_HW_RESET, .cd_type = DW_MCI_CD_EXTERNAL, .clk_dly = DW_MMC_DRIVE_DELAY(0) | DW_MMC_SAMPLE_DELAY(0) | DW_MMC_DRIVE_PHASE(2) | DW_MMC_SAMPLE_PHASE(1), .init = _dwmci2_init, .get_cd = _dwmci2_get_cd, .get_ro = _dwmci_get_ro, .desc_sz = 4, .detect_delay_ms= 200, .sdr_timing = 0x01010001, .ddr_timing = 0x03030002, #if defined (CONFIG_MMC_DW_IDMAC) && defined (CONFIG_MMC_NXP_CH2_USE_DMA) .mode = DMA_MODE, #else .mode = PIO_MODE, #endif };
在結構體dw_mci_board中定義了所有mmc Bus的各項參數值,參考了其他公板和其他廠商的s5p4418開發板,我關注在.caps這項屬性,結構體原型定義在/linux-3.4.y/include/linux/mmc/dw_mmc.h中:
unsigned int caps; // Capabilities unsigned int caps2; // More capabilities unsigned int pm_caps; // supported pm features由此可得知是設定Bus屬性的重要參數,對照了以後發現Nano Pi 2多了MMC_CAP_4_BIT_DATA這個設定,這個設定出處在/linux-3.4.y/include/linux/mmc/host.h中:
#define MMC_CAP_4_BIT_DATA (1 << 0) // Can the host do 4 bit transfers #define MMC_CAP_MMC_HIGHSPEED (1 << 1) // Can do MMC high-speed timing #define MMC_CAP_SD_HIGHSPEED (1 << 2) // Can do SD high-speed timing #define MMC_CAP_SDIO_IRQ (1 << 3) // Can signal pending SDIO IRQs #define MMC_CAP_SPI (1 << 4) // Talks only SPI protocols #define MMC_CAP_NEEDS_POLL (1 << 5) // Needs polling for card-detection #define MMC_CAP_8_BIT_DATA (1 << 6) // Can the host do 8 bit transfers假設s5p4418的mmc控制器根本不支持4Bit的傳輸模式,因此我將三個Bus上的MMC_CAP_4_BIT_DATA的設定值全部去掉
3. 修改完成後,三個mmc Bus的設定原始碼如下:
static struct dw_mci_board _dwmci0_data = { .quirks = DW_MCI_QUIRK_HIGHSPEED, .bus_hz = 100 * 1000 * 1000, .caps = MMC_CAP_CMD23, .caps2 = MMC_CAP2_BROKEN_VOLTAGE, .detect_delay_ms= 200, .cd_type = DW_MCI_CD_EXTERNAL, .clk_dly = DW_MMC_DRIVE_DELAY(0) | DW_MMC_SAMPLE_DELAY(0) | DW_MMC_DRIVE_PHASE(2) | DW_MMC_SAMPLE_PHASE(1), .init = _dwmci0_init, .get_cd = _dwmci0_get_cd, .get_ro = _dwmci_get_ro, .ext_cd_init = _dwmci_ext_cd_init, .ext_cd_cleanup = _dwmci_ext_cd_cleanup, #if defined (CONFIG_MMC_DW_IDMAC) && defined (CONFIG_MMC_NXP_CH0_USE_DMA) .mode = DMA_MODE, #else .mode = PIO_MODE, #endif }; static struct dw_mci_board _dwmci1_data = { .quirks = DW_MCI_QUIRK_BROKEN_CARD_DETECTION | DW_MCI_QUIRK_HIGHSPEED, .bus_hz = 100 * 1000 * 1000, .caps = MMC_CAP_CMD23 | MMC_CAP_NONREMOVABLE, .detect_delay_ms= 200, .cd_type = DW_MCI_CD_NONE, .pm_caps = MMC_PM_KEEP_POWER | MMC_PM_IGNORE_PM_NOTIFY, .clk_dly = DW_MMC_DRIVE_DELAY(0) | DW_MMC_SAMPLE_DELAY(0) | DW_MMC_DRIVE_PHASE(2) | DW_MMC_SAMPLE_PHASE(1), #if defined (CONFIG_MMC_DW_IDMAC) && defined (CONFIG_MMC_NXP_CH1_USE_DMA) .mode = DMA_MODE, #else .mode = PIO_MODE, #endif }; static struct dw_mci_board _dwmci2_data = { .quirks = DW_MCI_QUIRK_HIGHSPEED, .bus_hz = 100 * 1000 * 1000, .caps = MMC_CAP_CMD23 | MMC_CAP_HW_RESET, .cd_type = DW_MCI_CD_EXTERNAL, .clk_dly = DW_MMC_DRIVE_DELAY(0) | DW_MMC_SAMPLE_DELAY(0) | DW_MMC_DRIVE_PHASE(2) | DW_MMC_SAMPLE_PHASE(1), .init = _dwmci2_init, .get_cd = _dwmci2_get_cd, .get_ro = _dwmci_get_ro, .desc_sz = 4, .detect_delay_ms= 200, .sdr_timing = 0x01010001, .ddr_timing = 0x03030002, #if defined (CONFIG_MMC_DW_IDMAC) && defined (CONFIG_MMC_NXP_CH2_USE_DMA) .mode = DMA_MODE, #else .mode = PIO_MODE, #endif };以上是修改好的程式碼,可以開始編譯來替換官方的鏡像檔中的Kernel檔
4. 打開虛擬機上的Terminal,輸入以下指令開始編譯Kernel,這裡假設您已經架設好編譯環境
make uImage -j8
至此就完成了工作,可將檔案替換SD卡第一分區的uImage檔案,此為LCD用的Kernel檔
<驗證>
5. 本來我的Nano Pi 2使用apt-get指令更新時候,會一次成功一次失敗交替,即Hash Sum的錯誤,替換後可有效降低更新時發生錯誤的機率,文末附上編譯好的檔案,要注意的是,對於此CPU而言,SD卡當系統仍然相當不穩定(已測試過4種SD卡)
替換後仍然會有幾次更新失敗
替換後連續更新成功
<檔案下載>
<小結>
此Patch主要依據各廠商mmc控制器上的原始碼設定來比較差異,再進行修改,有效降低錯誤發生率,但仍然建議使用emmc當作系統啟動媒體,能夠觸類旁通,另外,關於大型檔案的解壓縮仍然存在問題
作者:MOP 發布於:ICKEY社區