Variable like object at specific address

  • Thread starter Glenn Møller-Holst
  • Start date
G

Glenn Møller-Holst

Hi!

Is it possible to transform these macro definitions to a c++/c
"variable" at specific address? It is going to be used on an ARM-processor:

#define IOPIN0 (*((volatile unsigned long *) 0xE0028000))
#define IOSET0 (*((volatile unsigned long *) 0xE0028004))
#define IODIR0 (*((volatile unsigned long *) 0xE0028008))
#define IOCLR0 (*((volatile unsigned long *) 0xE002800C))

to some native C++, C? So it is possible to write:

unsigned long iopin0 /*some declaration defining iopin0 at the address
0xE0028000*/;

Applications:

iodir0 |= 0x00400000;
iopin0 = 0x00400000;
/*some instruction write sequence*/;

iodir0 &= (~0x00400000);
/*some instruction read sequence*/;
x= iopin0; // read pin.

-

The purpose is to be able to send the variable (eg. io) as a
const-parameter:


typedef struct io_iog_t { // iog: io-group.
volatile unsigned int pin; // 32 bit.
volatile unsigned int set;
volatile unsigned int dir;
volatile unsigned int clr;
} io_iog_t;

typedef struct iopin_t { // iopin: io-consecutive pin group.
unsigned char pingroup; // 8 bits.
unsigned char firstpinselected; // 8 bits.
unsigned int consecutivepinselection; // 32 bits.
} iopin_t;

struct io_iog_t iog[3] /* start address 0xE0028000 */;
const struct iopin_t io= { // Will normally be passed
pingroup= 0, // to a class or function as const.
firstpinselected= 5,
consecutivepinselection= 0x01 };

Applications:
iog[io.pingroup].dir &= (~(consecutivepinselection<<io.firstpinselected));
/*some instruction read sequence*/;
x= ((iog[io.pingroup].pin)>>io.firstpinselected)&io.consecutivepinselection;

iog[io.pingroup].dir |= (consecutivepinselection<<io.firstpinselected);
iog[io.pingroup].pin = (1<<io.firstpinselected);
/*some instruction write sequence*/;

regards,

Glenn
 
I

Ivan Vecerina

: Is it possible to transform these macro definitions to a c++/c
: "variable" at specific address? It is going to be used on an
ARM-processor:
:
: #define IOPIN0 (*((volatile unsigned long *) 0xE0028000))
: #define IOSET0 (*((volatile unsigned long *) 0xE0028004))
: #define IODIR0 (*((volatile unsigned long *) 0xE0028008))
: #define IOCLR0 (*((volatile unsigned long *) 0xE002800C))
:
: to some native C++, C? So it is possible to write:
:
: unsigned long iopin0 /*some declaration defining iopin0 at the address
: 0xE0028000*/;

There are some compiler-specific extensions that allow you to do so.
You could also try writing:
volatile unsigned long& iopin0 = *((volatile unsigned
long*)0xE0028000);
This can work as well with a struct / other variable type.

This said, in this type of context, I often prefer to focus on a
slightly higer-level level of encapsulation. (sometimes a
vendor-provided
header exists with such #define-s, and you want to avoid rewriting
them).
As long as these #define-s are well-encapsulated in a single file
(e.g. a module providing functions for sending/reading complete
messages), I would not worry too much about getting rid of them.


Regards -Ivan
 
E

Erik Wikström

Hi!

Is it possible to transform these macro definitions to a c++/c
"variable" at specific address? It is going to be used on an ARM-processor:

#define IOPIN0 (*((volatile unsigned long *) 0xE0028000))
#define IOSET0 (*((volatile unsigned long *) 0xE0028004))
#define IODIR0 (*((volatile unsigned long *) 0xE0028008))
#define IOCLR0 (*((volatile unsigned long *) 0xE002800C))

to some native C++, C? So it is possible to write:

Since it seems like you are working quite close to the hardware I
suppose that you are quite familiar with pointers, so why not treat it
as one (since it is one)? You might want to create a typedef if you are
going to pass it around a lot.

unsigned long * const IoPin0 = (unsigned long*)0x00400000;



Or you could create a wrapper class, and overload common operations,
such as =, |=, etc., but that might require more effort than it is worth.
 
G

Glenn Møller-Holst

Hi!

I am still having some problems declaring an array:

static const int grpidxfirst= 0;
static const int grpidxlast= 3;

