Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to write register from linux kernel module (cpu: ARM)

Tags:

linux

memory

arm

I trying to write into system control register from linux kernel. But result is segmentation fault:

Unable to handle kernel paging request at virtual address 20050004

Code from kernel module:

#define REGBASE 0x20050000

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

How to access on-chip memory where system control registers located?

like image 223
HardRock Avatar asked Jun 05 '13 08:06

HardRock


Video Answer


2 Answers

I'm guessing that REGBASE is a physical address and not a virtual one. You need to ask the kernel to map it into the address space before you can use it. Most of the time you'd use ioremap to map it in.

For example:

void __iomem *io = ioremap(REGBASE, SZ_4K);
writel(0x00000002, io + 0x0004);
like image 156
tangrs Avatar answered Sep 24 '22 20:09

tangrs


I know that is not exactly the answer you are looking for, but there is a way to do it in user space, if you want to avoid to program a kernel module for your application.

This is an example for GPIO access in Raspberry Pi3:

#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;
}

Now you have a simply pointer variable *gpio that links to the hardware's memory address. You do it mapping "mem" device on memory, that exists for you "for free" :-)

Regards.

like image 32
omotto Avatar answered Sep 23 '22 20:09

omotto