嵌入式 Linux應用程序如何讀取(修改)芯片寄存器的值


這一問題來自項目中一個實際的需求:
我需要在Linux啟動之后,確認我指定的芯片寄存器是否與我在uboot的配置一致。

舉個例子:
寄存器地址:0x20000010負責對DDR2的時序配置,該寄存器是在uboot中設置,現在我想在Linux運行后,讀出改寄存器的值,再來檢查該寄存器是否與uboot的配置一致。

Linux應用程序運行的是虛擬空間,有沒有什么機制可以是完成我提到的這一需求。若行,還請附些測試代碼。
謝謝!

這個需要用mmap()函數將寄存器物理地址映射為用戶空間的虛擬地址,即將寄存器的那段內存映射到用戶空間,函數介紹如下:

 
         
  1.  
  2.  
  3. void* mmap(void * addr, size_t len, int prot, int flags, int fd, off_t offset);
 

該函數映射文件描述符 fd 指定文件的 [offset, offset + len] 物理內存區至調用進程的 [addr, addr + len] 的用戶空間虛擬內存區,通常用於內存共享或者用戶空間程序控制硬件設備,函數的返回值為最后文件映射到用戶空間的地址,進程可直接操作該地址。下面是測試代碼(僅供參考):

 
         
  1. #define DDR2_REG_BASE (0x20000000)
  2. #define MAP_SIZE 4096UL
  3. #define MAP_MASK (MAP_SIZE - 1)
  4. static unsigned int pTestRegBase;
  5. static int dev_fd;
  6. dev_fd = open("/dev/mem", O_RDWR | O_NDELAY);
  7. if (dev_fd <</SPAN> 0) {
  8. LOGE("open(/dev/mem) failed.");
  9. return;
  10. }
  11. pTestRegBase = (void *)mmap(NULL, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, dev_fd,DDR2_REG_BASE & ~MAP_MASK);
  12. if (MAP_FAILED == pTestRegBase) {
  13. printf("mmap failed. fd(%d), addr(0x%x), size(%d)\n", dev_fd, DDR2_REG_BASE, MAP_SIZE);
  14. else {
  15. unsigned int reg_value = *((volatile unsigned int *)(pTestRegBase + 10));
  16. printf("reg_value = 0xx\n", reg_value);
  17. munmap((void*)pTestRegBase, MAP_SIZE);
  18. }
  19. pTestRegBase = 0;
  20. if(dev_fd)
  21. close(dev_fd);
 

這里將DDR2_REG_BASE開始大小為1個page的物理地址映射到了用戶空間,然后就可以用pTestRegBase作為起始地址操作寄存器了。

 
  • 0 支持
    贊一個!可以看到我的開發板指定位置寄存器的值了。
    追問一下:
    我在我ubuntu主機(intel x86)上使用運行你給代碼,會出現錯誤:
    ajaxhe@bbs:~/program/c$ sudo ./a.out
    mmap failed. fd(3), addr(0x20000000), size(4096)
    但將15行的程序修改為:
    pTestRegBase = (void *)mmap(NULL, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, dev_fd, 0);
    運行時正常,這里問題出再哪里呢?是不是因為0x20000000~0x20000000+4096在ubuntu的機器上沒有地址映射的緣故呢?
  • 0 支持
    @ajaxhe x86架構寄存器地址我不怎么清楚,像arm架構的處理器寄存器一般都是在高端地址如0xF0000000以上,你可以在程序中把errno值打印出來看看是什么原因引起的。

1、首先寫一個內核模塊,在該內核模塊中設置一個變量,用來存儲該寄存器的值。
2、在內核模塊中創建一個對應的proc,用來向用戶空間輸出該寄存器的值。
3、在用戶空間直接cat之前創建的proc文件。

需要以內核模塊的方式運行

暈,不說詳細點,就扣分阿....

寫個內核模塊
使用ioremap()
映射到user地址空間

看看這里的咚咚

asm/io.h

寫個驅動,在驅動里面去讀你的寄存器就可以了。
這里有個實例,你可以下載試試:read_register_kmod.tar(下載地址:http://sdrv.ms/ZM8gFi)。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM