XMEGA related pointer issues (GCC & IAR)

Go To Last Post
45 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi all,
XMEGA sram starts from 0x2000. I have tested GCC an IAR codes as follows:

GCC:

#include 
void main(void)
{
 unsigned char *ptr,i; 
 for(i=0;i<100;i++)
 *ptr++=0x55;
 while(1); 
} 

IAR:

#include"ioavr.h"
void main()
{ 
 unsigned char *ptr,i;  
 for(i=0;i<100;i++)
 *ptr++=0x55;
 while(1);
}

Debugging of both codes in AVRStudio simulator shows, wrong placement of data in non-sram areas(0x022C for GCC and 0x0000 for IAR).
Adding these lines modifies problem in IAR,

unsigned char x;
ptr=&x;

but corrupts GCC action entirely.

Ozhan KD
Knowledge is POWER

Last Edited: Sun. Jan 30, 2011 - 01:15 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Maybe I'm missing something, but this is what I see:

In the original code, you are not initializing ptr. By definition (according to K&R) uninitialized local variables are guaranteed to start off as garbage.

When you added code, you initialized ptr to point to the bottom of the stack. The subsequent code would wipe out the stack.

What are you trying to do? If you want to write to RAM starting at 0x2000, initialize ptr to 0x2000.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The problem is why compiler assigns a wrong memory location(outside SRAM)
when using pointers?

Ozhan KD
Knowledge is POWER

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You are using a pointer. The pointer's value is interpreted as an address. It is not the compiler's job to assign values to your variables. You assign a value to i ("i=0") but you don't assign a value to ptr. Global objects get initialized to zero, but local/automatic/stack objects don't get initialized.

A good compiler should warn you when you use an uninitialized variable. I'm guessing GCC would give a warning.

The line:
*ptr = 0x55
tells the compiler, which then tells the computer, put the value 0x55 in some memory location. You explicitly state the value to be stored (0x55), but you don't explicitly state where to store it.

Instead, you are telling the computer that the address where you want it stored is inself stored in the variable called ptr. So the computer has to fetch the value of ptr, maybe put that in an address register, and then store the number 0x55.

If your program doesn't set the value of ptr, it could be anything, so the 0x55 would be stored anywhere.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for your answer. But it would be more better if this "anywhere" be in an existed memory area.
Why the second form does not work in GCC(it works in IAR):

#include 
void main(void)
{ 
 unsigned char *ptr,x,i; 
 ptr=&x;
 for(i=0;i<100;i++)
 *ptr++=0x55;
 while(1); 
}  

Ozhan KD
Knowledge is POWER

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Your code isn't used just for accessing SRAM. It is also used to access the memory mapped registers that exist below the SRAM. Your code is nonsense and the results are nonsense, that makes sense to me.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

steve17 wrote:
memory mapped registers that exist below the SRAM.

If you mean R0-R31,this is not correct for XMEGA family. 0x0000 is not the address of R0 in SRAM(Below SRAM is EEPROM space).In addition,the assembly code in debugger shows that for(;;)does not execute in any way.

Ozhan KD
Knowledge is POWER

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You are flogging a dead horse, Ozhan. "Null pointers" have been a topic of discussion in C for --well -- forever. It is not the purpose of C to protect the programmer from himself. That is part of the rationale.

Automatic variables, pointer or not, have no defined initial value. It can have any random value, depending on what happens to occur before it is used.

If you make your pointer a global, it >>will<< have an initial value--as a null pointer. Still won't "work"; still doesn't point to a valid memory location probably.

Note that this has nothing to do with Xmega.

If you want more hand-holding, lint your programs, or switch to Pascal or Ada. Better yet, use e.g. VisualBASIC where there are no pointers.

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

If you mean R0-R31,this is not correct for XMEGA family. 0x0000 is not the address of R0 in SRAM(Below SRAM is EEPROM space).

Well, yeah--look at your Xmega "Data Memory Map". All addresses are allocated first to I/O, then EEPROM, then internal SRAM, and then external memory. So your protestation has a very hollow ring.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

1) Read a good book on C ( get some pointers on pointers ) because you obviously don't know enough about ptrs to use them.

2) Your last posted code, puts the pointer and x on the STACK !! A ptr must HAVE a permanent address itself and it must HOLD a valid address, not from the stack !

This will work as a local or global declaration:

static unsigned char *ptr,x;

1) Studio 4.18 build 716 (SP3)
2) WinAvr 20100110
3) PN, all on Doze XP... For Now
A) Avr Dragon ver. 1
B) Avr MKII ISP, 2009 model
C) MKII JTAGICE ver. 1

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

A ptr must HAVE a permanent address itself and it must HOLD a valid address, not from the stack !

Ummm--there is no "must" there. I use local pointers all the time.

