Search code examples
androideclipseandroid-ndkcpu-registerscortex-a

R/W register outside application address space with Android Native C++


I'll start at the end.

My final goal is to build a C/C++ library with Android NDK which would allow me to directly access registers in the Freescale i.MX 6Solo processor so that I could implement methods which would control hardware GPIO, SPI, I2C and PWM from Java. Once I'd build and compile the methods in a native library, they would be provided to Android programmers for the remainder of the project. My background is primarily in C/C++ micro-controller development but I'm quickly getting oriented in Java as well.

My question:

I have successfully written and compiled the native C++ code and managed to call it from Java. The test program also runs on the target processor, but when I call the native method which would write directly to the desired CPU register the system hangs and I get the error in LogCat:

Fatal signal 11 (SIGSEGV) at 0x20E015C (code=1), thread 3699 (xamp le.nativecall)

Signal 11 and the Segmentation fault (SIGSEGV) mean that my application is trying to access memory outside it's adress space which is exactly what I'm trying to do, namely to write into the register 0x020E015C.

So my question follows: How can I successfuly write into registers outside of the application address space?

What have I tried so far:

I found a promising description of a situation where there's a virtual adress space involved on this site under "Variable Base Addresses", but I'm having some trouble understanding and implementing the solution he proposes. For the record, the line in which I attempt to modify the register is:

*(volatile uint32_t *)GPIO4_16MUX = 0x00000005;

Where I've previously defined GPIO4_16MUX to be 0x20E015C.

Software and Hardware:

Android ADK and Eclipse, building for Android 4.3 with NDK rc10, RIoT Board with Cortex-A9 i.MX 6Solo.


Solution

  • In normal, protected memory linux environments like Android, one process can't arbitrarily access absolute memory addresses. Keep in mind that you only see a virtual memory address space within your application anyway - the mappings are set up by the kernel. Even if the address 0x20E015C would happen to be readable/writeable within your process, it doesn't mean that it maps to 0x20E015C on the hardware level (it most probably wouldn't).

    You'd either need to modify your kernel to map this memory specifically to your process (or all processes), or more practically, create a kernel driver which exposes the registers as a unix char/block device. Then you can manage the permissions for accessing the device via the normal unix permissions, and any user level process with access to the device can control it.