<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          Linux SDIO總線驅(qū)動

          作者: 時間:2016-12-15 來源:網(wǎng)絡(luò) 收藏

          CMD53命令:

          CMD52每次只能讀寫一個字節(jié),因?yàn)橛辛薈MD53對讀寫進(jìn)行了擴(kuò)展,CMD53允許每次讀寫多個字節(jié)或者多個塊(BLOCK)。CMD53的命令格式如下:

          第一位是1,為開始位,然后是一位方向位,總是1,代表方向?yàn)镠OST向DEVICE設(shè)備傳送,其后6位為命令號,這里是110101b,用十進(jìn)制表示為53,CMD53的名字也由此而來。

          然后是1位的讀寫標(biāo)志。接著是3位功能號,這個同CMD52都是相同的。BlockMode如果1代表是塊傳輸模式,否則為字節(jié)傳輸模式。

          OP Code為操作位,如果是0,代表數(shù)據(jù)往固定的位置讀寫,如果1代表是地質(zhì)增量讀寫。例如,對地址0固定讀寫16個字節(jié),相當(dāng)于16次讀寫的地址0,而對地址0增量讀寫16個字節(jié),相當(dāng)于讀寫0~15地址的數(shù)據(jù)。

          然后是17位的地址寄存器,可以尋址到128K字節(jié)的地址,然后是9位的讀寫的計(jì)數(shù),對于字節(jié)讀取,讀寫大小就是這個計(jì)數(shù),而對于塊讀寫,讀寫的大小是計(jì)數(shù)乘以塊的大小。

          隨后的7位為CRC校驗(yàn)碼。最后一位為1。

          當(dāng)讀寫操作是塊操作的時候,塊的大小是可以通過設(shè)置FBR中的相關(guān)寄存器來設(shè)置。

          同CMD52命令不同的是,CMD53沒有返回的命令的,這里判斷是否DEVICE設(shè)備讀寫完畢是需要驅(qū)動里面自己判斷的,一般有2個方法,1.設(shè)置相應(yīng)的讀寫完畢中斷。如果DEVICE設(shè)備讀寫完畢,則對HOST設(shè)備發(fā)送中斷。2.HOST設(shè)備主動查詢DEVICE設(shè)備是否讀寫完畢,可以通過CMD命令是否有返回來判斷是否DEVICE是否讀寫完畢。

          驅(qū)動:

          以SDIO為例其會采用mmc_attach_sdio來實(shí)現(xiàn)驅(qū)動和設(shè)備的匹配,其本質(zhì)還是根據(jù)sdio_bus的匹配規(guī)則來實(shí)現(xiàn)匹配。在mmc_attach_sdio中首先是mmc匹配一個bus,即采用何種bus來進(jìn)行mmc bus來處理host。在這里需要理解一點(diǎn)就是在SDIO中,對于SD卡存儲器mmc為實(shí)體設(shè)備,而對于非SD卡存儲器,如SDIO接口的設(shè)備,則mmc則表征為bus,這個比較重要。除了mmc bus外還存在SDIO_BUS。

          int mmc_attach_sdio(struct mmc_host *host,u32 ocr)

          {

          interr;

          inti, funcs;

          structmmc_card *card;

          mmc_attach_bus(host,&mmc_sdio_ops); --host匹配一條mmc bus

          card= mmc_alloc_card(host, NULL); --申請一個card實(shí)體,類似于總線設(shè)備。

          card->type= MMC_TYPE_SDIO;

          card->sdio_funcs= funcs;

          host->card= card;

          for(i = 0;i < funcs;i++) {

          sdio_init_func(host->card,i + 1);

          }

          mmc_release_host(host);

          mmc_add_card(host->card);

          for(i = 0;i < funcs;i++) {

          sdio_add_func(host->card->sdio_func[i]);

          }

          return0;

          }

          比較難以理解的是func,這個東東其實(shí)是一個實(shí)體設(shè)備的封裝,可以認(rèn)為其是一個設(shè)備。

          struct sdio_func *sdio_alloc_func(structmmc_card *card)

          {

          structsdio_func *func;

          func= kzalloc(sizeof(struct sdio_func), GFP_KERNEL);

          func->card= card;

          device_initialize(&func->dev);

          func->dev.parent= &card->dev; --很明顯card設(shè)備為sdio設(shè)備的父設(shè)備。

          func->dev.bus= &sdio_bus_type;

          func->dev.release= sdio_release_func;

          returnfunc;

          }

          上面的code一目了然,其就是具體設(shè)備實(shí)體的封裝,其bus類型為sdio_bus. sdio_init_func僅僅是初始化一個設(shè)備,而并沒有register。在sdio_add_func實(shí)現(xiàn)設(shè)備的register,同理就是card實(shí)體,在mmc_add_card之前并沒有注冊,在mmc_add_card函數(shù)中才實(shí)現(xiàn)設(shè)備的注冊。

          到此設(shè)備注冊也就完成了,其實(shí)sdio總線在形式上類似于usb bus,為什么呢?編寫過usb驅(qū)動的童鞋們應(yīng)該知道,編寫usb驅(qū)動僅僅是編寫驅(qū)動的加載,并沒有具體加載設(shè)備實(shí)體,導(dǎo)致很多童鞋的困惑,為什么沒有設(shè)備的加載,其實(shí)在usb設(shè)備插入時,會動態(tài)的創(chuàng)建一個usb設(shè)備實(shí)體,在usb設(shè)備實(shí)體創(chuàng)建完成后,根據(jù)不同設(shè)備id調(diào)用相匹配的驅(qū)動。而SDIO設(shè)備設(shè)備也是一樣的。上面的code比較混亂,總是讓人看不出具體的設(shè)備的加載。其實(shí)在上面的code中,其中包括了mmc host的驅(qū)動。



          關(guān)鍵詞: LinuxSDIO總線驅(qū)

          評論


          技術(shù)專區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();