// **************************************************************************
// *
// *		M E M E C P Y
// *
// **************************************************************************
void						memecpy			(	unsigned char eeprom *eptr,
												void *dptr,
												unsigned int howmany)
{
unsigned int	count;
unsigned char * sptr;

    sptr = dptr;

	for (count = 0; count < howmany; count++)
		{
		*eptr++ = *sptr++;
		}

	return;
}

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

indianajones11 wrote:
A ptr must HAVE a permanent address itself
Bullshit.
Quote:
and it must HOLD a valid address, not from the stack !

Bullshit.

Do what you preach and read a good book on C.

Stealing Proteus doesn't make you an engineer.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

How come his last posted code doesn't work ?

1) Studio 4.18 build 716 (SP3)
2) WinAvr 20100110
3) PN, all on Doze XP... For Now
A) Avr Dragon ver. 1
B) Avr MKII ISP, 2009 model
C) MKII JTAGICE ver. 1

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Good. I thought I had a monopoly on this thread.

Now I have other people to lambaste. :)

Lee, thanks. You are right about the peripheral addresses being below SRAM, of course.

So it pains me no end to point out that a pointer containing zero is valid. ;) At least it can be useful. If you de-reference a "null" pointer, you will find yourself accessing the location at address zero. On an Xmega that is general purpose register 0, A.K.A GPIO0. Hmmm. An uppercase letter o bears a strong resemblance to the numeral 0.

However if you make the pointer const and set its value to zero, GCC won't let you de-reference it. It says a NULL pointer can't be de-referenced. So whether you can use it or not depends on which is smarter, you or the compiler. :)

I look at a null pointer like the null char, which of course also has the value zero. Of course if your code is looking for a null char, it will find it. But the so-called NULL char is still a valid char and can appear in an array of chars, as long as it's not a "null terminated string".

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

One more thought about the OP's code.

unsigned char x;
ptr=&x;

This is not only good code, but it is the way to find the bottom of the stack. Assuming x is the last object put on the stack. If you are concerned about the stack colliding with the heap (or the data put at the bottom of RAM by the linker), this address is useful.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks all.
By tracing the code in AVRStudio simulator, 0x55 is written to 0X2FFB-0x2FFF and then pointer goes beyond 0x2FFF. ATXMEGA64A3 is the target chip and 0x2FFF is the end of internal SRAM. So only 5 bytes are written in SRAM and then the code fails. I also tried:

#include 
void main(void)
{ 
 unsigned char *ptr,x,i; 
 ptr=&x;
 for(i=0;i<100;i++)
 *ptr--=0x55; 
 while(1); 
} 

and the result was worse.0x55 is written in 0x2FFB,0x2FFA and then 0x55F9.

Ozhan KD
Knowledge is POWER

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

WTH... why you STILL jackin' off to the same tired beat ??! Ain't 'cha gonna try my declaration ? ANYTHING but the same code people keep tellin' you WON'T WORK.

1) Studio 4.18 build 716 (SP3)
2) WinAvr 20100110
3) PN, all on Doze XP... For Now
A) Avr Dragon ver. 1
B) Avr MKII ISP, 2009 model
C) MKII JTAGICE ver. 1

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

indianajones11 wrote:
WTH... why you STILL jackin' off to the same tired beat ??! Ain't 'cha gonna try my declaration ? ANYTHING but the same code people keep tellin' you WON'T WORK.

Your suggestion works:

#include 
void main(void)
{  
 static unsigned char *ptr,x;
 unsigned char i; 
 ptr=&x;
 for(i=0;i<100;i++)
 *ptr++=0x55; 
 while(1); 
} 

And also:

#include 
unsigned char *ptr,x;
void main(void)
{  
 unsigned char i; 
 ptr=&x;
 for(i=0;i<100;i++)
 *ptr++=0x55; 
 while(1); 
} 

As automatic variables, this also works:

#include 
void main(void)
{  
 unsigned char *ptr,x[100],i; 
 ptr=&x;
 for(i=0;i<100;i++)
 *ptr++=0x55; 
 while(1); 
} 

Ozhan KD
Knowledge is POWER

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Electronic.designer, I apologize for judging you so QUICKLY about ptrs (interacting online makes it easy enough to do so ).

1) Studio 4.18 build 716 (SP3)
2) WinAvr 20100110
3) PN, all on Doze XP... For Now
A) Avr Dragon ver. 1
B) Avr MKII ISP, 2009 model
C) MKII JTAGICE ver. 1

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

indianajones11 wrote:
Electronic.designer, I apologize for judging you so QUICKLY about ptrs (interacting online makes it easy enough to do so ).

That's OK my friend.

Ozhan KD
Knowledge is POWER

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This structure is defined in AVR1308 with a pointer to function, as a member:

