问题
I am working on rasberry pi board. Is it possible to directly access the GPIO physical address from linux kernel space using inb(), outb()... ?. If yes how ?.
GPIO register address link Page 90 http://www.raspberrypi.org/wp-content/uploads/2012/02/BCM2835-ARM-Peripherals.pdf
Thank you
回答1:
Yes.
- Get a virtual address mapping setup to the registers in question using
ioremap
- Use
readl/writel
to manipulate the physical memory.
Beware that ARM processors will fault on unaligned accesses. Linux handles this gracefully, but with a performance penalty.
Tiny example:
void __iomem *regs = ioremap(0xdead0000, 4);
pr_info("0xdead0000: %#x\n", readl(regs));
iounmap(regs);
回答2:
Allocation of I/O memory is not the only required step before that memory may be accessed. You must also ensure that this I/O memory has been made accessible to the kernel. So a mapping must be set up first. This is the role of the ioremap function.
void *ioremap(unsigned long phys_addr, unsigned long size);
void *ioremap_nocache(unsigned long phys_addr, unsigned long size);
void iounmap(void * addr);
The function is designed specifically to assign virtual addresses to I/O memory regions.
The proper way of getting at I/O memory is via a set of functions (defined via ) provided for that purpose.
To read from I/O memory, use one of the following:
unsigned int ioread8(void *addr);
unsigned int ioread16(void *addr);
unsigned int ioread32(void *addr);
Here, addr should be an address obtained from ioremap and the return value is what was read from the given I/O memory.
There is a similar set of functions for writing to I/O memory:
void iowrite8(u8 value, void *addr);
void iowrite16(u16 value, void *addr);
void iowrite32(u32 value, void *addr);
As an example:
void __iomem *io = ioremap(PHYSICAL_ADDRESS, SZ_4K);
iowrite32(value, io);
On the other hand, you can do it in user space on this way:
static volatile uint32_t *gpio = NULL;
int fd;
if ((fd = open ("/dev/mem", O_RDWR | O_SYNC | O_CLOEXEC) ) < 0) return -1;
gpio = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_BASE);
if ((int32_t)gpio == -1) return -1;
*(gpio + n) = value;
来源:https://stackoverflow.com/questions/22529039/how-to-acess-the-physical-address-from-linux-kernel-space