// Works:
volatile unsigned long& iopin1 = *((volatile unsigned long*)0xE0028010);

// Array declaration do not work - can it be made ok?:
volatile io_iog_t & io[3] = *((io_iog_t*)0xE0028000);

// This array declaration do not work either - can it be made ok?:
volatile int & io[15] = *((int*)0xE0028000);

It would be useful to be able to use that kind of array.

regards,

Glenn

-

Declaration of io_iog_t:
 
P

Paul Brettschneider

Glenn said:
Hi!

I am still having some problems declaring an array:

static const int grpidxfirst= 0;
static const int grpidxlast= 3;

// Works:
volatile unsigned long& iopin1 = *((volatile unsigned long*)0xE0028010);

// Array declaration do not work - can it be made ok?:
volatile io_iog_t & io[3] = *((io_iog_t*)0xE0028000);

// This array declaration do not work either - can it be made ok?:
volatile int & io[15] = *((int*)0xE0028000);

It would be useful to be able to use that kind of array.

Why don't you declare it as a pointer? You can then access it like an array:

struct io_iog_t {
volatile unsigned int pin;
volatile unsigned int set;
volatile unsigned int dir;
volatile unsigned int clr;
};

io_iog_t * const io = (io_iog_t*)0xE0028000;

int f()
{
io[0].set = 5;
return io[3].clr;
}

Gives the following code with g++4.2 -O3 -fomit-frame-pointer:
_Z1fv:
..LFB2:
movl $5, -536707068
movl -536707012, %eax
ret

Just as you wanted?

Also note that in C++ you can lose the typedef and you probably shouldn't
use "unsigned int" and "unsigned char" but the (C99?) uint32_t and uint8_t
data types. You might also have to tell the compiler to not do any packing,
but this is highly compiler specific AFAIK.

HTH.
 
P

Paul Brettschneider

Paul said:
Glenn said:
Hi!

I am still having some problems declaring an array:

static const int grpidxfirst= 0;
static const int grpidxlast= 3;

// Works:
volatile unsigned long& iopin1 = *((volatile unsigned long*)0xE0028010);

// Array declaration do not work - can it be made ok?:
volatile io_iog_t & io[3] = *((io_iog_t*)0xE0028000);

// This array declaration do not work either - can it be made ok?:
volatile int & io[15] = *((int*)0xE0028000);

It would be useful to be able to use that kind of array.

Why don't you declare it as a pointer? You can then access it like an
array:

struct io_iog_t {
volatile unsigned int pin;
volatile unsigned int set;
volatile unsigned int dir;
volatile unsigned int clr;
};

io_iog_t * const io = (io_iog_t*)0xE0028000;

int f()
{
io[0].set = 5;
return io[3].clr;
}

Gives the following code with g++4.2 -O3 -fomit-frame-pointer:
_Z1fv:
.LFB2:
movl $5, -536707068
movl -536707012, %eax
ret

Just as you wanted?

Also note that in C++ you can lose the typedef and you probably shouldn't
use "unsigned int" and "unsigned char" but the (C99?) uint32_t and uint8_t
data types. You might also have to tell the compiler to not do any
packing, but this is highly compiler specific AFAIK.

