[NanoPi 2学习笔记] 降低apt-get之mmc控制器錯誤風險

  • MOP
  • LV5工程师
  • |      2016-02-07 19:14:01
  • 浏览量 1786
  • 回复:0

<前言>

恭喜發財 修復apt-get之mmc控制器問題,本篇就一些改進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卡槽,以下是原理圖

 修復apt-get之mmc控制器問題

SD卡使用mmc0作為開機,mmc2作為擴充


 修復apt-get之mmc控制器問題

SD卡mmc0的電路圖


 修復apt-get之mmc控制器問題

SD卡之mmc2的電路圖


 修復apt-get之mmc控制器問題

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社區

  • 0
  • 收藏
  • 举报
  • 分享
我来回复

登录后可评论,请 登录注册

所有回答 数量:0
x
收藏成功!点击 我的收藏 查看收藏的全部帖子