ã€æ‘˜ è¦ã€‘ 簡明介紹MMCå¡é©…動程åºçš„é«”ç³»çµæ§‹ï¼Œè¨è¨ˆå¹¶å¯¦ç¾MMCå¡çš„底層驅動;å°å‚³çµ±çš„塊è¨å‚™é©…動程åºä¸çš„單塊讀寫進行改進,實ç¾MMCå¡çš„é›†ç¾¤è®€å¯«ï¼ŒåŒæ™‚實ç¾äº†å¡çš„é›»æºç®¡ç†å’Œå³æ’å³ç”¨åŠŸèƒ½ã€‚
  
ã€é—œéµè©žã€‘ Linux MMCå¡ åº•å±¤é©…å‹• 集群讀寫 熱拔æ’
引 言
  
MMC(Multitmedia Card)是一種體ç©å°å·§ã€å®¹é‡å¤§ã€ä½¿ç”¨æ–¹ä¾¿çš„å˜å„²å™¨ï¼Œç›®å‰åœ¨æ‰‹æ©Ÿç‰åµŒå…¥å¼ç³»çµ±ä¸æœ‰è‘—廣泛的應用。MMC通éŽå¡å…§çš„一個集æˆç‰‡å…§æŽ§åˆ¶å™¨å°MMCå¡é€²è¡ŒæŽ§åˆ¶å’Œç®¡ç†ï¼Œç•¶ä¸»æ©Ÿæ£ç¢ºåœ°é©…å‹•MMCå¡åŽï¼Œå°±å¯ä»¥åƒç£ç›¤ä¸€æ¨£æ–¹ä¾¿åœ°å˜å–æ•¸æ“šã€‚æœ¬æ–‡æ‰€ç ”ç©¶èˆ‡å¯¦ç¾çš„Linux驅動程åºï¼Œä»¥Intel XScaleçš„PXA250為硬件平臺,在éµå¾ªMMCå¡é€šä¿¡å”è°è¦èŒƒçš„基礎上,實ç¾äº†å¡çš„底層讀寫。然åŽå°å‚³çµ±çš„塊è¨å‚™é©…動程åºä¸çš„單塊讀寫進行了改進,實ç¾äº†é›†ç¾¤è®€å¯«æŠ€è¡“,æé«˜äº†å¡çš„è®€å¯«é€Ÿåº¦ï¼›åŒæ™‚å¢žåŠ äº†é›»æºç®¡ç†åŠŸèƒ½ï¼Œæ»¿è¶³äº†åµŒå…¥å¼ç³»çµ±ä½ŽåŠŸè€—çš„éœ€æ±‚ï¼›å¢žåŠ äº†å³æ’å³ç”¨åŠŸèƒ½ï¼Œæ–¹ä¾¿äº†ç”¨æˆ¶çš„ä½¿ç”¨ã€‚
1 MMCå¡é©…動程åºçš„é«”ç³»çµæ§‹
  
MMCå¡åƒ…通éŽ5個引腳與主機的控制器相連,通éŽä¸²è¡Œå”è°èˆ‡ä¸»æ©Ÿé€šä¿¡ã€‚MMCå¡åœ¨ç¡¬ä»¶ä¸Šçš„ç°¡å–®æ§‹é€ å¿…ç„¶å°Žè‡´åœ¨å¯¦ç¾é©…動程åºä¸Šçš„å¾©é›œã€‚ä¾æ“šMMCå¡çš„通信擲è°è¦èŒƒå’ŒLinux驅動程åºçš„çµæ§‹ï¼ŒæŠŠé©…動程åºåŽŸæœ‰çš„åº•å±¤é©…å‹•ã€å®ˆè·ç·šç¨‹ã€å–®å¡Šè®€å¯«é€²è¡Œæ”¹é€²å’Œæ“´å±•ï¼Œå…¶çµæ§‹å±¤æ¬¡å†åŠƒåˆ†ç‚ºåº•å±¤é©…å‹•ã€å®ˆè·ç·šç¨‹ã€é›†ç¾¤è®€å¯«ã€é›»æºç®¡ç†åŠç†±æ‹”æ’管ç†5個部分,如圖l所示。

