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

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設計應用 > 嵌入式uClinux下的CAN總線設備驅(qū)動程序設計

          嵌入式uClinux下的CAN總線設備驅(qū)動程序設計

          作者: 時間:2013-03-30 來源:網(wǎng)絡 收藏

          1、操作系統(tǒng)概述

            是Linux2.0的一個分支,它被設計用于沒有MMU的微控制器領域,即被廣泛應用于嵌入式Linux領域。的最大特征就是沒有MMU(內(nèi)存管理單元模塊)。它很適合那些沒有MMU的處理器,如ARM7TDMI,m68ez328等。

            uClinux具有完全的TCP/IP協(xié)議棧,同時對其他許多的網(wǎng)絡協(xié)議都提供支持。這些網(wǎng)絡協(xié)議都在uClinux上得到了很好的實現(xiàn)。uClinux可以稱作是一個針對嵌入式系統(tǒng)的優(yōu)秀網(wǎng)絡操作系統(tǒng)。

          2、Linux驅(qū)動程序設計概述

            Linux系統(tǒng)內(nèi)核通過程序與外圍設備交互,程序是Linux內(nèi)核的一部分,它是一組數(shù)據(jù)結(jié)構(gòu)和函數(shù),這些數(shù)據(jù)結(jié)構(gòu)和函數(shù)通過定義的接口控制一個或多個設備。

            和UNIX一樣,Linux中所有的設備均作為文件來對待,這些文件一般稱為特殊文件,這樣做的一個好處是使用戶或應用程序可按操縱普通文件的方式進行訪問控制硬件設備。

            Linux內(nèi)核有三種類型的程序:字符設備驅(qū)動程序、塊設備驅(qū)動程序和網(wǎng)絡設備驅(qū)動程序。Linux的設備由一個主設備號(major)和一個次設備號(minor)標識。主設備號唯一標識了設備類型,它是塊設備表或字符設備表中設備表的索引。次設備號僅由設備驅(qū)動程序解釋,用于識別同類設備中,I/O請求所涉及到的那個設備。設備驅(qū)動程序可以分為3個主要組成部分:

           ?。╨)自動配置和初始化子程序,負責檢測所要驅(qū)動的硬件設備是否能正常工作。

           ?。?)服務于I/O請求的子程序,又稱為驅(qū)動程序的上半部分。

           ?。?)中斷服務子程序,又稱為驅(qū)動程序的下半部分。

          3、uClinux下CAN設備的驅(qū)動程序編寫

            根據(jù)上文對LINUX下設備驅(qū)動程序的描述,以及參考相關(guān)的實例分析,下面對CAN總線設備SJA1000的驅(qū)動程序進行編寫。

            CAN設備驅(qū)動程序?qū)嶋H上是linux內(nèi)核直接對sja1000器件的初始化與讀寫操作。經(jīng)分析,sja1000 CAN驅(qū)動程序構(gòu)成包括如下幾個部分:

            1)定義sja1000芯片內(nèi)所有寄存器的訪問地址,用于完成對其內(nèi)部寄存器以及緩沖區(qū)的讀寫訪問。例如:

            #define IO_PMOD (*(volatile unsigned *)0x3ff5000)

            #define IO_PDATA (*(volatile unsigned *)0x3ff5008)

            #define IO_PCON (*(volatile unsigned *)0x3ff5004)

            #define SJA_MOD (0x2700000) #define SJA_CMR (0x2700004)

            …………………

            #define SJA_CANRXB7 (0x270006c) #define SJA_CANRXB8 (0x2700070)

            因為在我們的系統(tǒng)中,對sja1000的讀寫是采用的部分模擬時序的方式,所以用到了S3C4510的IO端口。下面對sja1000地址的定義進行分析。因為uClinux運行的時候,采用的是32位方式,即兩個相鄰地址間相隔4個字節(jié),而在sja1000內(nèi)部的地址間的間隔只有1個字節(jié)。雖然可以對S3C4510的內(nèi)部寄存器定義為在訪問sja1000的時候,將位寬度定義為8位,但這樣會與linux系統(tǒng)運行不匹配,經(jīng)測試發(fā)現(xiàn)讀寫不正常。所以將sja1000的地址定義為32位寬度。于是各個寄存器地址為(基址+sja1000內(nèi)部地址×4)。這里將sja1000的基址定義為0x2700000。

          2)編寫對SJA1000內(nèi)部寄存器訪問的讀寫函數(shù)

            因為處理器的地址和數(shù)據(jù)總線是分開的,而SJA1000的地址與數(shù)據(jù)總線是8位分時復用的。所以我們只有采用先向sja1000的8位地址數(shù)據(jù)總線上送出地址,然后再送數(shù)據(jù)或者讀數(shù)據(jù)的方式。片選信號/CS,讀信號/RD,寫信號/WR仍由自己產(chǎn)生。需要模擬的是鎖存信號ALE、地址數(shù)據(jù)總線AD0-AD7。參照sja1000時序圖,具體的操作步驟見下面程序和注釋。

          寫子程序如下:

            void sja_write(unsigned int data, unsigned int addr)

            { unsigned char tmp;

            tmp=(addr)>>2;//將32位地址右移2位,tmp的低8位即為sja1000實際地址。

            outl(tmp,addr);//將地址信息作為數(shù)據(jù)送往SJA1000數(shù)據(jù)總線

            IO_PDATA=0x32;//ALE=0,讓SJA1000將該地址鎖存

            outl(data,addr);//將數(shù)據(jù)信息送往SJA1000數(shù)據(jù)總線

            O_PDATA=0x33; } //將ALE置高電平,74HC245的/OE置高位

          讀子程序如下:

            unsigned char sja_read(unsigned int addr)

            { unsigned char data;

            volatile unsigned int data1;

            unsigned char tmp;

            tmp=(addr)>>2; //將32位地址右移2位,tmp的低8位即為sja1000實際地址S3C2410

            outl(tmp,addr); //將地址信息作為數(shù)據(jù)送往SJA1000數(shù)據(jù)總線

            IO_PDATA=0x32; //p0-ALE=0,鎖存地址信息

            IO_PDATA=0x12; //p5-245dir=0,將74HC245的方向置為CPU輸入方向

            data1=inl(addr); //讀出所需的數(shù)據(jù)

            IO_PDATA=0x33; //ALE置高,74HC245置為不工作狀態(tài)

            data=data1; return(data); }//返回數(shù)據(jù)

            后面對sja1000的初始化、CAN發(fā)送與CAN接收函數(shù)中需要對寄存器操作均調(diào)用sja_write()和sja_read()函數(shù)進行。


          上一頁 1 2 下一頁

          評論


          相關(guān)推薦

          技術(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); })();