2013-06-05 71 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链接到硬件的内存地址。你做它映射“内存”设备的内存,这是为你“免费”:-)

问候。