sven
sven

Reputation: 1121

hexadecimal array in C

I am trying to learn expansion header configuration of a processor on this instruction http://41j.com/blog/2011/09/beagleboard-gpio-input-driverless/

I have a part that I could not understand

volatile ulong *pinconf;
pinconf = (ulong*) mmap(NULL, 0x10000, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0x48000000);
pinconf[0x2168/4] = 0x001C001C;

Can anyone explain how does the pinconf array works? what value does it store?

Edit: What I really could not understand what does pinconf[0x2168/4] mean. is it an hexadecimal array and what value does it refer to?

Upvotes: 1

Views: 291

Answers (4)

Mike
Mike

Reputation: 49523

Based on the title of your question, I think you’re confused about the hex notation in accessing the array.

hex is just another way of writing numbers, don't let it throw you too much. I could write:

int a = 0xA;

or

int a = 10;

And they mean the same thing. So in this case:

pinconf[0x2168/4] = 0x001C001C;

Is just:

pinconf[8552/4] = 1835036;

The latter is actually more confusing because pinconf is storing an address which are typically written in hex using 4 (or 8) bytes, hence the 00 proceeding the rest of the number (1C001C)

Upvotes: 2

new299
new299

Reputation: 814

I'm the original blog/code author, here's what I meant:

To answer your main point, pinconf[0x2168/4] refers to the address 0x48002168. The pinconf array starts at the address 0x48000000. It's been defined as a ulong [1], which on ARM processors is 4 bytes. I know I want to access the address pinconf+0x2168. To convert the address 0x2168 into an index in pinconf I need to divide by 4.


Walking through the code from the start:

volatile ulong *pinconf;

pinconf is defined as a ulong (32bit int) pointer. It's defined as volatile, this means that something outside of our code may change its value. It tells the compiler that every time we use that value we need to read it from memory, this stops the compiler doing clever optimisations that may screw things up.

pinconf = (ulong*) mmap(NULL, 0x10000, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0x48000000);

This sets pinconf to point to the address 0x48000000. Normally you could do something like:

pinconf = (ulong*) 0x48000000;

To make pinconf point to an address, but this won't work. 0x48000000 is a protected address, it's only accessible by the kernel. The mmap magic gives you a way to access the address from userspace.

pinconf[0x2168/4] = 0x001C001C;

We've covered this already, but this is writing a value to the address: 0x48000000+0x2168. The value 0x48002168 comes from the OMAP3 datasheets, and is used to do memory mapped IO with the GPIO system. We divide by 4 to convert the address 0x2168 to an index in pinconf.

[1] I should probably have used a uint32_t to be honest.

Upvotes: 2

Joe
Joe

Reputation: 7818

pinconf is a memory mapped file/device. Looking at your linked code, fd is a descriptor for the newly opened /dev/mem. So whatever you write into the pinconf array is actually writing direct to /dev/mem at whatever offset you use in the array. I'm assuming this is how this code is "talking" to the GPIO hardware. Without the memory map for the GPIO device it's hard to know what happens at the addresses that are being written to.

See what /dev/mem is.

And read up about memory mapped i/o, which is what this is doing (sort of), see: http://www.kernel.org/doc/htmldocs/uio-howto.html#userspace_driver

Upvotes: 2

Burkhard
Burkhard

Reputation: 14738

The pinconf array stores ulong (unsigned long).

With volatile ulong *pinconf; you define a pointer to a ulong. It points to the first element of the array. It is volatile, meaning it may be changed by an outside "event" and won't be cached. It workes linke any array in C.

In this case, it is mapped to a file/device with a file descriptor fd.

Upvotes: 1

Related Questions