How to read/write an 'address' from a memory location......

Oct 18, 2007 18 Replies

I am trying to read an address from a memory location and then write into that memory location. i.e.



unsigned long * mem_pointer = 0x93700020; //Valid memory location on my hardware unsigned long mem_value = *mem_pointer; //Retrieve the value (another memory location) from //the pointer


The question is - How do i use the value at mem_value as an address? Basically, I want to do something like.


*(unsigned char *)mem_value = 10.


Thanks and warm regards, Rintu



Your question / posting is unclear.

Karthik Balaguru

Please keep your source lines under 72 chars (67 is better) to avoid those silly line wraps. Also avoid the // comment style, which doesn't survive line wraps, and is even illegal in C90 withut extensions.

You have:

unsigned long *mem_pointer =

where is a suitable description of an address in your machine. To access the data at that address just use a *, i.e.:

*mem_pointer = 10; or if (10 == *mem_pointer) /* do something */; or something_else = *mem_pointer.

Note that a cast is not a legal lvalue. I.e:

(unsigned char *) = anything;

The type pointed to is built into the value of mem_pointer (unless that type is 'void').

Chuck F (cbfalconer at maineline dot net) Available for consulting/temporary embedded and systems.

Please don't wrap code examples when you post them.

unsigned long **p1, *p2, v;

p1 = (unsigned long **)0x93700020; p2 = *p1; v = *p2;

or if you prefer a one-liner:

v = **((unsigned long **)0x93700020);

Grant Edwards grante Yow! Hello, GORRY-O!! at I'm a GENIUS from HARVARD!! visi.com

[....]

That should work, assuming that "unsigned long" is the same size as a pointer on your system. But as Grant Edwards points out, it's easier to use the compiler's type system directly, and just cast the address to be a pointer to a pointer, rather than a pointer to an unsigned long (which is another pointer in disguise):

unsigned char **mem_pointer = 0x93700020; foo = **mem_pointer;

or, if you prefer: unsigned char **mem_pointer = 0x93700020; unsigned char *mem_value = *mem_pointer; foo = *mem_value;

Wim Lewis , Seattle, WA, USA. PGP keyID 27F772C1

[...]

Using physical addresses in C code is dirty hack. You should not do that. Also you should never use the nonsense like "unsigned long".

  1. In the linker file, define a section "foobar" at the required location.
  2. Place a variable there: #pragma section "foobar" u32 * mem_pointer;
  3. Use this pointer as any other variable.

Vladimir Vassilevsky DSP and Mixed Signal Consultant

formatting link

Really? I've never heard of anyone doing that. It seems cumbersome; you could end up with hundreds of sections in the object file. And you each definition appears twice.

gcc lets you define variables in the linker script

PROVIDE( PORT0 = 0xE0020000);

Then you can reference it with

extern volatile unsigned long PORT0;

I don't quite see the advantage over the usual

#define PORT0 (*(volatile unsigned long *)(0xE0020000))

Except.... aha! It should appear nicely in the debugger! Must try this now! :)

John Devereux

That's even less portable than the OPs "hack".

Grant Edwards grante Yow! I'm dressing up in at an ill-fitting IVY-LEAGUE visi.com SUIT!! Too late...

I agree. Allocating a separate section for each location you want to "hard-wire" is overly complex and fragile.

In my experience, the former method using PROT0 = 0xE0020000 will be visible to the debugger, the latter might or might not.

Grant Edwards grante Yow! Now I am depressed ... at visi.com

Which "that" --- the one you read the address from, or the one the address specifies?

An address kept in a variable is called a pointer, in C programs. So mem_value should be of a pointer type, rather than an integer. Consequentially, mem_pointer should be a pointer-to-pointer-to-something type, e.g.

some_type **mem_pointer = ...; some_type *mem_value = *mem_pointer; some_type the_actual_thing = *mem_value;

And what's keeping you from doing exactly that?

But this all hides a probably more important question: why do you think you should be doing this?

My problem is: I have two processors exchanging data over a shared section of memory. Now before processor 1 can write the data for processor 2 (in the shared memory), processor 1 needs to tell processor 2 where exactly it will be writing. Thats where i was coming from - processor 1 basically needs to write an "address" into a predefined location for processor 2 and that "address" will hold the actual data for processor 2.

Thanks a lot for all your clarifications. I should try some of them now!

Warm regards, Rintu

... snip ...

That is outside the abilities of the C language, which has no intrinsic knowledge of multiple processes and managing them. However, if your description is adequate, the following might work:

Global (common memory): int running = 1; Type *ptr = NULL;

Sender code fragment: do { /* prepare data */ while (ptr && running) continue; if (running) { ptr = malloc(sizeof *ptr); *ptr = data; } } while (running)'

Receiver code fragment: do { while (!ptr && running) continue; if (running) { rcvdata = *ptr; free(*ptr); ptr = NULL; /* process rcvdata */ } } while (running);

Note that either process can shut down the interaction by setting running to zero. Sender has a local variable named data, and receiver has one named rcvdata. The processes are in strict sync, i.e. one item of data causes one item to be transmitted, and nothing more is done until that item is received. Similarly the receiver can do nothing while waiting for new data to be prepared.

Note that malloc failing in sender is a fatal error. The initialization values ensure that the sender runs first. The definition of 'Type' controls the amount of data transferred. The 'continue' statements can be changed into function calls to do other things.

Chuck F (cbfalconer at maineline dot net) Available for consulting/temporary embedded and systems.

. . .

Ah, the pleasures of using dual-port RAM. You need to have a good handle on the use of semaphores so that the data is not overwritten before the second processor has read it.

John B

No. It only needs to do that as it *finishes* writing there. Allowing the reader to find out you've started writing, before you're finished doing it, will cause nasty race conditions.

No. You rather probably shouldn't be using addresses for that part of the communication --- not even in "quotes". Use indices into a shared array of bytes instead. The difference being that the two processors don't have to agree on where in their respective address space that shared memory actually is. Pointers are pretty much *always* the wrong thing to export from any program to the outside world (or another program, for that matter).

The algorithm of exchanging data once the addresses are known to both processors is pretty much done. The way to communicate the address is where I was kind of stuck. I just tested one of the ways described here and it seems to work!

Thanks again!

Regards, Rintu

By the way, there is no concept of semaphores between two processors right? What I can think of is a flag shared between the two processors by means of shared RAM or a messaging unit.

So now you have a program that *seems to work.

mac the naïf

Sure there is.

A flag + a couple atomic operations == semaphore.

Grant Edwards grante Yow! People humiliating at a salami! visi.com

I have no idea what this refers to - you have omitted the quotation portion. However, if you are referring to my earlier answer, the state of 'ptr' functions as a data_ready flag. It is not a good process for simultaneous action.

Chuck F (cbfalconer at maineline dot net) Available for consulting/temporary embedded and systems.

Join the Discussion

Have something to add? Share your thoughts — no account required.

Didn't find your answer?

Ask the community — no account required