圖1ä¸å„部分的功能為:
  ①底層驅動——處ç†ç›´æŽ¥æ¶‰åŠèˆ‡MMCå¡ç¡¬ä»¶å¯„å˜å™¨ç«¯å£çš„æ“ä½œï¼ŒåŒ…æ‹¬ï¼šå‘½ä»¤çš„ç™¼å¸ƒå’ŒéŸ¿æ‡‰ã€ä¸æ–·éŸ¿æ‡‰å’Œè™•ç†ã€PIO或者DMAé€šé“æ•¸æ“šå‚³è¼¸ç‰ã€‚
  ②集群讀寫——將ç£ç›¤ç›¸é„°æ•¸æ“šå¡Šçš„讀寫請求åˆå¹¶èµ·ä¾†ä¸€èµ·ç™¼å¸ƒè®€å¯«å‘½ä»¤ï¼Œä»¥åŠ å¿«æ•¸æ“šè®€å¯«ï¼Œå¹¶åœ¨è®€å¯«ä¸å¯¦ç¾å¹¶ç™¼æŽ§åˆ¶ã€‚
  ③電æºç®¡ç†â€”—實ç¾MMCå¡çš„低功耗管ç†ã€‚
  ④熱拔æ’管ç†â€”—實ç¾MMCå¡çš„峿’å³ç”¨åŠŸèƒ½ã€‚
  ⑤守è·ç·šç¨‹â€”—響應文件系統的讀寫請求并啟動å°å¡çš„1/O。
2 MMCå¡é©…動程åºçš„實ç¾
  
2.1 底層驅動
  
底層驅動指的是直接å°MMCå¡é€²è¡Œæ“作。MMCå¡é‡‡ç”¨ä¸²è¡Œçš„æ•¸æ“šå‚³è¼¸æ–¹å¼ï¼›æ˜¯ä¸€ç¨®æ¯”較“精細â€çš„å¡ï¼Œå°å®ƒçš„æ“ä½œæ¯”è¼ƒå¾©é›œè€Œä¸”å¿…é ˆæœ‰æº–ç¢ºçš„æ™‚åºå®‰æŽ’。以下從命令的發布和響應ã€ä¸æ–·éŸ¿æ‡‰å’Œè™•ç†ã€DMA數據傳輸3個方é¢è¬›è¿°å¦‚何進行底層讀寫驅動。
(1)命令發布和響應
  