padding not packing. As always too fast on the "send" button. :(
 
G

Glenn Møller-Holst

Paul Brettschneider wrote:
....
Why don't you declare it as a pointer? You can then access it like an array:

struct io_iog_t {
volatile unsigned int pin;
volatile unsigned int set;
volatile unsigned int dir;
volatile unsigned int clr;
};

io_iog_t * const io = (io_iog_t*)0xE0028000;

int f()
{
io[0].set = 5;
return io[3].clr;
}

Gives the following code with g++4.2 -O3 -fomit-frame-pointer:
_Z1fv:
.LFB2:
movl $5, -536707068
movl -536707012, %eax
ret

Just as you wanted?

Also note that in C++ you can lose the typedef and you probably shouldn't
use "unsigned int" and "unsigned char" but the (C99?) uint32_t and uint8_t
data types. You might also have to tell the compiler to not do any packing,
but this is highly compiler specific AFAIK.

HTH.

Hi Paul

It nearly worked in the GCC compiler:

typedef struct iog_t { // Digital io-consecutive pin group.
volatile tu32 pin;
volatile tu32 set;
volatile tu32 dir;
volatile tu32 clr;
} iog_t;

static const int grpidxfirst= 0;
static const int grpidxlast= 3;

iog_t* const io = (iog_t*)0xE0028000;
....
tu32 x= io[0].pin;
85: io[0].dir=1;

Compiler result:

pin.hpp:85: error: expected constructor, destructor, or type conversion
before '.' token

regards,

Glenn
 
G

Glenn Møller-Holst

Glenn said:
Paul Brettschneider wrote:
...
Why don't you declare it as a pointer? You can then access it like an
array:

struct io_iog_t {
volatile unsigned int pin;
volatile unsigned int set;
volatile unsigned int dir;
volatile unsigned int clr;
};

io_iog_t * const io = (io_iog_t*)0xE0028000;

int f()
{
io[0].set = 5;
return io[3].clr;
}

Gives the following code with g++4.2 -O3 -fomit-frame-pointer:
_Z1fv:
.LFB2:
movl $5, -536707068
movl -536707012, %eax
ret

Just as you wanted?

Also note that in C++ you can lose the typedef and you probably shouldn't
use "unsigned int" and "unsigned char" but the (C99?) uint32_t and
uint8_t
data types. You might also have to tell the compiler to not do any
packing,
but this is highly compiler specific AFAIK.

HTH.

Hi Paul

It nearly worked in the GCC compiler:

typedef struct iog_t { // Digital io-consecutive pin group.
volatile tu32 pin;
volatile tu32 set;
volatile tu32 dir;
volatile tu32 clr;
} iog_t;

static const int grpidxfirst= 0;
static const int grpidxlast= 3;

iog_t* const io = (iog_t*)0xE0028000;
...
tu32 x= io[0].pin;
85: io[0].dir=1;

Compiler result:

pin.hpp:85: error: expected constructor, destructor, or type conversion
before '.' token

regards,

Glenn

The Compiler is:

#arm-elf-gcc -dumpversion
4.2.0
#arm-elf-gcc -dumpmachine
arm-elf

regards,

Glenn
 
P

Paul Brettschneider

Hi,
Paul Brettschneider wrote:
...
Why don't you declare it as a pointer? You can then access it like an
array:

struct io_iog_t {
volatile unsigned int pin;
volatile unsigned int set;
volatile unsigned int dir;
volatile unsigned int clr;
};

io_iog_t * const io = (io_iog_t*)0xE0028000;

int f()
{
io[0].set = 5;
return io[3].clr;
}

Gives the following code with g++4.2 -O3 -fomit-frame-pointer:
_Z1fv:
.LFB2:
movl $5, -536707068
movl -536707012, %eax
ret

Just as you wanted?

Also note that in C++ you can lose the typedef and you probably shouldn't
use "unsigned int" and "unsigned char" but the (C99?) uint32_t and
uint8_t data types. You might also have to tell the compiler to not do
any packing, but this is highly compiler specific AFAIK.

HTH.

Hi Paul

It nearly worked in the GCC compiler:

typedef struct iog_t { // Digital io-consecutive pin group.
volatile tu32 pin;
volatile tu32 set;
volatile tu32 dir;
volatile tu32 clr;
} iog_t;

static const int grpidxfirst= 0;
static const int grpidxlast= 3;

iog_t* const io = (iog_t*)0xE0028000;
...
tu32 x= io[0].pin;
85: io[0].dir=1;

Compiler result:

pin.hpp:85: error: expected constructor, destructor, or type conversion
before '.' token

Are you doing this *inside* a function? Because there it definitely works
for me. May I suggest you post a minimal but complete example which
produces this error? Maybe I misunderstand what you're trying to achieve...

Here is an example that compiles for me (btw, I'm absolutely not sure about
the use of volatile, it might very well not be enough):

#include <inttypes.h>

struct io_iog_t {
volatile uint32_t pin;
volatile uint32_t set;
volatile uint32_t dir;
volatile uint32_t clr;
};

io_iog_t * const io = (io_iog_t*)0xE0028000;

int f()
{
io[0].set = 5;
io[0].dir = 1;
return io[3].clr;
}
 
G

Glenn Møller-Holst

Paul Brettschneider wrote:
....
Are you doing this *inside* a function? Because there it definitely works
for me. May I suggest you post a minimal but complete example which
produces this error? Maybe I misunderstand what you're trying to achieve...

Here is an example that compiles for me (btw, I'm absolutely not sure about
the use of volatile, it might very well not be enough):
....

Hi Paul

Thank for your help. I just did a silly mistake. It works now.

kind regards,

Glenn
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,901
Latest member
Noble71S45

Latest Threads

Top