2013-06-05 70 views
3

我試圖從linux內核寫入系統控制寄存器。但結果是分段錯誤:如何從linux內核模塊寫入寄存器(cpu:ARM)

無法在虛擬地址從內核模塊20050004

代碼來處理內核尋呼請求:

#define REGBASE 0x20050000 

void writeRegister(void){ 
    __raw_writel(0x00000002, REGBASE + 0x0004); 
} 

如何訪問片上存儲器,其中系統控制寄存器位於?

+0

可能的重複:[request_mem_region()'做什麼?](http://stackoverflow.com/questions/7682422/what-does-request-mem-region-actually-do-and-when-it-是需要的) –

回答

3

我猜REGBASE是一個物理地址,而不是一個虛擬的。您需要讓內核將其映射到地址空間,然後才能使用它。大多數時候,你會使用ioremap它在映射

例如:

void __iomem *io = ioremap(REGBASE, SZ_4K); 
writel(0x00000002, io + 0x0004); 
+0

正確答案! – JohnnyFromBF

1

我知道這是不是正是你正在尋找的答案,但有一個辦法做到這一點的用戶空間,如果你想避免爲你的應用程序編寫一個內核模塊。

這是在覆盆子PI3 GPIO訪問的示例:

#define RASPBERRY_PI_PERI_BASE 0x3F000000 
#define GPIO_BASE    (RASPBERRY_PI_PERI_BASE + 0x200000) // GPIO controller 

#define BLOCK_SIZE    (4*1024) 

static volatile uint32_t *gpio = NULL; 

int GPIO_init(void) { 
    int fd; 

    if ((fd = open ("/dev/mem", O_RDWR | O_SYNC | O_CLOEXEC)) < 0) return -1; // printf("Failed to open /dev/mem, try checking permissions.\n"); 
    gpio = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_BASE); 
    if ((int32_t)gpio == -1) return -1; // printf("Failed mmap (GPIO): %s\n", strerror (errno)); 

    return 0; 
} 

現在你有一個簡單的指針變量* GPIO鏈接到硬件的內存地址。你做它映射「內存」設備的內存,這是爲你「免費」:-)

問候。