基于Linux的現場總線無線通信卡的實現
無線分散控制站中無線通信卡軟件開發基于Linux操作系統。由于Linux系統基于802.11b協議的無線驅動已經很成熟了,而基于Linux操作系統的協議棧軟件移植也比較容易。因此,選擇Linux系統會有效的提高無線通信卡的開發周期。
基于Linux的無線通信卡與有線的通信卡在協議棧和功能塊方面大致相同,僅需將應用程序向Linux系統上移植即可。但由于采用了Linux系統在與IO模塊控制卡通信的實現上就相對比較復雜了。與IO模塊控制卡通信的程序流程圖如下圖3-2所示:
圖3-2 與IO模塊控制卡通信的程序流程圖
3.3軟件實現中關鍵性問題的解決
在Linux操作系統下對于中斷及其它系統資源的操作有特定的規范,如內核模式操作和用戶模式操作具有不同操作權限,內核空間與用戶空間也不能隨意互訪。導致如協議棧無法直接對雙端口RAM進行讀寫,也無法直接向I/O模塊控制卡收發中斷,在Linux系統下,只有在內核模式下才可以做到。那么,怎么樣將數據寫入到雙端口RAM中,然后發送中斷信號通知對方及如何響應對方的中斷并從雙端口RAM中讀數是軟件實現中的關鍵性問題。
3.3.1發中斷與注冊中斷處理程序的實現
由于發中斷與注冊中斷處理程序是對硬件直接操作,在Linux系統下用戶程序無法直接對其硬件進行操作。因此,必須編寫相應的內核模塊,在內核模塊中完成發中斷與注冊中斷處理程序的操作。在用戶程序中動態加載相應內核模塊來達到用戶程序發中斷與注冊中斷處理程序的效果。其注冊中斷處理程序的內核模塊關鍵性代碼如下:
int init_module(void) //中斷注冊模塊初始化
{ …… /* 初始化設置 */
AT91_SYS->AIC_SMR[25]|=0X20; //設置中斷下跳沿觸發
if (request_irq(n, interrupt_program, INTERRUPT, IRQ1,NULL))
// 請求分配中斷號為n的快速中斷處理
// interrupt_program為指向處理這個中斷的中斷處理程序的指針
{ ……/*沒有申請成功 根據返回值進行出錯處理 * / }
else
{ printk(1> 注冊中斷成功 ! n);
return 0;}
init_waitqueue_head(my_queue);
}
void cleanup_module(void)
{ …… /* 釋放資源 */
free_irq(n,NULL); //釋放中斷線n
}
在用戶程序中發中斷時,通過調用system(send_riq)來動態執行內核模塊程序來控制發送中斷的管腳的信號,從而實現在用戶程序發中斷的效果。其發中斷的內核模塊關鍵性代碼如下:
AT91_SYS->PIOC_PER |= AT91C_PIO_PC15;//設置PC15IO使能
AT91_SYS->PIOC_OER |= AT91C_PIO_PC15;//設置PC15輸出使能
//發送一個方波中斷信號
AT91_SYS->PIOC_CODR |= AT91C_PIO_PC15;
for(i=1;i
AT91_SYS->PIOC_SODR |= AT91C_PIO_PC15;
3.3.2雙端口RAM驅動的實現
由于用戶程序不能直接對雙端口RAM進行讀寫,因此必須根據用戶程序的需要編寫雙端口RAM的驅動,以內核模塊的形式動態加載到系統中去。Linux系統將所有設備都看做是文件,對設備的讀寫相當于對文件的讀寫。雙端口RAM驅動模塊加載后,用戶程序就可以像讀寫文件一樣,間接的對雙端口RAM進行讀寫了。其雙端口RAM驅動模塊的主要實現過程如下:
static int write_dpram(struct file *file, const char *buf, u32 count, loff_t *f_pos)
{ …… /* 寫初始化 */
copy_from_user(wMessage,buf,count);
…… /* 進行數據處理 */
for (i=0;i
{ writeb(wMessage[i], base+wadd);
wadd++; }
…… /*向IO模塊控制卡發中斷信號*/
}
static int read_dpram(struct file *file,char *buf,u32 count,loff_t *f_pos)
{ …… /*讀函數則調用相應的readb( )和copy_to_user( )函數,與寫函數同理*/}
static int open_dpram(struct inode *inode,struct file *file )
{ …… /*初始化*/
if (!request_mem_region(AT91_DPRAM,BUF_LEN*sizeof(u8),DEVICE_NAME))
{ …… /*未申請到該內存空間時進行相應處理*/} //申請使用內存空間
base =ioremap(AT91_DPRAM,BUF_LEN*sizeof(u8));//為設備內存區域分配虛擬地址
…… /* 設置DPRAM讀寫時序*/
}
static int release_dpram(struct inode *inode,struct file *file )
{ …… /* 釋放相應資iounmap( )和release_mem_region();}
以上為DPRAM設備驅動的打開、讀寫、關閉函數的實現,然后通過以下標記化結構將其驅動的功能映射到前面的具體實現函數上:
static struct file_operations test_fops = {
read:read_dpram,
write:write_dpram,
open: open_dpram,
release:release_dpram
};
linux操作系統文章專題:linux操作系統詳解(linux不再難懂)
評論