typedef struct TWI_Slave {
	TWI_t *interface;
	void (*Process_Data) (void);
	register8_t receivedData[TWIS_RECEIVE_BUFFER_SIZE];
	register8_t sendData[TWIS_SEND_BUFFER_SIZE];
	register8_t bytesReceived;
	register8_t bytesSent;
	register8_t status;
	register8_t result;
	bool abort;
} TWI_Slave_t;
void TWIC_SlaveProcessData(void)
{
	uint8_t bufIndex = twiSlave.bytesReceived;
	twiSlave.sendData[bufIndex] = (~twiSlave.receivedData[bufIndex]);
}

This function uses the pointer:

void TWI_SlaveInitializeDriver(TWI_Slave_t *twi,
                               TWI_t *module,
                               void (*processDataFunction) (void))
{
	twi->interface = module;
	twi->Process_Data = processDataFunction;
	twi->bytesReceived = 0;
	twi->bytesSent = 0;
	twi->status = TWIS_STATUS_READY;
	twi->result = TWIS_RESULT_UNKNOWN;
	twi->abort = false;
}

The code invokes the function as follow:

TWI_SlaveInitializeDriver(&twiSlave, &TWIC, TWIC_SlaveProcessData);

But the Question is why code does not use & operator:

TWI_SlaveInitializeDriver(&twiSlave, &TWIC, &TWIC_SlaveProcessData);

Ozhan KD
Knowledge is POWER

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I guess the compiler assumes you want to take the address of the function, and does it for you. It seems like a bad idea to me, and I'm not sure all compilers will do that.

Of course you can't pass the function as an argument, so that leaves two possibilities. You either wanted to take the address of the function, or call the function, and the compilers guess the former. Maybe the compilers consider the function prototype when doing so.

There is another peculiarity concerning pointers to functions. If you call a function by using a pointer to the function, you don't have to de-reference the pointer. The compiler will do it for you.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I tested both cases in IAR and AVRStudio simulator and both seem to be the same.

15:        TWI_SlaveInitializeDriver(&twiSlave, &TWIC, &TWIC_SlaveProcessData);
+000001D8:   EC49        LDI       R20,0xC9       Load immediate
+000001D9:   E051        LDI       R21,0x01       Load immediate
+000001DA:   E820        LDI       R18,0x80       Load immediate
+000001DB:   E034        LDI       R19,0x04       Load immediate
+000001DC:   E40C        LDI       R16,0x4C       Load immediate
+000001DD:   E210        LDI       R17,0x20       Load immediate
+000001DE:   940E023D    CALL      0x0000023D     Call subroutine
15:        TWI_SlaveInitializeDriver(&twiSlave, &TWIC, TWIC_SlaveProcessData);
+000001D8:   EC49        LDI       R20,0xC9       Load immediate
+000001D9:   E051        LDI       R21,0x01       Load immediate
+000001DA:   E820        LDI       R18,0x80       Load immediate
+000001DB:   E034        LDI       R19,0x04       Load immediate
+000001DC:   E40C        LDI       R16,0x4C       Load immediate
+000001DD:   E210        LDI       R17,0x20       Load immediate
+000001DE:   940E023D    CALL      0x0000023D     Call subroutine

Ozhan KD
Knowledge is POWER

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
But the Question is why code does not use & operator:
Because the name of a function is its address.

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Koshchi wrote:
Because the name of a function is its address.

Good hint.

Ozhan KD
Knowledge is POWER

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

electronic.designer wrote:
Koshchi wrote:
Because the name of a function is its address.

Good hint.
What do you mean by hint?
According to the C standard the name of a function is literally its address. A function name isn't like other objects. Since functions have prototypes the compiler is able to tell the difference and act accordingly.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

In one of my first attempts at programming in C (late 1980s?), I made the classical mistake for someone coming from pascal. I tried to call a (parameter-less) function thus:

foo;

I debugged this for hours, and had to seek help from a C-enlightened friend who mocked me for an evening after he pointed to the obvious. So, one thing I will never forget is that you don't need to be use the address-of operator (&) explicitly to get the address of a function.

As of lately, I have actually found some amusement in reading snippets of the C standard (remember my and MBedders type promotion slip? :wink:). I tried to locate something in the standard that is explicit about "the name of a function is it's address". The closest I came is

Quote:
A function designator is an expression that has function type. Except when it is the
operand of the sizeof operator54) or the unary & operator, a function designator with
type ‘‘function returning type’’ is converted to an expression that has type ‘‘pointer to
function returning type’’.

("C99", ISO/IEC 9899:TC2, §6.3.2.1, item 4). Is that what you a referring to, atomicdog?

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

A function name isn't like other objects.