MMCå¡çš„æ“ä½œæ˜¯é€šéŽå°å…¶18個控制寄å˜å™¨çš„讀寫實ç¾çš„。首先,è¨ç½®æ™‚é˜èµ·åœå¯„å˜å™¨MMC_STRCPL的最低兩ä½ç‚º01.關閉MMCå¡å…§éƒ¨æ™‚é˜ã€‚ç„¶åŽï¼Œè¨ç½®ä¸æ–·å±è”½å¯„å˜å™¨MMC_LMASK的最低7ä½éƒ½ç‚º1,å±è”½æ‰€æœ‰å°MMCæŽ§åˆ¶å™¨çš„ä¸æ–·ï¼Œå†å‘指定的MMC控制寄å˜å™¨ä¸å¯«å…¥å‘½ä»¤åƒæ•¸ï¼Œå¦‚時é˜é »çއè¨ç½®å¯„å˜å™¨MMC_CLKRT,讀寫塊數寄å˜å™¨MMC_NOB,命令寄å˜å™¨MMC_CMDç‰ã€‚最åŽï¼Œæ‰“開內部時é˜ï¼Œè§£é™¤å±è”½çš„䏿–·ã€‚這時,當å‰è®€å¯«é€²ç¨‹é€²å…¥ç¡çœ 狀態,ç‰å¾…䏿–·è™•ç†ç¨‹åºçš„喚醒。
(2ï¼‰ä¸æ–·éŸ¿æ‡‰å’Œè™•ç†
MMCå¡åœ¨æ•¸æ“šå‚³è¼¸è«‹æ±‚ã€å…§éƒ¨æ™‚é˜é—œé–‰ã€å‘½ä»¤ç™¼å¸ƒå®Œç•¢ã€æ•¸æ“šå‚³è¼¸å®Œç•¢çš„æƒ…æ³ä¸‹éƒ½æœƒç”¢ç”Ÿä¸æ–·ï¼Œä½†è¶³MMCå¡çš„æŽ§åˆ¶å™¨åªé€šéŽ1裉GPIO23的引腳與CPUç›¸é€£ï¼Œç”¨äºŽä¸æ–·ä¿¡è™Ÿç·šçš„å¾©ç”¨ï¼›å› æ¤åœ¨ä¸æ–·è™•ç†ç¨‹åºä¸ï¼Œå¿…é ˆé¦–å…ˆåˆ¤æ–·åˆ°åº•æ˜¯å“ªç¨®åŽŸå› ç”¢ç”Ÿçš„ä¸æ–·ï¼Œç„¶åŽå†é€²è¡Œç›¸æ‡‰çš„處ç†ã€‚這里,MMCå¡åœ¨æ£ç¢ºç™¼å¸ƒè®€å¯«å‘½ä»¤ä»¥åŽï¼Œç³»çµ±æœƒç”¢ç”Ÿ1æ¬¡ä¸æ–·ï¼Œä¸æ–·è™•ç†ç¨‹åºä¸è®€å–MMC_IREG的值,判斷命令已經發布æˆåŠŸï¼ŒåŒæ™‚喚醒ç‰å¾…命令完æˆçš„進程。
è®€å¯«é€²ç¨‹è¢«ä¸æ–·å–šé†’åŽï¼Œé¦–先讀å–MMCå¡éŸ¿æ‡‰å¯„å˜å™¨MMC_RESä¸çš„狀態信æ¯ï¼Œå†æ ¹æ“šé€™äº›ç‹€æ…‹ä¿¡æ¯åˆ¤æ–·å‘½ä»¤æ˜¯å¦ç™¼å¸ƒæˆåŠŸå’Œå¡çš„ç•¶å‰ç‹€æ…‹ã€‚如果這些狀態信æ¯è¡¨ç¤ºå‘½ä»¤åŸ·è¡ŒæˆåŠŸï¼Œå‰‡é€šéŽè®€å¯«ç·©æ²–寄å˜å™¨MMC_RXFIFOå’ŒMMC_TXFIFO進行數據的讀寫(這里使用DMA進行數據傳輸,æé«˜äº†æ•¸æ“šçš„傳輸速度);如果返回的狀態信æ¯è¡¨æ˜Žå‘½ä»¤åŸ·è¡Œä¸æˆåŠŸï¼Œå‰‡æ ¹æ“šç‹€å¿µä¿¡æ¯é€²è¡Œç›¸æ‡‰çš„出錯處ç†ã€‚
(3)DMA數據傳輸
驅動程åºä¸å°MMCå¡çš„æ•¸æ“šè®€å¯«æ˜¯é€šéŽDMA通é“é€²è¡Œå‚³è¼¸çš„ã€‚ç‚ºäº†ä¿æ±ªæ“作的連續性,驅動程åºå°MMCå¡çš„輸入和輸出緩沖å„è¨ç½®1個DMA通é“,在進行實際數據傳輸時,讀寫進程也進入ç¡çœ 狀態,ç‰å¾…DMA數據傳輸完畢åŽï¼Œè¢«DMA䏿–·å–šé†’。實ç¾ä¸€æ¬¡è®€æ“作的å½ä»£ç¢¼å¦‚下:
  Pxa_read_mmc(){
  關閉時é˜ï¼Œå±è”½ä¸æ–·ï¼›
  è¨ç½®è®€å¯«å¯„å˜å™¨çš„內容; /*讀寫塊數,起始塊數,讀寫速度ç‰ï¼Šï¼
  打開時é˜ï¼Œç™¼å¸ƒè®€å¯«å‘½ä»¤ï¼›
  Interruptible_sleep_on(); ï¼ï¼Šé€²å…¥å¯æ‰“æ–·ç¡çœ 狀態,ç‰å¾…䏿–·ç¨‹åºçš„喚醒*ï¼
ã€€ã€€è¢«ä¸æ–·ç¨‹åºå–šé†’,打開DMA通é“ï¼Œé€²è¡Œæ•¸æ“šå‚³è¼¸ï¼Œå†æ¬¡é€²å…¥å¯æ‰“æ–·ç¡çœ 狀態;
  被DMAå‚³è¼¸å®Œç•¢ä¸æ–·å–šé†’ï¼Œç™¼å¸ƒçµæŸå‚³è¼¸å‘½ä»¤ï¼ŒçµæŸæ•¸æ“šå‚³è¼¸ï¼›
2.2 集群(clustering)讀寫和并發控制
  
2.2.1 傳統的塊è¨å‚™é©…動程åºçµæ§‹å’Œä¸è¶³
  
å¡Šæ²’å‚™é©…å‹•ç¨‹åºæ˜¯Linuxç³»çµ±ä¸æœ€å¾©é›œçš„驅動程åºä¹‹ä¸€ï¼Œåƒé–±æ–‡ç»[3,4]å¯ä»¥è©³ç´°äº†è§£Linux塊è¨å‚™é©…動程åºã€‚é€™é‡Œç°¡å–®ä»‹ç´¹èˆ‡é›†ç¾¤è®€å¯«ç›¸é—œçš„æ•¸æ“šçµæ§‹å’Œæ“作。扇å€ï¼ˆseetor)是塊è¨å‚™ç¡¬ä»¶å‚³è¼¸æ•¸æ“šçš„基本單ä½ï¼Œè€Œå¡Šï¼ˆblock)是塊è¨å‚™è«‹æ±‚1次Iï¼Oæ“作所涉åŠçš„一組相鄰扇å€ï¼Œæ¯å€‹å¡Šéƒ½éœ€è¦æœ‰è‡ªå·±çš„å…§å˜ç·©æ²–å€ã€‚ç·©æ²–å€é¦–部(buffer_head)是與æ¯å€‹ç·©æ²–å€ç›¸é—œçš„æ•¸æ“šçµæ§‹ï¼Œæ¯æ¬¡å°å¡Šæ²’備的Iï¼Oå‚³è¼¸éƒ½å¿…é ˆç¶“éŽå¡Šçš„ç·©æ²–å€ã€‚
Linux塊沒備驅動程åºé‡‡å–一種延é²Iï¼Oç–略。當進程有Iï¼O請求時,驅動程åºå»¶é²ä¸€æ®µæ™‚間,把塊è¨å‚™ä¸Šç›¸é€£çºŒçš„buffer_headçµæ§‹é—œè¯åœ¨ä¸€èµ·å½¢æˆä¸€å€‹Iï¼O請求æè¿°ç¬¦ï¼ˆstruct requestï¼‰ï¼Œå†æŠŠrequestçµæ§‹æŒ‰ç…§é›»æ¢¯ç®—法排隊到è¨å‚™çš„請求隊列(request_queue_t)。這樣實際執行Iï¼Oå‚³è¼¸æ™‚ï¼Œé †æ¬¡è™•ç†å°æ‡‰å¡Šè¨å‚™çš„請求隊列。
  
å°äºŽrequestçµæ§‹çš„電梯排隊算法,é¿å…ç”±äºŽé »ç¹çš„移動ç£é 而導致塊è¨å‚™æ€§èƒ½ä¸‹é™ï¼›ç„¶è€Œï¼Œç›®å‰åœ¨Linux塊è¨å‚™é©…動程åºä¸ï¼Œå°ä¸€å€‹requestçµæ§‹ä¸çš„å„個buffer_headçµæ§‹åˆ†åˆ¥ç™¼å¸ƒIï¼Oè®€å¯«å‘½ä»¤ï¼Œæœƒå°Žè‡´æ¯æ¬¡å°ä¸€å€‹buffer_head的輸入ï¼è¼¸å‡ºæ™‚,ç£é 都會åœé “一段時間,進行DMAæ•¸æ“šè®€å¯«ã€‚é€™æ¨£é »ç¹çš„ç£é å•Ÿåœæœƒå°Žè‡´ç£ç›¤æ€§èƒ½ä¸‹é™ã€‚
2.2.2 集群讀寫的實ç¾
  
傳統的塊è¨å‚™é©…動程åºä¸æ¯æ¬¡ç™¼å¸ƒè®€å¯«å‘½ä»¤éƒ½åªå°ä¸€å€‹buffer_head緩沖而導致塊è¨å‚™æ€§èƒ½ä¸‹é™ã€‚é‡å°é€™ä¸€å•題,我們å°å‚³çµ±å¡Šè¨å‚™é€²è¡Œæ”¹é€²ï¼Œå¯¦ç¾äº†é›†ç¾¤è®€å¯«ã€‚由于æ¯ä¸€å€‹requestçµæ§‹çš„buffer_headçµæ§‹éˆå°æ‡‰çš„物ç†å¡Šéƒ½æ˜¯ç›¸é„°çš„ï¼Œå› æ¤ç‚ºé€²è¡Œé›†ç¾¤è®€å¯«å‰µé€ 了æ¢ä»¶ã€‚requestçµæ§‹ä¸çš„nr_sectors表示該requestçµæ§‹éœ€è¦è®€å¯«çš„塊數。進行讀寫時,一次性發布讀寫塊數為nr_seetors,讀入塊è¨å‚™å…§å®¹åˆ°requemçµæ§‹æŒ‡å‘的第一個buffer_headçµæ§‹å°æ‡‰çš„å…§å˜å€åŸŸã€‚在一個buffer_headçµæ§‹çš„ç·©æ²–å€è®€å¯«æ»¿äº†ä»¥åŽï¼Œå°±èª¿æ•´è®€å¯«ç·©æ²–å€åœ°å€ç‚ºä¸‹ä¸€å€‹buffer_head所指å‘的緩沖å€ï¼ŒåŒæ™‚é…åˆDMA進行數據傳輸,æé«˜äº†è®€å¯«é€Ÿåº¦ã€‚å°ä¸€å€‹requestçµæ§‹æ“作完æˆä»¥åŽï¼Œé‡‹æ”¾requestçµæ§‹è³‡æºã€‚實ç¾é›†ç¾¤è®€æ“作å½ç¢¼å¦‚下:
  Read_mmc(){
  發布讀寫命令,讀入的數據塊數為一個rcquest一>nr_sectors的塊數;
  緩沖å€çš„æŒ‡é‡æŒ‡å‘第1個bhçµæ§‹æ‰€æŒ‡çš„ç·©æ²–å€ï¼›
  while(數據還沒有讀完){
  讀入數據到buffer_headçµæ§‹æ‰€æŒ‡å®šçš„ç·©æ²–å€ï¼›ï¼ï¼Šèª¿ç”¨Pxa_read_mmc()*ï¼
  調整緩沖å€çš„æŒ‡é‡åˆ°ä¸‹ä¸€å€‹buffer_headçµæ§‹æ‰€æŒ‡å‘的緩沖å€ï¼›
  ï½
  ï½
2.2.3集群讀寫ä¸çš„并發控制
  
如果Iï¼O請求隊列request_queue_tæ˜¯åœ¨å…§æ ¸ä¸çš„許多地方都被訪å•的,則該隊列就æˆç‚ºäº†è‡¨ç•Œè³‡æºã€‚為了å°è©²éšŠåˆ—進行互斥ä¿è·ï¼ŒLinux2.4䏿‰€æœ‰çš„請求隊列都å—一個單ç¨çš„全局自旋鎖io_request_lockçš„ä¿è·ã€‚æ‰€æœ‰å°æ¸…求隊列的æ“ä½œå¿…é ˆè¦æ±‚æ“æœ‰è©²éŽ–å¹¶ç¦æ¢ä¸æ–·ï¼Œç„¶è€Œï¼Œåœ¨é©…å‹•ç¨‹åºæ“æœ‰é€™å€‹éŽ–çš„åŒæ™‚,其他任何讀寫請求ä¸èƒ½æŽ’隊到系統的任何塊è¨å‚™ä¸Šï¼Œå…¶ä»–讀寫處ç†å‡½æ•¸ä¹Ÿä¸èƒ½é‹è¡Œã€‚ç‚ºäº†ç›¡é‡æ¸›è¼•由于驅動程åºé•·æœŸçš„æ“æœ‰è©²éŽ–è€Œå°Žè‡´ç³»çµ±æ€§èƒ½ä¸‹é™çš„å•題,在實ç¾é›†ç¾¤è®€å¯«æ™‚å¿…é ˆéµå¾ªä»¥ä¸‹åŽŸå‰‡ï¼š
  ①å°è«‹æ±‚隊列進行讀寫æ“作時è¦ç²å¾—鎖;
  ②å°è«‹æ±‚隊列æ“作完畢åŽé‡‹æ”¾è«‹æ±‚鎖;
  ③為了減少å 用鎖的時間,å¯å…ˆæŠŠéšŠåˆ—ä¸çš„requestçµæ§‹å¾žéšŠåˆ—ä¸å–ä¸‹ä¾†ï¼Œå†æ‰“開鎖,然åŽåœ¨é–‹éŽ–çš„æƒ…æ³ä¸‹å°å–下的requestçµæ§‹é€²è¡Œæ“作。
  基于以上原則,讀ï¼å¯«è™•ç†å‡½æ•¸çš„å½ç¢¼å¦‚下所示:
  mmc_request_fn()
  whilc(1){
ã€€ã€€åŠ éŽ–io_request_lock;
  讀å–ç•¶å‰mmcå¡è«‹æ±‚éšŠåˆ—çš„ç¬¬ä¸€å€‹è«‹æ±‚çµæ§‹requestï¼›
  釋放鎖io_request_lock;
  if(request為空)
  cxit(O); ï¼ï¼Šæ²’有å¯ä»¥è™•ç†çš„隊列,返回*/
  read_mmc(); /*調用集群讀寫函數*/
ã€€ã€€åŠ éŽ–io_request_lockï¼›
  在queueçµæ§‹ä¸å–處ç†å®Œç•¢çš„requestçµæ§‹ï¼Œé‡‹æ”¾request資æºï¼›
  釋放鎖io_request_lock;
  ï½
  ï½
2.3 守è·ç·šç¨‹
  
在MMCå¡é©…動程åºåˆå§‹åŒ–的時候,啟動守è·ç·šç¨‹mme_block_thread。它平時處于ç¡çœ 狀態,當有å°MMCå¡çš„讀ï¼å¯«è«‹æ±‚時,mmc_blok_thread被喚醒。該線程調用上述讀ï¼å¯«è™•ç†å‡½æ•¸mmc_request_fn(),處ç†å®Œç•¢åŽå†é€²å…¥ç¡çœ 狀態。
2.4 é›»æºç®¡ç†
  
嵌入å¼ç³»çµ±ä¸€èˆ¬æœ‰ä½ŽåŠŸè€—è¦æ±‚,當æŸè¨å‚™é•·æœŸæ²’有é‹è¡Œæ™‚ï¼Œå°±æ‡‰è©²åœæ¢çµ¦è©²è¨å‚™ä¾›é›»ï¼Œä»¥æ¸›å°‘é›»èƒ½æ¶ˆè€—ã€‚åœ¨å…§æ ¸ä¸æœ‰ä¸€å€‹éœ€è¦æ³¨å†Šçš„é›»æºç®¡ç†è¨å‚™çš„隊列pm_listï¼ŒåŒæ™‚也有電æºç®¡ç†ç·šç¨‹kpowered,它的優先級是所有é‹è¡Œé€²ç¨‹ä¸æœ€ä½Žçš„。當系統長時間沒有進程é‹è¡Œæ™‚,kpowered被喚醒,掃æpm_list隊列å„個注冊的è¨å‚™ã€‚如果發ç¾è©²è¨å‚™é•·æœŸæ²’有é‹è¡Œï¼Œå‰‡å‘該è¨å‚™ç™¼å‡ºPM_SUSPEND事件;而當è¨å‚™é‡æ–°é–‹å§‹ä½¿ç”¨æ™‚,則å‘pm_list隊列發出:PM_RESUME事件。
在MMCå¡é©…å‹•æ¨¡å¡Šä¸æ³¨å†Šäº†é›»æºç®¡ç†çš„回調函數mme_block_callback,å³pm_register(PM_UNKNOWN_DEV,0,mme_pm_callback)。這樣MMCå¡å°±æ³¨å†Šåˆ°äº†pm_list隊列ä¸åŽ»äº†ã€‚ç•¶æœ‰é›»æºäº‹ä»¶æ™‚,就觸發mmc_pm_callback函數。該函數處ç†å„種電æºäº‹ä»¶ã€‚
程åºä¸çš„é›»æºäº‹ä»¶æœ‰å…©ç¨®ï¼š
  
â‘ PM_SUSPEND事件。該事件使MMCå¡é€²å…¥çœé›»æ¨¡å¼ã€‚這時驅動程åºä¿å˜MMCå¡çš„ç•¶å‰ç‹€æ…‹å’Œé‡è¦å¯„å˜å™¨çš„內容,如時é˜å¯„å˜å™¨MMC_CLKRT和狀態寄å˜å™¨MMC_STATç‰ã€‚ç„¶åŽï¼Œè¨ç½®MMCå¡çš„供電GPIO為高電平,關閉MMCå¡çš„é›»æºä¾›æ‡‰ï¼Œæ²’ç½®MMCå¡åœ¨æ™‚é˜ä½¿èƒ½å¯„å˜å™¨CKENçš„
相應ä½ç‚ºO,關閉MMCå¡çš„æ™‚é˜è„ˆæ²–。這時,MMCå¡å°±é€²å…¥äº†çœé›»æ¨¡å¼ã€‚
  
â‘¡PM_RESUME事件。該事件使MMCå¡é€²å…¥æ£å¸¸å·¥ä½œæ¨¡å¼ã€‚é€™æ™‚ç¨‹åºæ¢å¾©åœ¨é€²å…¥çœé›»æ¨¡å¼å‰ä¿å˜çš„寄å˜å™¨ï¼Œæ‰“é–‹é›»æºä¾›æ‡‰å’Œæ™‚é˜è„ˆæ²–,MMC塿¢å¾©åˆ°æ£å¸¸çš„工作模å¼ã€‚
  
ç•¶ç„¶é›»æºäº‹ä»¶ä¹Ÿå¯ä»¥ç”±ç”¨æˆ¶é€²ç¨‹è‡ªæ„¿è§¸ç™¼ã€‚在文件系統的接å£file_operaion io_controlä¸ç•™æœ‰é›»æºç†ç®¡ç†æŽ¥å£ï¼Œç”¨æˆ¶å¯ä»¥é€šéŽio_contolå‘å¡ç™¼é€é›»æºäº‹ä»¶è«‹æ±‚。
2.5 ç†±æ’æ‹”管ç†
  
在手機ã€PDAç‰åµŒå…¥å¼ç³»çµ±ä¸ï¼Œéƒ½è¦æ±‚æä¾›å°è¨å‚™çš„峿’å³ç”¨åŠŸèƒ½ï¼Œä½¿ç”¨æˆ¶ç„¡é ˆå®‰è£é©…動程åºå°±å¯ä»¥å³æ™‚使用è¨å‚™ã€‚Linux在系統層和應用層都è¦å°ç†±æ’拔事件進行處ç†ã€‚在系統層,一方é¢è¦æŽ¢æ¸¬MMCå¡çš„ç†±æ’æ‹”äº‹ä»¶ï¼Œåˆ†é…æˆ–釋放系統資æºï¼Œå¹¶é©…å‹•MMCå¡ï¼›å¦ä¸€æ–¹é¢ï¼Œè¦å°‡æ¤äº‹ä»¶æº–ç¢ºåŠæ™‚åœ°é€šçŸ¥çµ¦æ‡‰ç”¨å±¤ï¼Œæ‡‰ç”¨å±¤å‰‡æ ¹æ“šç†±æ’æ‹”事件作相應的處ç†ã€‚
在æ“ä½œç³»çµ±å±¤ï¼Œéœ€è¦æ³¨å†Šä¸€å€‹å—符型è¨å‚™mmc_plug文件,用于應用層探測MMCå¡çš„ç†±æ’æ‹”事什。CPU通éŽGPIO12引腳與MMCå¡ç›¸é€£ï¼Œç”¨äºŽå¡æ’æ‹”çš„ä¸æ–·æŽ¢æ¸¬ã€‚åŒæ™‚驅動程åºå·¾è¨ç½®ä¸€å€‹ä¿¡è™Ÿé‡MMC_EVENT,它å–MMC_INSERTå’ŒMMC_REMOVALå…©å€‹å€¼ã€‚ç•¶å¡æ’å…¥å’Œæˆ–è€…æ‹”å‡ºæ™‚ï¼Œåœ¨ä¸æ–·è™•ç†ç¨‹åºä¸è¢«åˆ†åˆ¥è¨ç½®ç‚ºMMC_INSERTå’ŒMMC_REMCOVALï¼›å¹¶åŒæ™‚傳給å—符è¨å‚™mmc_plug,供上層的應用程åºä½¿ç”¨ã€‚ç‚ºäº†è®“æ‡‰ç”¨å±¤èƒ½å¤ çŸ¥æ›‰å¡çš„æ‹”æ’事件,在å—符è¨å‚™mmc_plug使用異æ¥Iï¼O機制pollï¼Œéœ€è¦æŽ¥æ”¶å…§æ ¸æ‹”æ’事件的進程通éŽpoll在一個ç‰å¾…隊列上ç¡çœ ï¼Œç•¶æœ‰å¡æ‹”æ’äº‹ä»¶æ™‚ç”¢ç”Ÿä¸æ–·ï¼Œä¸æ–·è™•ç†ç¨‹åºå–šé†’在隊列上ç‰å¾…的進程。上層進程在被喚醒åŽå°±è®€å–å—符è¨å‚™ï¼Œç²å–所發生的事件。
在應用層,進程通éŽselect機制監è½MMC塿‰€ç™¼ç”Ÿçš„ç†±æ’æ‹”事件,在沒有拔æ’事件的時候,進程進入阻塞狀態,讓出CPU資æºï¼›ç•¶ç™¼ç”Ÿç†±æ‹”æ’事件時,系統喚醒通éŽpollåŠ å…¥åˆ°ç‰å¾…隊列ä¸çš„é€²ç¨‹ï¼Œç„¶åŽæ‡‰ç”¨å±¤é€šéŽread函數得到MMCå¡çš„ç†±æ’æ‹”事件,進行相應的應用層處ç†ã€‚當然,應用層也å¯ä»¥é€šéŽwrite方法通知系統層å°å¡é€²è¡Œè™•ç†ã€‚
çµèªž
  
æœ¬æ–‡ç ”ç©¶å¯¦ç¾çš„MMCå¡é©…動程åºï¼Œå…¶å¯¦ç¾çš„é›†ç¾¤è®€å¯«è‰æ˜Žæœ‰ç©©å®šè€Œè¼ƒé«˜çš„讀ï¼å¯«é€Ÿåº¦ï¼›å¢žåŠ äº†é›»æºç®¡ç†åŠŸèƒ½ï¼Œé™ä½Žäº†é›»æºçš„功耗,滿足了嵌入å¼ç³»çµ±ä½ŽåŠŸè€—çš„è¦æ±‚ï¼›å¢žåŠ çš„å³æ’å³ç”¨åŠŸèƒ½ï¼Œå¤§å¤§æ–¹ä¾¿äº†ç”¨æˆ¶çš„ä½¿ç”¨ã€‚é©…å‹•ç¨‹åºçš„é«”ç³»çµæ§‹æ˜¯å¯¦ç¾åµŒå…¥å¼ç³»çµ±å¡Šè¨å‚™é©…動的一種好方法。