Really? I see the fact that the name of an array is also a pointer to its first element as something remarkably similar. The name of a function is a pointer to the first opcode of the function. Quite close?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It all seems goofy to me but function names seem goofier than array names.

The following 2 lines produce the same result.

Function_ptr = Function_name;
Function_ptr = &Function_name;

But the following 2 lines do not.

char_ptr = char_array_name;
char_ptr = &char_array_name;

By the way, the following 2 lines produce the same result.

Function_ptr();
(*Function_ptr)();

I don't know what the corresponding array pointer weirdness is, and I don't want to know.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

By the way, the following 2 lines produce the same result

I've often wondered why anyone would use the second syntax there - but I guess it's to let the reader know that the symbol is a function pointer and not just a "normal" function name.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
Quote:

By the way, the following 2 lines produce the same result

I've often wondered why anyone would use the second syntax there -
Now we know why you have problems with pointers and I don't. ;)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

JohanEkdahl wrote:
... Is that what you a referring to, atomicdog?
In chapter 6.6 Constant expressions...
Quote:
9
An address constant is a null pointer, a pointer to an lvalue designating an object of static
storage duration, or a pointer to a function designator; it shall be created explicitly using
the unary & operator or an integer constant cast to pointer type, or implicitly by the use of
an expression of array or function type.
The array-subscript [] and member-access .
and -> operators, the address & and indirection * unary operators, and pointer casts may
be used in the creation of an address constant, but the value of an object shall not be
accessed by use of these operators.

Also K&R's 'The C Programming language' in chapter 5.12 talks about it.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you, John!

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
The name of a function is a pointer to the first opcode of the function.

Isn't the first opcode in flash? If the pointer points to flash, what about function variables?

Ozhan KD
Knowledge is POWER

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

what about function variables?

Please clarify "function variables". Are you referring to a variable of type "pointer to function", or are you referring to something else e.g. a local variable in a function?

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Isn't the first opcode in flash? If the pointer points to flash, what about function variables?

In the Harvard world of AVRs then of course a function pointer is a code flash, not SRAM (or EEPROM or fuse or lock) address.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

JohanEkdahl wrote:

Please clarify "function variables". Are you referring to a variable of type "pointer to function", or are you referring to something else e.g. a local variable in a function?

How can define a pointer which points to local variables in a function (can be accessed from outside the function)?

And another question:
If a structure contains members in different memories(SRAM,Flash,Eeprom),how the pointer to structure can point to different types of memories?

Ozhan KD
Knowledge is POWER

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

How can define a pointer which points to local variables in a function (can be accessed from outside the function)?

Make the local var(s) "static"

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

Make the local var(s) "static"

Where should define the pointer to these static variables?

Quote:
And another question:

Ozhan KD
Knowledge is POWER

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

There's various ways to do this. Here's one:

uint8_t * readA(void) {
  static uint8_t valA;

  valA = PINA;

  return &valA;
}

int main(void) {
  uint8_t * ptr_to_valA;

  ptr_to_valA = readA();
  if (*ptr_to_valA = 0x37) ...
}

Another might be:

void readA(uint8_t * ptr) {
  static uint8_t valA;

  valA = PINA;

  ptr = &valA;
}

int main(void) {
  uint8_t * ptr_to_valA;

  readA(ptr_to_valA);
  if (*ptr_to_valA = 0x37) ...
}

there's loads of other ways you could do it too. But ultimately why not just make 'valA' global?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you Cliff for your answer. According to my question about pointer to structure with different located members, I did a test in IAR and flash or eeprom located arrays are not accepted in a structure.

Ozhan KD
Knowledge is POWER

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

I did a test in IAR and flash or eeprom located arrays are not accepted in a structure

Eh?

Show what you tried. Did you mean the struct contains a pointer to EEPROM/flash or something else?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

Show what you tried.

This code:

struct{
  __flash unsigned char a;
  unsigned char b;
} strct;

and this:

struct{
  __flash unsigned char* a;
  unsigned char b;
} strct;

generates error.

Error[Pa004]: illegal declaration

This is also the case for __eeprom variables.

Ozhan KD
Knowledge is POWER

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well you couldn't have a flash based element in the middle of a RAM based struct. But you should be able to put a "pointer to flash". What happens with:

struct{ 
  unsigned char* __flash a; 
  unsigned char b; 
} strct; 

(for things like this you will find the cdecl command useful - if you don't have a system that can run this you can use it online at http://www.lemoda.net/c/cdecl/ (I just did)).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
What happens with:

struct{ 
  unsigned char* __flash a; 
  unsigned char b; 
} strct; 

This code still generates error, even by commenting "unsigned char b".

EDIT: This works fine.

struct{
  unsigned char __flash *a;
  unsigned char b;
} strct;

Ozhan KD
Knowledge is POWER