For users of the Atmel AT91SAM7 and AT91SAM9 ARM CPU chips. Atmel has taken a new direction by combining on chip flash and ram with the ARM CPU on a single die. This provides low cost devices for small systems using the ARM CPU.
This group is to exchange information to help users get started and learn how to use the devices.
AT91SAM7S USB Woes - Ralph Hempel - Jan 27 11:18:57 2008
Some time back, I was looking for some help with the
Atmel USB Framework 1.02 Core ad CDC application under
gcc 4.1
In my project (pbLua for LEGO MINDSTORMS NXT) I am
having issues with the Atmel Framework either
dropping characters or overwriting its receive
buffers occasionally - just enough to make it
a nuisance.
I can shoot characters out the USB port of the NXT
to my host PC (running Windows XP or 2000) all day and
not drop a character.
Reading the characters from the PC and simply echoing
what I get back shows some issues with dropped characters
and mangled buffers, but it only happens intermittently.
If I configure my host app to wiat 1 msec between characters
then I get no dropped characters, but unusable throughput...
I have read LOTS of posts on the AT91 site and have
tried all the fixes I have read about, but none of
them seem to help.
Does anyone have any definitive summary of what must
be changed in the framework to make it work, besides
the GET/SET Enpoint macros...?
Or does anyone have an interrupt driven USB framework
they would be willing to share for this project?
Cheers, Ralph

(You need to be a member of AT91SAM -- send a blank email to AT91SAM-subscribe@yahoogroups.com )
Re: AT91SAM7S USB Woes - Robert Adsett - Jan 31 12:36:13 2008
At 11:18 AM 1/31/2008 -0500, Ralph Hempel wrote:
>Ralph Hempel wrote:
> > Some time back, I was looking for some help with the
> > Atmel USB Framework 1.02 Core ad CDC application under
> > gcc 4.2
>
>I finally! tracked down the problem to some overzealous
>optimization by gcc.
>
>With -O1 the USB Framework works fine
>With -O2 or -Os there is a problem
>
>I think it's in UDP_Read() and what's happening is that
>the interrupt enable on the endpoint is ocurring before
>the endpoint parameters are getting set up.
>
>Looking at the source, I can definitely see that the order
>in the listing is OK, but when I look at the resulting
>assembler code, it seems as if it's been moved up to just
>after the point where pInterface gets set...
Would the interrupt enable be in inline asm?
Robert
http://www.aeolusdevelopment.com/
From the Divided by a Common Language File (Edited to protect the guilty)
ME - "I'd like to get Price and delivery for connector Part # XXXXX"
Dist./Rep - "$X.XX Lead time 37 days"
ME - "Anything we can do about lead time? 37 days seems a bit high."
Dist./Rep - "that is the lead time given because our stock is live.... we
currently have stock."

(You need to be a member of AT91SAM -- send a blank email to AT91SAM-subscribe@yahoogroups.com )
Re: AT91SAM7S USB Woes - Eric Pasquier - Jan 31 13:30:20 2008
Dear Ralph,
Hum. I am not sure that solving realtime problem with optimization option is a good
practice.
I don't know the details of your code, but there is certainly another solution.
Eric.
----- Original Message -----
From: Ralph Hempel
To: A...@yahoogroups.com
Sent: Thursday, January 31, 2008 5:18 PM
Subject: Re: [AT91SAM] AT91SAM7S USB Woes
Ralph Hempel wrote:
> Some time back, I was looking for some help with the
> Atmel USB Framework 1.02 Core ad CDC application under
> gcc 4.2
I finally! tracked down the problem to some overzealous
optimization by gcc.
With -O1 the USB Framework works fine
With -O2 or -Os there is a problem
I think it's in UDP_Read() and what's happening is that
the interrupt enable on the endpoint is ocurring before
the endpoint parameters are getting set up.
Looking at the source, I can definitely see that the order
in the listing is OK, but when I look at the resulting
assembler code, it seems as if it's been moved up to just
after the point where pInterface gets set...
I hope that this helps somebody that's having trouble.
Now I just have to modify my build system to allow for
optimizing some modules and not others. On the other
hand the difference between -O1 and -O2 is only about 10%
so it might be more trouble than it's worth!
Cheers, Ralph

(You need to be a member of AT91SAM -- send a blank email to AT91SAM-subscribe@yahoogroups.com )
Re: AT91SAM7S USB Woes - Ralph Hempel - Jan 31 14:26:04 2008
> Ralph
> Check out GCC's "memory barrier". I believe it is something like
>
> #define barrier() __asm__ __volatile__ ("":::"memory")
>
> Place it between the accesses to the register. It will cause GCC to not
> optimize code by moving it across the barrier.
Bill,
I'll do that, but it begs the question, what else has gcc optimized
to the point where it does not work correctly?
At this point, I'll take the 10% code hit knowing that it works
correctly.
I've been at this game long enough to know that all compilers
have bugs in the corners somewhere. Normally they manifest themselves
in obvious ways - this one has been producing nagging little
errors for almost a year now.
No matter how often you look at and inspect the source code, having
the compiler silently move code around is unsettling...
Ralph

(You need to be a member of AT91SAM -- send a blank email to AT91SAM-subscribe@yahoogroups.com )
Re: AT91SAM7S USB Woes - Ralph Hempel - Jan 31 14:37:20 2008
Eric Pasquier wrote:
> Dear Ralph,
>
> Hum. I am not sure that solving realtime problem with optimization
> option is a good practice.
> I don't know the details of your code, but there is certainly another
> solution.
I'm solving it by _removing_ optimization. Embedded systems often
suffer from being sensitive to the order of operations.
In this case the optimization appears to have enabled an interrupt
before the set up of the data structure required by the interrupt
handler was complete.
I'm all for finding the root cause of the problem. I solved it WITH
the optimization by adding code around the interrupt enable that FORCED
it to happen at the right time, and all was OK after that.
Ralph

(You need to be a member of AT91SAM -- send a blank email to AT91SAM-subscribe@yahoogroups.com )
Re: AT91SAM7S USB Woes - Robert Adsett - Jan 31 15:41:09 2008
At 01:35 PM 1/31/2008 -0500, Ralph Hempel wrote:
>Robert Adsett wrote:
> > At 11:18 AM 1/31/2008 -0500, Ralph Hempel wrote:
> >> Ralph Hempel wrote:
> >>> Some time back, I was looking for some help with the
> >>> Atmel USB Framework 1.02 Core ad CDC application under
> >>> gcc 4.2
> >> I finally! tracked down the problem to some overzealous
> >> optimization by gcc.
>
> > Would the interrupt enable be in inline asm?
>
>SET(pInterface->UDP_IER, 1 << bEndpoint);
>
>Which evaluates to:
>
>register = register | flags
>
>It's a read only register, but it returns all 0s
Write only maybe?
>The UDP_IER is defined as a AT91_REG which is in turn
>typedef'd as a volatile unsigned int...
What about the other operations? Are they also on volatile types? The
compiler is allowed to change the order on non-volatile data types but the
order and number of accesses of volatile types must be maintained.
Robert
"C is known as a language that gives you enough rope to shoot yourself in
the foot." -- David Brown in comp.arch.embedded
http://www.aeolusdevelopment.com/

(You need to be a member of AT91SAM -- send a blank email to AT91SAM-subscribe@yahoogroups.com )
Re: AT91SAM7S USB Woes - Bill Knight - Jan 31 15:47:59 2008
Ralph Hempel wrote:
> Robert Adsett wrote:
>> At 11:18 AM 1/31/2008 -0500, Ralph Hempel wrote:
>>> Ralph Hempel wrote:
>>>> Some time back, I was looking for some help with the
>>>> Atmel USB Framework 1.02 Core ad CDC application under
>>>> gcc 4.2
>>> I finally! tracked down the problem to some overzealous
>>> optimization by gcc.
>
>> Would the interrupt enable be in inline asm?
>
> SET(pInterface->UDP_IER, 1 << bEndpoint);
>
> Which evaluates to:
>
> register = register | flags
>
> It's a read only register, but it returns all 0s
>
> The UDP_IER is defined as a AT91_REG which is in turn
> typedef'd as a volatile unsigned int...
>
> Ralph
Ralph
Check out GCC's "memory barrier". I believe it is something like
#define barrier() __asm__ __volatile__ ("":::"memory")
Place it between the accesses to the register. It will cause GCC to not
optimize code by moving it across the barrier.
Regards
-Bill Knight
R O SoftWare
PS - This post is from memory and a quick web search. Please test
throughly.

(You need to be a member of AT91SAM -- send a blank email to AT91SAM-subscribe@yahoogroups.com )
Re: AT91SAM7S USB Woes - Ralph Hempel - Jan 31 17:25:26 2008
Robert Adsett wrote:
>> It's a read only register, but it returns all 0s
>
> Write only maybe?
Yes, write only - I was a bit excited when I was writing
that...
>> The UDP_IER is defined as a AT91_REG which is in turn
>> typedef'd as a volatile unsigned int...
>
> What about the other operations? Are they also on volatile types? The
> compiler is allowed to change the order on non-volatile data types but the
> order and number of accesses of volatile types must be maintained.
Good point. There is one volatile item but it's one of the first things
that is initialized.
The problem is that there's still no guarantee that the compiler would
not optimize the code in a way that could break it.
I guess the lesson here is that sometimes the source code is not
executed in the order you think. The compiler will make sure that
there is no semantic difference after running the code, but it
cannot make sure that the side effects of running the code out
of order are benign.
Ralph

(You need to be a member of AT91SAM -- send a blank email to AT91SAM-subscribe@yahoogroups.com )
Re: AT91SAM7S USB Woes - Robert Adsett - Jan 31 17:52:30 2008
At 05:20 PM 1/31/2008 -0500, Ralph Hempel wrote:
>Robert Adsett wrote:
>
> >> It's a read only register, but it returns all 0s
> >
> > Write only maybe?
>
>Yes, write only - I was a bit excited when I was writing
>that...
>
> >> The UDP_IER is defined as a AT91_REG which is in turn
> >> typedef'd as a volatile unsigned int...
> >
> > What about the other operations? Are they also on volatile types? The
> > compiler is allowed to change the order on non-volatile data types but the
> > order and number of accesses of volatile types must be maintained.
>
>Good point. There is one volatile item but it's one of the first things
>that is initialized.
>
>The problem is that there's still no guarantee that the compiler would
>not optimize the code in a way that could break it.
That's what you use volatile for. To provide a guarantee on the order of
operations.
Robert
Another sign of the end of civilization, our technical magazines are
getting chatty
From an EETimes product descriptions 2006/08/09
".... systems that can sample gobs of inputs simultaneously"
Now just what is the technical definition for gobs again?
http://www.aeolusdevelopment.com/

(You need to be a member of AT91SAM -- send a blank email to AT91SAM-subscribe@yahoogroups.com )
Re: AT91SAM7S USB Woes - Ralph Hempel - Jan 31 20:14:58 2008
Robert Adsett wrote:
> That's what you use volatile for. To provide a guarantee on the order of
> operations.
Not to pick nits - but that's not quite right according to my
well-thumbed copy of "C - A Reference Manual"
In the section on the volatile qualifier, it says that any object
of a volatile qualified type should not participate in optimizations
that wold increase, decrease, or delay any references to, or
modifications of, the object.
Normally, that means statements like:
volatile unsigned int *some_register = 0xFFFF0200;
x = *some_register;
y = *some_register;
will _guarantee_ that some_register will be read twice, whereas the
whithout volitel, the compiler could just do:
y = x;
instead of the second statement.
More precisely, optimization of references to and modifications
of an object cannot occur across sequence points, and simple
assignments are not sequence points, so they can occur in any order.
A sequence point is something like the end of an expression, a control
strucuture like if, while, do, etc, or even logical comparisons or the
comma operator.
Long story short, even with a volatile operator, things like:
x = 2;
y = 4;
z = 6;
Can occur in ANY order because they are _assignments_ and that's
not enough to qualify as a sequence point.
Ralph

(You need to be a member of AT91SAM -- send a blank email to AT91SAM-subscribe@yahoogroups.com )
Re: AT91SAM7S USB Woes - Robert Adsett - Jan 31 20:38:05 2008
At 07:57 PM 1/31/2008 -0500, Ralph Hempel wrote:
>Robert Adsett wrote:
>
> > That's what you use volatile for. To provide a guarantee on the order of
> > operations.
>
>Not to pick nits - but that's not quite right according to my
>well-thumbed copy of "C - A Reference Manual"
>
>In the section on the volatile qualifier, it says that any object
>of a volatile qualified type should not participate in optimizations
>that wold increase, decrease, or delay any references to, or
>modifications of, the object.
>
>Normally, that means statements like:
>
>volatile unsigned int *some_register = 0xFFFF0200;
>
>x = *some_register;
>y = *some_register;
>
>will _guarantee_ that some_register will be read twice, whereas the
>whithout volitel, the compiler could just do:
>
>y = x;
>
>instead of the second statement.
Yep.
>More precisely, optimization of references to and modifications
>of an object cannot occur across sequence points, and simple
>assignments are not sequence points, so they can occur in any order.
>
>A sequence point is something like the end of an expression, a control
>strucuture like if, while, do, etc, or even logical comparisons or the
>comma operator.
>
>Long story short, even with a volatile operator, things like:
>
>x = 2;
>y = 4;
>z = 6;
There's a sequence point between each of those assignments. See for
example http://en.wikipedia.org/wiki/Sequence_point
Robert
>
" 'Freedom' has no meaning of itself. There are always restrictions,
be they legal, genetic, or physical. If you don't believe me, try to chew
a radio signal. " -- Kelvin Throop, III

(You need to be a member of AT91SAM -- send a blank email to AT91SAM-subscribe@yahoogroups.com )
Re: AT91SAM7S USB Woes - Ralph Hempel - Jan 31 21:20:30 2008
Robert Adsett wrote:
>> Long story short, even with a volatile operator, things like:
>>
>> x = 2;
>> y = 4;
>> z = 6;
>
> There's a sequence point between each of those assignments. See for
> example http://en.wikipedia.org/wiki/Sequence_point
Hmmm, mea culpa. According to wikipedia I stand corrected, but I think
that there's a caveat that those assignments are sequence points
if and only if the assignments have no side effects...
See point 2 and the subsequent discussion...
Robert, I am honestly not trying to have the last word here. I respect
your writings and the time you put in on this forum. We are talking
about the dark corners of the C language and we need to figure out
if this is a bug or just really good optimization at work.
Then we have to figure out how to make sure it does not happen again
by writing the code correctly next time!
Cheers, Ralph

(You need to be a member of AT91SAM -- send a blank email to AT91SAM-subscribe@yahoogroups.com )Re: AT91SAM7S USB Woes - Robert Adsett - Jan 31 21:52:21 2008
At 08:49 PM 1/31/2008 -0500, Ralph Hempel wrote:
>Robert Adsett wrote:
>
> >> Long story short, even with a volatile operator, things like:
> >>
> >> x = 2;
> >> y = 4;
> >> z = 6;
> >
> > There's a sequence point between each of those assignments. See for
> > example http://en.wikipedia.org/wiki/Sequence_point
>
>Hmmm, mea culpa. According to wikipedia I stand corrected, but I think
>that there's a caveat that those assignments are sequence points
>if and only if the assignments have no side effects...
>
>
See
point 2 and the subsequent discussion...
Nope, they are still sequence points, at least I've not seen anything that
would suggest otherwise. The point 2 referred to above simply states the
accessing a volatile is a side effect and side effects must occur by the
sequence point. See also point 5.
Jack Klein has a nice example in the following thread
http://groups.google.com/group/comp.lang.c/browse_frm/thread/284db3989db064a1/14bb21b33117d259?lnk=gst&q=%2Bvolatile+%2Bwrite#14bb21b33117d259
>Robert, I am honestly not trying to have the last word here. I respect
>your writings and the time you put in on this forum. We are talking
>about the dark corners of the C language and we need to figure out
>if this is a bug or just really good optimization at work.
>
>Then we have to figure out how to make sure it does not happen again
>by writing the code correctly next time!
I'm with you. Volatile is usually explained in terms of the hardware or
another thread changing the value underneath the feet of the first
thread. I think I've only seen the write implications explained once and I
can't find a reference.
Besides which compiler bugs usually show up in the dark corners or the
processor specific extensions. I expect the dark corners to work but they
are still areas to check when trouble occurs. Experience leads me to avoid
the latter, especially those that can be easily avoided like interrupt and
packed.
Robert
From the Divided by a Common Language File (Edited to protect the guilty)
ME - "I'd like to get Price and delivery for connector Part # XXXXX"
Dist./Rep - "$X.XX Lead time 37 days"
ME - "Anything we can do about lead time? 37 days seems a bit high."
Dist./Rep - "that is the lead time given because our stock is live.... we
currently have stock."

(You need to be a member of AT91SAM -- send a blank email to AT91SAM-subscribe@yahoogroups.com )Re: AT91SAM7S USB Woes - Ralph Hempel - Feb 1 1:40:40 2008
Ralph Hempel wrote:
> Some time back, I was looking for some help with the
> Atmel USB Framework 1.02 Core ad CDC application under
> gcc 4.2
I finally! tracked down the problem to some overzealous
optimization by gcc.
With -O1 the USB Framework works fine
With -O2 or -Os there is a problem
I think it's in UDP_Read() and what's happening is that
the interrupt enable on the endpoint is ocurring before
the endpoint parameters are getting set up.
Looking at the source, I can definitely see that the order
in the listing is OK, but when I look at the resulting
assembler code, it seems as if it's been moved up to just
after the point where pInterface gets set...
I hope that this helps somebody that's having trouble.
Now I just have to modify my build system to allow for
optimizing some modules and not others. On the other
hand the difference between -O1 and -O2 is only about 10%
so it might be more trouble than it's worth!
Cheers, Ralph

(You need to be a member of AT91SAM -- send a blank email to AT91SAM-subscribe@yahoogroups.com )
Re: AT91SAM7S USB Woes - Ralph Hempel - Feb 1 3:57:56 2008
Robert Adsett wrote:
> At 11:18 AM 1/31/2008 -0500, Ralph Hempel wrote:
>> Ralph Hempel wrote:
>>> Some time back, I was looking for some help with the
>>> Atmel USB Framework 1.02 Core ad CDC application under
>>> gcc 4.2
>> I finally! tracked down the problem to some overzealous
>> optimization by gcc.
> Would the interrupt enable be in inline asm?
SET(pInterface->UDP_IER, 1 << bEndpoint);
Which evaluates to:
register = register | flags
It's a read only register, but it returns all 0s
The UDP_IER is defined as a AT91_REG which is in turn
typedef'd as a volatile unsigned int...
Ralph

(You need to be a member of AT91SAM -- send a blank email to AT91SAM-subscribe@yahoogroups.com )
RE: AT91SAM7S USB Woes - Paul Curtis - Feb 1 4:02:49 2008
Ralph,
> > Ralph
> > Check out GCC's "memory barrier". I believe it is something like
> >
> > #define barrier() __asm__ __volatile__ ("":::"memory")
> >
> > Place it between the accesses to the register. It will cause GCC to
> not
> > optimize code by moving it across the barrier.
>
> Bill,
>
> I'll do that, but it begs the question, what else has gcc optimized
> to the point where it does not work correctly?
All reads and writes to volatiles should be in execution order (guaranteed
complete at sequence points, to be exact). Non-volatiles do not have this
property.
> I've been at this game long enough to know that all compilers
> have bugs in the corners somewhere. Normally they manifest themselves
> in obvious ways - this one has been producing nagging little
> errors for almost a year now.
>
> No matter how often you look at and inspect the source code, having
> the compiler silently move code around is unsettling...
It's what customers demand. Code can be transformed however the compiler
sees fit as long as the resulting code runs with C semantics. If you can
demonstrate a small snippet of code that shows what you write in C and what
you get in assembly code then it could be diagnosed a little further.
--
Paul Curtis, Rowley Associates Ltd http://www.rowley.co.uk
CrossWorks for ARM, MSP430, AVR, MAXQ, and now Cortex-M3 processors

(You need to be a member of AT91SAM -- send a blank email to AT91SAM-subscribe@yahoogroups.com )
Re: AT91SAM7S USB Woes - Ralph Hempel - Feb 1 9:27:06 2008
Paul Curtis wrote:
> All reads and writes to volatiles should be in execution order (guaranteed
> complete at sequence points, to be exact). Non-volatiles do not have this
> property.
Hi Paul! You can probably guess what project this is for based on
previous correspondence we've had.
Here's the code from the ATMEL USB Framework Core 1.02 in question. It
was downloaded from Martin Thomas's WinArm site...
UDP_IER is declared as a volatile unsigned int, SET is a macro that
expands to:
register = register | flags;
-----------------------------------------------
// Endpoint enters Read state
pEndpoint->dState = endpointStateRead;
// Set the transfer descriptor
pEndpoint->pData = (char *) pData;
pEndpoint->dBytesRemaining = dLength;
pEndpoint->dBytesBuffered = 0;
pEndpoint->dBytesTransferred = 0;
pEndpoint->fCallback = fCallback;
pEndpoint->pArgument = pArgument;
// Enable interrupt on endpoint
SET(pInterface->UDP_IER, 1 << bEndpoint);
-----------------------------------------------
gcc 4.2 with -Os optimizations puts the enable interrupt code
_before_ the code that initialized the endpoint handler data
structure, probably because pInterface is calculated in an
earlier assignment and there's no point in reloading a register
to get it back.
>> No matter how often you look at and inspect the source code, having
>> the compiler silently move code around is unsettling...
>
> It's what customers demand. Code can be transformed however the compiler
> sees fit as long as the resulting code runs with C semantics. If you can
> demonstrate a small snippet of code that shows what you write in C and what
> you get in assembly code then it could be diagnosed a little further.
That's exactly why I'm pressing this point. Is what I'm seeing a bug
or is it a very good optimization?
Ralph

(You need to be a member of AT91SAM -- send a blank email to AT91SAM-subscribe@yahoogroups.com )
Re: AT91SAM7S USB Woes - Bill Knight - Feb 1 9:51:48 2008
Ralph Hempel wrote:
> Paul Curtis wrote:
>
>> All reads and writes to volatiles should be in execution order (guaranteed
>> complete at sequence points, to be exact). Non-volatiles do not have this
>> property.
>
> Hi Paul! You can probably guess what project this is for based on
> previous correspondence we've had.
>
> Here's the code from the ATMEL USB Framework Core 1.02 in question. It
> was downloaded from Martin Thomas's WinArm site...
>
> UDP_IER is declared as a volatile unsigned int, SET is a macro that
> expands to:
>
> register = register | flags;
>
> -----------------------------------------------
> // Endpoint enters Read state
> pEndpoint->dState = endpointStateRead;
>
> // Set the transfer descriptor
> pEndpoint->pData = (char *) pData;
> pEndpoint->dBytesRemaining = dLength;
> pEndpoint->dBytesBuffered = 0;
> pEndpoint->dBytesTransferred = 0;
> pEndpoint->fCallback = fCallback;
> pEndpoint->pArgument = pArgument;
>
> // Enable interrupt on endpoint
> SET(pInterface->UDP_IER, 1 << bEndpoint);
> -----------------------------------------------
>
> gcc 4.2 with -Os optimizations puts the enable interrupt code
> _before_ the code that initialized the endpoint handler data
> structure, probably because pInterface is calculated in an
> earlier assignment and there's no point in reloading a register
> to get it back.
>
>>> No matter how often you look at and inspect the source code, having
>>> the compiler silently move code around is unsettling...
>> It's what customers demand. Code can be transformed however the compiler
>> sees fit as long as the resulting code runs with C semantics. If you can
>> demonstrate a small snippet of code that shows what you write in C and what
>> you get in assembly code then it could be diagnosed a little further.
>
> That's exactly why I'm pressing this point. Is what I'm seeing a bug
> or is it a very good optimization?
>
> Ralph
Ralph
I'm jumping back in here. I assume from looking at the code that
pEndpoint and what it points to are not marked as volatile. If that is
the case, then the compiler is not moving the setting of the interrupt
enable bit up, it is moving the initialization of the endpoint data
down. It is cases like this that the barrier marking was intended.
I've seen it used in the RTEMS (rtos) code and have seen discussions of
its use in the Linux kernel code.
Regards
-Bill Knight
R O SoftWare

(You need to be a member of AT91SAM -- send a blank email to AT91SAM-subscribe@yahoogroups.com )
RE: AT91SAM7S USB Woes - Paul Curtis - Feb 1 9:55:05 2008
Hi Ralph,
> > All reads and writes to volatiles should be in execution order
> (guaranteed
> > complete at sequence points, to be exact). Non-volatiles do not have
> this
> > property.
>
> Hi Paul! You can probably guess what project this is for based on
> previous correspondence we've had.
Sure. :-)
> Here's the code from the ATMEL USB Framework Core 1.02 in question. It
> was downloaded from Martin Thomas's WinArm site...
>
> UDP_IER is declared as a volatile unsigned int, SET is a macro that
> expands to:
>
> register = register | flags;
>
> -----------------------------------------------
> // Endpoint enters Read state
> pEndpoint->dState = endpointStateRead;
>
> // Set the transfer descriptor
> pEndpoint->pData = (char *) pData;
> pEndpoint->dBytesRemaining = dLength;
> pEndpoint->dBytesBuffered = 0;
> pEndpoint->dBytesTransferred = 0;
> pEndpoint->fCallback = fCallback;
> pEndpoint->pArgument = pArgument;
>
> // Enable interrupt on endpoint
> SET(pInterface->UDP_IER, 1 << bEndpoint);
> -----------------------------------------------
>
> gcc 4.2 with -Os optimizations puts the enable interrupt code
> _before_ the code that initialized the endpoint handler data
> structure, probably because pInterface is calculated in an
> earlier assignment and there's no point in reloading a register
> to get it back.
[ snip ]
> That's exactly why I'm pressing this point. Is what I'm seeing a bug
> or is it a very good optimization?
Ok, here we need to be very precise and choose words carefully. In another
life I reckon I would enjoy being a lawyer.
The compiler is being smart. It's allowed to move statements around as long
as the overall effect is the same. Consider this:
x = 1;
y = 2;
z = 3;
Now you can see that x, y, and z can be assigned in any order and the effect
will be the same. Introducing a volatile variable v:
x = 1;
y = 2;
z = 3;
v = 4;
Same thing! As there are no other volatile references, all you can say at
the ; on v=4 is that v *will* be 4. You can't make a judgement on x, y, or
z. No siree.
You want x to be 1 before z? No problem: declare it volatile as C's
semantics guarantee ordering amongst volatile accesses and sequence points.
The corollary is, of course, the solution to your specific case: do the
RIGHT THING and declare pEndpoint as volatile or the struct it points to as
volatile and bingo! Job done!
Now, back in the Real World. People who write compilers break the Principle
of Last Astonishment on a regular basis:
http://en.wikipedia.org/wiki/Principle_of_least_astonishment
Really, there is NO reason WHATSOEVER for a compiler to do this optimization
other than pure exhibitionism. Yes, it's valid by the language standard but
the reality of day-to-day life is that you don't want surprises. The world
is full of programmers oblivious to the C standard --I know as I get
assaulted by programmers that think they know better than I about the C
language and proceed to reel off reasons why things are broken. Ask them
whether they have read the C standard and it's invariably "no I haven't but
my code works on
and it's
not working on your compiler do your compiler is broken!" This is a vacuous
argument as all it does is compare implementations of C, not whether they've
written code which has unambiguous meaning when measured against the
standard. I have argued with customers forever that their code is broken
but they can write it cleanly in portable fashion to work on multiple
compilers. I've been doing so for 25 years now.
All my compilers work by a simple principle: do nothing that astonishes
users, do good code generation simply, let the user optimize his own code.
It worked for Wirth and I'm glad I had experience of his compilers when I
started on my chosen path. C compilers often want to optimize the hell out
of a program when it's just not worth the effort. Wirth had it right, an
optimization is only worth making if adding it to the compiler will pay for
itself (i.e. the time for self-compilation would be reduced).
All the "sexy" stuff is in the back end and, boy, GCC has one BIG arse to
tinker with. Big fascination.
--
Paul Curtis, Rowley Associates Ltd http://www.rowley.co.uk
CrossWorks for ARM, MSP430, AVR, MAXQ, and now Cortex-M3 processors

(You need to be a member of AT91SAM -- send a blank email to AT91SAM-subscribe@yahoogroups.com )Re: AT91SAM7S USB Woes - Ralph Hempel - Feb 1 10:31:05 2008
Bill Knight wrote:
> Ralph
> I'm jumping back in here. I assume from looking at the code that
> pEndpoint and what it points to are not marked as volatile. If that is
> the case, then the compiler is not moving the setting of the interrupt
> enable bit up, it is moving the initialization of the endpoint data
> down. It is cases like this that the barrier marking was intended.
> I've seen it used in the RTEMS (rtos) code and have seen discussions of
> its use in the Linux kernel code.
Bill,
The pEndpoint->State is marked volatile. It is possible that the
interrupt enable happens after the state is set but before
the rest of the struct is initialized.
Honestly, the code with -O2 is so convoluted that it's almost
impossible to figure out what it's doing.
The end effect of the moving is still not what is intended, even if
it's semantically correct :-)
I'll look at implementing the barrier, but I wish there was a
standard C construct I could use to avoid the problem with other
compilers too.
Thanks for the extra info!
Cheers, Ralph

(You need to be a member of AT91SAM -- send a blank email to AT91SAM-subscribe@yahoogroups.com )
Re: AT91SAM7S USB Woes - Ralph Hempel - Feb 1 10:39:09 2008
Paul Curtis wrote:
> Ok, here we need to be very precise and choose words carefully. In another
> life I reckon I would enjoy being a lawyer.
>
> The compiler is being smart. It's allowed to move statements around as long
> as the overall effect is the same. Consider this:
...
> You want x to be 1 before z? No problem: declare it volatile as C's
> semantics guarantee ordering amongst volatile accesses and sequence points.
>
> The corollary is, of course, the solution to your specific case: do the
> RIGHT THING and declare pEndpoint as volatile or the struct it points to as
> volatile and bingo! Job done!
I could also move the state assignment to after the struct init, but I
like your suggestion of declating pEndpoint volatile...
> I have argued with customers forever that their code is broken
> but they can write it cleanly in portable fashion to work on multiple
> compilers. I've been doing so for 25 years now.
And I've argued that programmers (especially embedded programmers)
should at the very least have Harbison & Steeles C Reference Manual
close at hand.
If your copy does not fall apart every 5 years from use, then you
are not using it enough :-)
> It worked for Wirth and I'm glad I had experience of his compilers when I
> started on my chosen path. C compilers often want to optimize the hell out
> of a program when it's just not worth the effort. Wirth had it right, an
> optimization is only worth making if adding it to the compiler will pay for
> itself (i.e. the time for self-compilation would be reduced).
Wow. You worked for Wirth? That's something that not everyone can say...
> All the "sexy" stuff is in the back end and, boy, GCC has one BIG arse to
> tinker with. Big fascination.
And your toolset is based on gcc as I understand it, so you are as
familiar with it as can be.
Thanks for the extra insight Paul!
Cheers, Ralph

(You need to be a member of AT91SAM -- send a blank email to AT91SAM-subscribe@yahoogroups.com )
RE: AT91SAM7S USB Woes - Paul Curtis - Feb 1 10:44:58 2008
Ralph,
> The pEndpoint->State is marked volatile.
Not enough! Just means that that member is volatile, nothing else.
> It is possible that the
> interrupt enable happens after the state is set but before
> the rest of the struct is initialized.
Sure is.
> Honestly, the code with -O2 is so convoluted that it's almost
> impossible to figure out what it's doing.
>
> The end effect of the moving is still not what is intended, even if
> it's semantically correct :-)
>
> I'll look at implementing the barrier, but I wish there was a
> standard C construct I could use to avoid the problem with other
> compilers too.
Make pEndpoint a pointer to volatile:
volatile WhateverStruct * pEndpoint; // right
Note that making the *pointer* volatile will not necessarily change the
writes to the struct.
WhateverStruct * volatile pEndpoint; // wrong
--
Paul Curtis, Rowley Associates Ltd http://www.rowley.co.uk
CrossWorks for ARM, MSP430, AVR, MAXQ, and now Cortex-M3 processors

(You need to be a member of AT91SAM -- send a blank email to AT91SAM-subscribe@yahoogroups.com )
RE: AT91SAM7S USB Woes - Paul Curtis - Feb 1 10:45:51 2008
Ralph,
> > The corollary is, of course, the solution to your specific case: do
> the
> > RIGHT THING and declare pEndpoint as volatile or the struct it points
> to as
> > volatile and bingo! Job done!
>
> I could also move the state assignment to after the struct init, but I
> like your suggestion of declating pEndpoint volatile...
I don't believe that will work in the general case -- well, at least I don't
think it will. All it will do is guarantee that the state is assigned
*before* the interrupt is enabled. That doesn't mean that the struct will
fully-assigned before interrupts are enabled or that the state is set.
--
Paul Curtis, Rowley Associates Ltd http://www.rowley.co.uk
CrossWorks for ARM, MSP430, AVR, MAXQ, and now Cortex-M3 processors

(You need to be a member of AT91SAM -- send a blank email to AT91SAM-subscribe@yahoogroups.com )
RE: AT91SAM7S USB Woes - Robert Adsett - Feb 1 10:49:46 2008
At 03:41 PM 2/1/2008 +0000, Paul Curtis wrote:
>Make pEndpoint a pointer to volatile:
>
>volatile WhateverStruct * pEndpoint; // right
>
>Note that making the *pointer* volatile will not necessarily change the
>writes to the struct.
>
>WhateverStruct * volatile pEndpoint; // wrong
And if you find yourself getting confused about whether you are declaring a
pointer to volatile or a volatile pointer get a copy of cdecl. It'll help
confirm that your understanding is correct.
Robert
From the Divided by a Common Language File (Edited to protect the guilty)
ME - "I'd like to get Price and delivery for connector Part # XXXXX"
Dist./Rep - "$X.XX Lead time 37 days"
ME - "Anything we can do about lead time? 37 days seems a bit high."
Dist./Rep - "that is the lead time given because our stock is live.... we
currently have stock."

(You need to be a member of AT91SAM -- send a blank email to AT91SAM-subscribe@yahoogroups.com )
Re: AT91SAM7S USB Woes - Ralph Hempel - Feb 1 11:02:52 2008
Paul Curtis wrote:
> Make pEndpoint a pointer to volatile:
>
> volatile WhateverStruct * pEndpoint; // right
Because this is read as:
pEndpoint is a pointer to WhateverStruct which is volatile.
> Note that making the *pointer* volatile will not necessarily change the
> writes to the struct.
>
> WhateverStruct * volatile pEndpoint; // wrong
Because this is read as:
pEndpoint is a volatile pointer to WhateverStruct.
And for everyone else that's still following the thread and has
no idea what we're talking about:
Ralph

(You need to be a member of AT91SAM -- send a blank email to AT91SAM-subscribe@yahoogroups.com )Re: AT91SAM7S USB Woes - Ralph Hempel - Feb 1 11:40:48 2008
Paul Curtis wrote:
> We're dealing with (1) in Ralph's case, he needs to use volatile correctly.
> :-)
And then he needs to feed back the results to Atmel since he's using
their code...
Cheers, Ralph

(You need to be a member of AT91SAM -- send a blank email to AT91SAM-subscribe@yahoogroups.com )
RE: AT91SAM7S USB Woes - Paul Curtis - Feb 1 11:47:10 2008
Hi Robert,
> >Make pEndpoint a pointer to volatile:
> >
> >volatile WhateverStruct * pEndpoint; // right
> >
> >Note that making the *pointer* volatile will not necessarily change
> the
> >writes to the struct.
> >
> >WhateverStruct * volatile pEndpoint; // wrong
>
> And if you find yourself getting confused about whether you are
> declaring a pointer to volatile or a volatile pointer get a copy of cdecl.
It'll
> help confirm that your understanding is correct.
Biggest ever mistake in C, and the designers regret the decision to make
decls look like uses. Again, Wirth had it right in Pascal and even more
correct in Modula-2. But that's a story for another day.
--
Paul Curtis, Rowley Associates Ltd http://www.rowley.co.uk
CrossWorks for ARM, MSP430, AVR, MAXQ, and now Cortex-M3 processors

(You need to be a member of AT91SAM -- send a blank email to AT91SAM-subscribe@yahoogroups.com )
RE: AT91SAM7S USB Woes - Paul Curtis - Feb 1 12:08:44 2008
Bill,
> > That's exactly why I'm pressing this point. Is what I'm seeing a bug
> > or is it a very good optimization?
> >
> > Ralph
>
> Ralph
> I'm jumping back in here. I assume from looking at the code that
> pEndpoint and what it points to are not marked as volatile. If that is
> the case, then the compiler is not moving the setting of the interrupt
> enable bit up, it is moving the initialization of the endpoint data
> down. It is cases like this that the barrier marking was intended.
> I've seen it used in the RTEMS (rtos) code and have seen discussions of
> its use in the Linux kernel code.
There are two things here, perhaps being mixed together.
1. Tell the compiler to do things in order.
2. Tell the hardware to do things in order.
(1) is satisfied with proper use of "volatile" for single-core systems.
Memory is coherent, even in the case of caches, with a single-core system.
(We will leave out the case of accessing cached with non-cached memory
accesses).
(2) is satisfied with write/read barriers. These are required by SMP
systems along with exclusivity (some form of LOCK instruction, or the 68k
TAS/CAS/CAS2 style things). This is usually processor-specific and
accomplished by special instructions.
We're dealing with (1) in Ralph's case, he needs to use volatile correctly.
:-)
--
Paul Curtis, Rowley Associates Ltd http://www.rowley.co.uk
CrossWorks for ARM, MSP430, AVR, MAXQ, and now Cortex-M3 processors

(You need to be a member of AT91SAM -- send a blank email to AT91SAM-subscribe@yahoogroups.com )
Re: AT91SAM7S USB Woes - Russell Shaw - Feb 1 20:14:59 2008
Paul Curtis wrote:
> Hi Robert,
>
>>> Make pEndpoint a pointer to volatile:
>>>
>>> volatile WhateverStruct * pEndpoint; // right
>>>
>>> Note that making the *pointer* volatile will not necessarily change
>> the writes to the struct.
>>>
>>> WhateverStruct * volatile pEndpoint; // wrong
>> And if you find yourself getting confused about whether you are
>> declaring a pointer to volatile or a volatile pointer get a copy of cdecl.
> It'll help confirm that your understanding is correct.
>
> Biggest ever mistake in C, and the designers regret the decision to make
> decls look like uses. Again, Wirth had it right in Pascal and even more
> correct in Modula-2. But that's a story for another day.
"decls look like uses" ? How so? How else would you declare something?

(You need to be a member of AT91SAM -- send a blank email to AT91SAM-subscribe@yahoogroups.com )
Re: AT91SAM7S USB Woes - Russell Shaw - Feb 1 20:26:01 2008
Paul Curtis wrote:
> Hi Ralph,
>
>>> All reads and writes to volatiles should be in execution order
>> (guaranteed
>>> complete at sequence points, to be exact). Non-volatiles do not have
>> this
>>> property.
>> Hi Paul! You can probably guess what project this is for based on
>> previous correspondence we've had.
>
> Sure. :-)
>
>> Here's the code from the ATMEL USB Framework Core 1.02 in question. It
>> was downloaded from Martin Thomas's WinArm site...
>>
>> UDP_IER is declared as a volatile unsigned int, SET is a macro that
>> expands to:
>>
>> register = register | flags;
>>
>> -----------------------------------------------
>> // Endpoint enters Read state
>> pEndpoint->dState = endpointStateRead;
>>
>> // Set the transfer descriptor
>> pEndpoint->pData = (char *) pData;
>> pEndpoint->dBytesRemaining = dLength;
>> pEndpoint->dBytesBuffered = 0;
>> pEndpoint->dBytesTransferred = 0;
>> pEndpoint->fCallback = fCallback;
>> pEndpoint->pArgument = pArgument;
>>
>> // Enable interrupt on endpoint
>> SET(pInterface->UDP_IER, 1 << bEndpoint);
>> -----------------------------------------------
>>
>> gcc 4.2 with -Os optimizations puts the enable interrupt code
>> _before_ the code that initialized the endpoint handler data
>> structure, probably because pInterface is calculated in an
>> earlier assignment and there's no point in reloading a register
>> to get it back.
>
> [ snip ]
>
>> That's exactly why I'm pressing this point. Is what I'm seeing a bug
>> or is it a very good optimization?
>
> Ok, here we need to be very precise and choose words carefully. In another
> life I reckon I would enjoy being a lawyer.
>
> The compiler is being smart. It's allowed to move statements around as long
> as the overall effect is the same. Consider this:
>
> x = 1;
> y = 2;
> z = 3;
>
> Now you can see that x, y, and z can be assigned in any order and the effect
> will be the same. Introducing a volatile variable v:
>
> x = 1;
> y = 2;
> z = 3;
> v = 4;
>
> Same thing! As there are no other volatile references, all you can say at
> the ; on v=4 is that v *will* be 4. You can't make a judgement on x, y, or
> z. No siree.
>
> You want x to be 1 before z? No problem: declare it volatile as C's
> semantics guarantee ordering amongst volatile accesses and sequence points.
>
> The corollary is, of course, the solution to your specific case: do the
> RIGHT THING and declare pEndpoint as volatile or the struct it points to as
> volatile and bingo! Job done!
>
> Now, back in the Real World. People who write compilers break the Principle
> of Last Astonishment on a regular basis:
>
> http://en.wikipedia.org/wiki/Principle_of_least_astonishment
>
> Really, there is NO reason WHATSOEVER for a compiler to do this optimization
> other than pure exhibitionism. Yes, it's valid by the language standard but
> the reality of day-to-day life is that you don't want surprises.
When you've written optimizing compilers that do all kinds of intermediate
transformations on the intermediate code, preserving the order of statements
is really nonsensical because even basic optimizations rely on reordering
code.
> The world
> is full of programmers oblivious to the C standard --I know as I get
> assaulted by programmers that think they know better than I about the C
> language and proceed to reel off reasons why things are broken. Ask them
> whether they have read the C standard and it's invariably "no I haven't but
> my code works on
and it's
> not working on your compiler do your compiler is broken!" This is a vacuous
> argument as all it does is compare implementations of C, not whether they've
> written code which has unambiguous meaning when measured against the
> standard. I have argued with customers forever that their code is broken
> but they can write it cleanly in portable fashion to work on multiple
> compilers. I've been doing so for 25 years now.
>
> All my compilers work by a simple principle: do nothing that astonishes
> users, do good code generation simply, let the user optimize his own code.
> It worked for Wirth and I'm glad I had experience of his compilers when I
> started on my chosen path. C compilers often want to optimize the hell out
> of a program when it's just not worth the effort. Wirth had it right, an
> optimization is only worth making if adding it to the compiler will pay for
> itself (i.e. the time for self-compilation would be reduced).
>
> All the "sexy" stuff is in the back end and, boy, GCC has one BIG arse to
> tinker with. Big fascination.

(You need to be a member of AT91SAM -- send a blank email to AT91SAM-subscribe@yahoogroups.com )RE: AT91SAM7S USB Woes - Paul Curtis - Feb 2 4:01:45 2008
Hi,
> > Really, there is NO reason WHATSOEVER for a compiler to do this
> optimization
> > other than pure exhibitionism. Yes, it's valid by the language
> standard but
> > the reality of day-to-day life is that you don't want surprises.
>
> When you've written optimizing compilers that do all kinds of
> intermediate
> transformations on the intermediate code, preserving the order of
> statements
> is really nonsensical because even basic optimizations rely on
> reordering code.
This is where I vehemently disagree with every bone in my being.
I will agree that when lowing representation an inferior compiler might
decide to chuck source context and "get lost" in the raptures of code
motion, PRE, strength reduction, loop unrolling, and specialisation. During
the lowering some context will obviously get lost, such as the order of
operands of commutative operators, but never the order of statements in a
program.
Reorder the lowered representation within a statement all you like and apply
those whiz-bang optimizations to get great local code. But changing
statement order is plain evil, pure and simple. I know all the classic and
new optimizations having two shelves dedicated to published books and
journals and access to research papers online, but they make code generation
so difficult and error prone you can have little confidence in the compiler.
Simple compilers are robust compilers, and compilers written by a SINGLE
person happen to be the simplest and most robust and easiest to
understand--which is just the ticket: KISS.
--
Paul Curtis, Rowley Associates Ltd http://www.rowley.co.uk
CrossWorks for ARM, MSP430, AVR, MAXQ, and now Cortex-M3 processors

(You need to be a member of AT91SAM -- send a blank email to AT91SAM-subscribe@yahoogroups.com )
RE: AT91SAM7S USB Woes - Paul Curtis - Feb 2 4:29:40 2008
Hi,
> > decls look like uses. Again, Wirth had it right in Pascal and even
> more
> > correct in Modula-2. But that's a story for another day.
> "decls look like uses" ? How so? How else would you declare something?
Yes, declarations of variables look like their uses.
declare x as pointer to int: int *x;
fetch the int pointed to by x: *x;
declare x as a pointer to an array of three ints: int (*x)[3];
fetch the int in the array pointed to by x: (*x)[0];
declare x as an array of three pointers to ints: int *x[3];
fetch the int pointed to in the array x: *x[0];
These last two cause more confusion than anything, even amonst C
programmers. Mismatch the declaration and use and, boy, do sparks fly and
no compiler will generate an error in the process.
With prefix "*" and postfix [] it's possible to write horrible declarations
where you need to work inside out. Same for uses.
Contrast with a clean Modula-2 style that is unambiguous, same three
declarations and uses:
POINTER TO INTEGER
x^
POINTER TO ARRAY [0..2] OF INTEGER;
x^[0]
ARRAY [0..2] OF POINTER TO INTEGER;
x[0]^
With both you read and write left to right. Simple, clear, efficient. No
state machine needed to decode these, instantly recognizable, and the
compiler will bloody well tell you if you get it wrong. No hunting to
figure out what it means, no need for parentheses to alter binding order.
Modula-2 is clearly superior in this department.
--
Paul Curtis, Rowley Associates Ltd http://www.rowley.co.uk
CrossWorks for ARM, MSP430, AVR, MAXQ, and now Cortex-M3 processors

(You need to be a member of AT91SAM -- send a blank email to AT91SAM-subscribe@yahoogroups.com )
Re: AT91SAM7S USB Woes - Russell Shaw - Feb 2 4:38:46 2008
Paul Curtis wrote:
> Hi,
>
>>> decls look like uses. Again, Wirth had it right in Pascal and even
>> more
>>> correct in Modula-2. But that's a story for another day.
>> "decls look like uses" ? How so? How else would you declare something?
>
> Yes, declarations of variables look like their uses.
>
> declare x as pointer to int: int *x;
> fetch the int pointed to by x: *x;
>
> declare x as a pointer to an array of three ints: int (*x)[3];
> fetch the int in the array pointed to by x: (*x)[0];
>
> declare x as an array of three pointers to ints: int *x[3];
> fetch the int pointed to in the array x: *x[0];
>
> These last two cause more confusion than anything, even amonst C
> programmers. Mismatch the declaration and use and, boy, do sparks fly and
> no compiler will generate an error in the process.
The compiler gives an error if you declare the same thing twice
or forget to declare it at all (unless you use nested {} scopes
which isn't common).
> With prefix "*" and postfix [] it's possible to write horrible declarations
> where you need to work inside out. Same for uses.
>
> Contrast with a clean Modula-2 style that is unambiguous, same three
> declarations and uses:
>
> POINTER TO INTEGER
> x^
>
> POINTER TO ARRAY [0..2] OF INTEGER;
> x^[0]
>
> ARRAY [0..2] OF POINTER TO INTEGER;
> x[0]^
>
> With both you read and write left to right. Simple, clear, efficient. No
> state machine needed to decode these, instantly recognizable, and the
> compiler will bloody well tell you if you get it wrong. No hunting to
> figure out what it means, no need for parentheses to alter binding order.
> Modula-2 is clearly superior in this department.
I really hate the wordiness of pascal languages (especially VHDL and ADA).
http://azure.humbug.org.au/~aj/bwk_on_pascal.html
Turbo pascal was my first language, followed by delphi, C, C++, VHDL, and
various scripting languages.
I'd rather flip burgers if i had to write in anything other than C (for
compiled code, that is).
It helps C profiency a good deal if one can imagine the process of LALR
parsing (which isn't hard at all).

(You need to be a member of AT91SAM -- send a blank email to AT91SAM-subscribe@yahoogroups.com )
Re: AT91SAM7S USB Woes - Russell Shaw - Feb 2 4:40:20 2008
Paul Curtis wrote:
> Hi,
>
>>> decls look like uses. Again, Wirth had it right in Pascal and even
>> more
>>> correct in Modula-2. But that's a story for another day.
>> "decls look like uses" ? How so? How else would you declare something?
>
> Yes, declarations of variables look like their uses.
>
> declare x as pointer to int: int *x;
> fetch the int pointed to by x: *x;
>
> declare x as a pointer to an array of three ints: int (*x)[3];
> fetch the int in the array pointed to by x: (*x)[0];
>
> declare x as an array of three pointers to ints: int *x[3];
> fetch the int pointed to in the array x: *x[0];
>
> These last two cause more confusion than anything, even amonst C
> programmers. Mismatch the declaration and use and, boy, do sparks fly and
> no compiler will generate an error in the process.
The compiler gives an error if you declare the same thing twice
or forget to declare it at all (unless you use nested {} scopes
which isn't common).
> With prefix "*" and postfix [] it's possible to write horrible declarations
> where you need to work inside out. Same for uses.
>
> Contrast with a clean Modula-2 style that is unambiguous, same three
> declarations and uses:
>
> POINTER TO INTEGER
> x^
>
> POINTER TO ARRAY [0..2] OF INTEGER;
> x^[0]
>
> ARRAY [0..2] OF POINTER TO INTEGER;
> x[0]^
>
> With both you read and write left to right. Simple, clear, efficient. No
> state machine needed to decode these, instantly recognizable, and the
> compiler will bloody well tell you if you get it wrong. No hunting to
> figure out what it means, no need for parentheses to alter binding order.
> Modula-2 is clearly superior in this department.
I really hate the wordiness of pascal languages (especially VHDL and ADA).
http://azure.humbug.org.au/~aj/bwk_on_pascal.html
Turbo pascal was my first language, followed by delphi, C, C++, VHDL, and
various scripting languages.
I'd rather flip burgers if i had to write in anything other than C (for
compiled code, that is).

(You need to be a member of AT91SAM -- send a blank email to AT91SAM-subscribe@yahoogroups.com )
RE: AT91SAM7S USB Woes - Paul Curtis - Feb 2 6:50:48 2008
Hi,
> > These last two cause more confusion than anything, even amonst C
> > programmers. Mismatch the declaration and use and, boy, do sparks
> fly and
> > no compiler will generate an error in the process.
>
> The compiler gives an error if you declare the same thing twice
> or forget to declare it at all (unless you use nested {} scopes
> which isn't common).
That is not what I said. I said if mismatch the definition and use, the
compiler will not generate an error.
void foo(void)
{
int (*x)[3];
int u = (*x)[3];
int v = *(x[3]);
int w = *x[3];
}
Here, the compiler is clueless and does what you write even if it's utter
tosh.
> I'd rather flip burgers if i had to write in anything other than C (for
> compiled code, that is).
That, my man, is indeed utter tosh. I don't believe it for a single moment.
--
Paul Curtis, Rowley Associates Ltd http://www.rowley.co.uk
CrossWorks for ARM, MSP430, AVR, MAXQ, and now Cortex-M3 processors

(You need to be a member of AT91SAM -- send a blank email to AT91SAM-subscribe@yahoogroups.com )
Re: AT91SAM7S USB Woes - Russell Shaw - Feb 2 8:45:56 2008
Paul Curtis wrote:
> Hi,
>
>>> These last two cause more confusion than anything, even amonst C
>>> programmers. Mismatch the declaration and use and, boy, do sparks
>> fly and no compiler will generate an error in the process.
>> The compiler gives an error if you declare the same thing twice
>> or forget to declare it at all (unless you use nested {} scopes
>> which isn't common).
>
> That is not what I said. I said if mismatch the definition and use, the
> compiler will not generate an error.
>
> void foo(void)
> {
> int (*x)[3];
> int u = (*x)[3];
> int v = *(x[3]);
> int w = *x[3];
> }
>
> Here, the compiler is clueless and does what you write even if it's utter
> tosh.
It accepts it only because x has been declared.
That code is perfectly reasonable to me, except that x is uninitialized.
Better to have: int (*x)[3] = NULL;
>> I'd rather flip burgers if i had to write in anything other than C (for
>> compiled code, that is).
>
> That, my man, is indeed utter tosh. I don't believe it for a single moment.
:)

(You need to be a member of AT91SAM -- send a blank email to AT91SAM-subscribe@yahoogroups.com )
RE: AT91SAM7S USB Woes - Paul Curtis - Feb 2 13:18:06 2008
Hi,
> > That is not what I said. I said if mismatch the definition and use,
> the
> > compiler will not generate an error.
> >
> > void foo(void)
> > {
> > int (*x)[3];
> > int u = (*x)[3];
> > int v = *(x[3]);
> > int w = *x[3];
> > }
> >
> > Here, the compiler is clueless and does what you write even if it's
> utter
> > tosh.
>
> It accepts it only because x has been declared.
> That code is perfectly reasonable to me, except that x is
> uninitialized.
> Better to have: int (*x)[3] = NULL;
It accepts it because it knows no better. Putting initialization of x to
one side, EVERY ASSIGNMENT violates the C standard in one way or another.
So no, the code is not perfectly reasonable at all, in fact, it is a gross
error.
--
Paul Curtis, Rowley Associates Ltd http://www.rowley.co.uk
CrossWorks for ARM, MSP430, AVR, MAXQ, and now Cortex-M3 processors

(You need to be a member of AT91SAM -- send a blank email to AT91SAM-subscribe@yahoogroups.com )
Re: AT91SAM7S USB Woes - Russell Shaw - Feb 2 20:30:33 2008
Paul Curtis wrote:
> Hi,
>
>>> That is not what I said. I said if mismatch the definition and use,
>> the
>>> compiler will not generate an error.
>>>
>>> void foo(void)
>>> {
>>> int (*x)[3];
>>> int u = (*x)[3];
>>> int v = *(x[3]);
>>> int w = *x[3];
>>> }
>>>
>>> Here, the compiler is clueless and does what you write even if it's
>> utter tosh.
>> It accepts it only because x has been declared.
>
>> That code is perfectly reasonable to me, except that x is
>> uninitialized.
>> Better to have: int (*x)[3] = NULL;
>
> It accepts it because it knows no better. Putting initialization of x to
> one side, EVERY ASSIGNMENT violates the C standard in one way or another.
> So no, the code is not perfectly reasonable at all, in fact, it is a gross
> error.
How do those assignments violate the C standard?
I didn't know that initializing a local declaration wasn't standard.
I'd rather use gcc that allows that than any compiler that doesn't.
95% of the declarations i do are initialized which makes code safer,
easier to debug, and will bomb out with a runtime error if the code
above was run with x initialized to NULL (on a protected memory system
anyway).

(You need to be a member of AT91SAM -- send a blank email to AT91SAM-subscribe@yahoogroups.com )
Re: AT91SAM7S USB Woes - rako1966 - Feb 3 4:48:02 2008
Hi,
Russel: You are missing the point, and: exactly the situation that you
are missing the point is the prove, that you don't know the (possible)
advantages of pascal or modula (which I don't see either - I like C
despite its obvious problems with error checking, too).
--- In A...@yahoogroups.com, Russell Shaw
wrote:
>
> Paul Curtis wrote:
> >>> That is not what I said. I said if mismatch the definition and use,
> >> the
> >>> compiler will not generate an error.
> >>>
> >>> void foo(void)
> >>> {
> >>> int (*x)[3];
> >>> int u = (*x)[3];
> >>> int v = *(x[3]);
> >>> int w = *x[3];
> >>> }
> >>>
> >>> Here, the compiler is clueless and does what you write even if it's
> >>> utter tosh.
> >>> It accepts it only because x has been declared.
> >
> >> That code is perfectly reasonable to me, except that x is
> >> uninitialized.
> >> Better to have: int (*x)[3] = NULL;
> >
> > It accepts it because it knows no better. Putting initialization
of x to
> > one side, EVERY ASSIGNMENT violates the C standard in one way or
another.
> > So no, the code is not perfectly reasonable at all, in fact, it is
a gross
> > error.
>
> How do those assignments violate the C standard?
1. Paul told you to put the initialization aside - that part is not
the point. BTW: Initializing the pointer to NULL does nothing good to
pauls code.
2. int (*x)[3];
A Pointer to an array of 3 ints (starting with index [0] !)
3. int u = (*x)[3];
Derefence the pointer and get the fourth (!) element from the int
array - obviously a big big fault, since the pointer points to an
array of three elements. pascal/modula would complain the array
overflow, C continues silently. Still, this may not be a violation of
C standard, at all.
4. int v = *(x[3]);
Remember: x is a pointer to an array of three ints, hence x[3] is: Get
a pointer to the fourth arrays of 3 ints. Dereferencing it, yields its
first element. This may be perfectly legal however, provided x indeed
is initialized to point to such an array!
However, for a modula/pascal programmer, this line is in conflict with
the declaration, and pascal/modula will still do the check and may
complain about the wrong usage of the pointer.
This is definitely NOT a violation of C Standard, provided that the
pointer points to an array of arrays of three ints.
5. int w = *x[3];
This may be a bad example, since it is exactly the same as 4. However
it probably proves Pauls point: It is in conflict with the
declaration, looks different from the line above and still means
exactly the same. And You still are required to think about the
question: which one is evaluted first: the [] or the *? According to
Pauls post modula (which I don't know, can't remember pascal) always
evaluates from left to right, so this would not require the programmer
to think about evaluation priorities.
And: C still may give headaches to novice programmers:
In the example above the following could happen:
int z[3];
int (*x)[3] = &z;
A novice programmer would think this code snippet to be perfect. z is
an array of 3 ints, x is a pointer to an array of three ints! Perfect,
isn't it?? Of course we know, it's utter nonsense! In the example we
just need a pointer to int, nothing more. That is,how C was designed.
I second Pauls point, that this still is not obvious. Pascal would
indeed need a decl of a pointer to an array of three ints, which is
more clear - and allows the compiler to check the array boundaries.
Given this example, in Pauls example it may not have been the
programers intention at all, to use the pointer as a pointer to a two
dimensional array, but at a first look it looks perfect. You need to
take a second look (as long as you are not a senior C programmer) to
see the possible flaw. Pascal will help you out.
Note however, this example code still works if we would have declared
an array of pointers to arrays of int ( "int *(x[3])" instead of "int
(*x)[3]" ), but the initialization, the resulting code AND the code
faults (due to the array overflow) would be completely different! Yes,
this may be a flaw in the design of C, and yes, to understand this
difference is a major problem for novice C programmers (it was to me
long ago), and yes, this would be impossible in pascal.
> I didn't know that initializing a local declaration wasn't standard.
>
> I'd rather use gcc that allows that than any compiler that doesn't.
>
> 95% of the declarations i do are initialized which makes code safer,
> easier to debug, and will bomb out with a runtime error if the code
> above was run with x initialized to NULL (on a protected memory system
> anyway).
Local variables are NEVER initialized in C, not even with gcc, just to
clarify what you obviously already knew. Coded initializations of
local variables like "int *x=NULL;" was not even in the standard until
ANSI C. In K&R this line was in error, except when declared static.
I would however never initialize a variable in a MCU, as long as it is
not needed, since this is a complete waste of memory. (Don't flame: at
-O1 gcc usualy get's rid of these initializations, and gcc warns about
possibly uninitialized locals, so this works great either way)
So both of you have had your point, and after all: This small war is
not about AT91SAM at all, so we should end it.
Greetings
Rainer Koch

(You need to be a member of AT91SAM -- send a blank email to AT91SAM-subscribe@yahoogroups.com )Re: Re: AT91SAM7S USB Woes - Russell Shaw - Feb 3 5:17:38 2008
rako1966 wrote:
> Hi,
>
> Russel: You are missing the point, and: exactly the situation that you
> are missing the point is the prove, that you don't know the (possible)
> advantages of pascal or modula (which I don't see either - I like C
> despite its obvious problems with error checking, too).
>
> --- In A...@yahoogroups.com, Russell Shaw
wrote:
>> Paul Curtis wrote:
>>>>> That is not what I said. I said if mismatch the definition and use,
>>>> the
>>>>> compiler will not generate an error.
>>>>>
>>>>> void foo(void)
>>>>> {
>>>>> int (*x)[3];
>>>>> int u = (*x)[3];
>>>>> int v = *(x[3]);
>>>>> int w = *x[3];
>>>>> }
>>>>>
>>>>> Here, the compiler is clueless and does what you write even if it's
>>>>> utter tosh.
>>>>> It accepts it only because x has been declared.
>>>> That code is perfectly reasonable to me, except that x is
>>>> uninitialized.
>>>> Better to have: int (*x)[3] = NULL;
>>> It accepts it because it knows no better. Putting initialization of x to
>>> one side, EVERY ASSIGNMENT violates the C standard in one way or another.
>>> So no, the code is not perfectly reasonable at all, in fact, it is a gross
>>> error.
>> How do those assignments violate the C standard?
>
> 1. Paul told you to put the initialization aside - that part is not
> the point. BTW: Initializing the pointer to NULL does nothing good to
> pauls code.
I was thinking of what that vague question meant for quite a while.
> 2. int (*x)[3];
>
> A Pointer to an array of 3 ints (starting with index [0] !)
>
> 3. int u = (*x)[3];
>
> Derefence the pointer and get the fourth (!) element from the int
> array - obviously a big big fault, since the pointer points to an
> array of three elements.
Oh, is that all. That's just a matter of remembering zero-based counting
which i never have any problem with.
It took a lot of getting used to that from pascal, but after a while you
very rarely make those bugs.
Zero based addressing is very convenient mathematically.
> pascal/modula would complain the array
> overflow, C continues silently. Still, this may not be a violation of
> C standard, at all.
>
> 4. int v = *(x[3]);
>
> Remember: x is a pointer to an array of three ints, hence x[3] is: Get
> a pointer to the fourth arrays of 3 ints. Dereferencing it, yields its
> first element. This may be perfectly legal however, provided x indeed
> is initialized to point to such an array!
> However, for a modula/pascal programmer, this line is in conflict with
> the declaration, and pascal/modula will still do the check and may
> complain about the wrong usage of the pointer.
> This is definitely NOT a violation of C Standard, provided that the
> pointer points to an array of arrays of three ints.
>
> 5. int w = *x[3];
>
> This may be a bad example, since it is exactly the same as 4. However
> it probably proves Pauls point: It is in conflict with the
> declaration, looks different from the line above and still means
> exactly the same. And You still are required to think about the
> question: which one is evaluted first: the [] or the *? According to
> Pauls post modula (which I don't know, can't remember pascal) always
> evaluates from left to right, so this would not require the programmer
> to think about evaluation priorities.
>
> And: C still may give headaches to novice programmers:
> In the example above the following could happen:
>
> int z[3];
> int (*x)[3] = &z;
>
> A novice programmer would think this code snippet to be perfect. z is
> an array of 3 ints, x is a pointer to an array of three ints! Perfect,
> isn't it?? Of course we know, it's utter nonsense! In the example we
> just need a pointer to int, nothing more. That is,how C was designed.
> I second Pauls point, that this still is not obvious. Pascal would
> indeed need a decl of a pointer to an array of three ints, which is
> more clear - and allows the compiler to check the array boundaries.
>
> Given this example, in Pauls example it may not have been the
> programers intention at all, to use the pointer as a pointer to a two
> dimensional array, but at a first look it looks perfect. You need to
> take a second look (as long as you are not a senior C programmer) to
> see the possible flaw. Pascal will help you out.
>
> Note however, this example code still works if we would have declared
> an array of pointers to arrays of int ( "int *(x[3])" instead of "int
> (*x)[3]" ), but the initialization, the resulting code AND the code
> faults (due to the array overflow) would be completely different! Yes,
> this may be a flaw in the design of C, and yes, to understand this
> difference is a major problem for novice C programmers (it was to me
> long ago), and yes, this would be impossible in pascal.
>
>> I didn't know that initializing a local declaration wasn't standard.
>>
>> I'd rather use gcc that allows that than any compiler that doesn't.
>>
>> 95% of the declarations i do are initialized which makes code safer,
>> easier to debug, and will bomb out with a runtime error if the code
>> above was run with x initialized to NULL (on a protected memory system
>> anyway).
>
> Local variables are NEVER initialized in C, not even with gcc, just to
> clarify what you obviously already knew. Coded initializations of
> local variables like "int *x=NULL;" was not even in the standard until
> ANSI C. In K&R this line was in error, except when declared static.
> I would however never initialize a variable in a MCU, as long as it is
> not needed, since this is a complete waste of memory. (Don't flame: at
> -O1 gcc usualy get's rid of these initializations, and gcc warns about
> possibly uninitialized locals, so this works great either way)
>
> So both of you have had your point, and after all: This small war is
> not about AT91SAM at all, so we should end it.
The reason i never get these kinds of bugs is (a) experience, (b) use
macros:
#define LEN 3
int (*x)[LEN];
int u = (*x)[LEN]; //error: never index at LEN, alway upto LEN-1
int u = (*x)[LEN - 1] //right
For arbitrary indexing of the array, it is up to the cleanliness and
discipline of your coding style to avoid overruns (something lacking
in newbies). Safe and obvious:
for(int i = 0; i < LEN; i++) {
int u = (*x)(i);
}
After a while, it's easy to spot these bugs. You'd rarely make this
error though.
Even if you made the error as a typo, testing the code on a pc will
catch the error if you use valgrind (non cpu-specific code).
Developing with crash-n-burn or ICE is a good deal harder to find
these errors. The general pain of developing that way means i test
most generic code on a pc first.
Any newbie can improve. I don't like languages specifically made
for non-programmers like ADA, because it kills the compactness and
flexibility.

(You need to be a member of AT91SAM -- send a blank email to AT91SAM-subscribe@yahoogroups.com )RE: AT91SAM7S USB Woes - Paul Curtis - Feb 3 6:02:31 2008
Russel,
> >>> That is not what I said. I said if mismatch the definition and
> use,
> >> the
> >>> compiler will not generate an error.
> >>>
> >>> void foo(void)
> >>> {
> >>> int (*x)[3];
> >>> int u = (*x)[3];
> >>> int v = *(x[3]);
> >>> int w = *x[3];
> >>> }
> >>>
> >>> Here, the compiler is clueless and does what you write even if it's
> >> utter tosh.
> >> It accepts it only because x has been declared.
> >
> >> That code is perfectly reasonable to me, except that x is
> >> uninitialized.
> >> Better to have: int (*x)[3] = NULL;
> >
> > It accepts it because it knows no better. Putting initialization of
> x to
> > one side, EVERY ASSIGNMENT violates the C standard in one way or
> another.
> > So no, the code is not perfectly reasonable at all, in fact, it is a
> gross
> > error.
>
> How do those assignments violate the C standard?
int u = (*x)[3];
This indexes one beyond the array pointed to by x.
int v = *(x[3]);
This indexes into the non-existent array x; x is a pointer, and only a
pointer, so x[0] is valid and is identical to *x, but x[3] is invalid. x[2]
is invalid. x[1] is invalid. &x[0] and &x[1] are a valid address
expressions by the C standard, but &x[2] is not, nor is &x[-1]. What more
can I say?
int w = *x[3];
Save as that above. Adding parentheses makes no difference.
> I didn't know that initializing a local declaration wasn't standard.
It is standard. That is not the point.
> I'd rather use gcc that allows that than any compiler that doesn't.
Oh dear.
> 95% of the declarations i do are initialized which makes code safer,
> easier to debug, and will bomb out with a runtime error if the code
> above was run with x initialized to NULL (on a protected memory system
> anyway).
I said, put initialisation to one side. It doesn't matter what x is
initialized to, every one is wrong.
-- Paul.

(You need to be a member of AT91SAM -- send a blank email to AT91SAM-subscribe@yahoogroups.com )
Re: AT91SAM7S USB Woes - Russell Shaw - Feb 3 6:16:02 2008
Paul Curtis wrote:
> Russel,
>
>>>>> That is not what I said. I said if mismatch the definition and
>> use,
>>>> the
>>>>> compiler will not generate an error.
>>>>>
>>>>> void foo(void)
>>>>> {
>>>>> int (*x)[3];
>>>>> int u = (*x)[3];
>>>>> int v = *(x[3]);
>>>>> int w = *x[3];
>>>>> }
>>>>>
>>>>> Here, the compiler is clueless and does what you write even if it's
>>>> utter tosh.
>>>> It accepts it only because x has been declared.
>>>> That code is perfectly reasonable to me, except that x is uninitialized.
>>>> Better to have: int (*x)[3] = NULL;
>>> It accepts it because it knows no better. Putting initialization of x to
>>> one side, EVERY ASSIGNMENT violates the C standard in one way or another.
>>> So no, the code is not perfectly reasonable at all, in fact, it is a gross
>>> error.
>> How do those assignments violate the C standard?
>
> int u = (*x)[3];
>
> This indexes one beyond the array pointed to by x.
>
> int v = *(x[3]);
>
> This indexes into the non-existent array x; x is a pointer, and only a
> pointer, so x[0] is valid and is identical to *x, but x[3] is invalid. x[2]
> is invalid. x[1] is invalid. &x[0] and &x[1] are a valid address
> expressions by the C standard, but &x[2] is not, nor is &x[-1]. What more
> can I say?
When i say the code looked ok, it was from the context of the C standard
and those individual lines rather than that obvious overrun error in the
code as a whole.
> int w = *x[3];
>
> Save as that above. Adding parentheses makes no difference.
>
>> I didn't know that initializing a local declaration wasn't standard.
>
> It is standard. That is not the point.
>
>> I'd rather use gcc that allows that than any compiler that doesn't.
>
> Oh dear.
>
>> 95% of the declarations i do are initialized which makes code safer,
>> easier to debug, and will bomb out with a runtime error if the code
>> above was run with x initialized to NULL (on a protected memory system
>> anyway).
>
> I said, put initialisation to one side. It doesn't matter what x is
> initialized to, every one is wrong.

(You need to be a member of AT91SAM -- send a blank email to AT91SAM-subscribe@yahoogroups.com )
RE: Re: AT91SAM7S USB Woes - Paul Curtis - Feb 3 6:33:01 2008
Hi,
> > 2. int (*x)[3];
> >
> > A Pointer to an array of 3 ints (starting with index [0] !)
> >
> > 3. int u = (*x)[3];
> >
> > Derefence the pointer and get the fourth (!) element from the int
> > array - obviously a big big fault, since the pointer points to an
> > array of three elements.
>
> Oh, is that all. That's just a matter of remembering zero-based
> counting which i never have any problem with.
No. As I pointed out, you have obviously demonstrated *exactly* why
programmers have problems because not only have you missed the fact that I'm
indexing beyond the end of an array, you have also missed the absolute
howler in the code. The mistake *everybody* makes at one time or another.
One of the other classics that happen over and over again is the "K&R says
an array is the same as a pointer, right? I mean, I can pass an array to
something that needs a pointer to its elements, ok?"
No, this is not "ok" in the slightest. Arrays and pointers are distinct
objects and have distinct types. Yes, you can index a pointer and arrays
can decay to pointers. But don't ever make the mistake that they are the
same thing.
Let's take this:
void foo (char dst[], char src[]);
void foo (char *dst, char *src);
Both are the same prototype and can be compiled in the same file without
error. You can use [] to mean "an array" and * to mean the same thing.
By extension, in File1.c:
int x[10];
File2.c:
extern int *x; // external array "x" with unknown size
Compiles, links, should work shouldn't it given C treats arrays and pointers
as the same thing? I mean, the prototypes of foo above are identical and
the C compiler doesn't complain. So what's wrong with it?
-- Paul.

(You need to be a member of AT91SAM -- send a blank email to AT91SAM-subscribe@yahoogroups.com )
RE: AT91SAM7S USB Woes - Paul Curtis - Feb 3 6:38:50 2008
Hi,
> > This indexes into the non-existent array x; x is a pointer, and only
> a
> > pointer, so x[0] is valid and is identical to *x, but x[3] is
> invalid. x[2]
> > is invalid. x[1] is invalid. &x[0] and &x[1] are a valid address
> > expressions by the C standard, but &x[2] is not, nor is &x[-1]. What
> more
> > can I say?
>
> When i say the code looked ok, it was from the context of the C
> standard and those individual lines rather than that obvious overrun error
in
> the code as a whole.
There are two classes of error in there; the C compiler and many programmers
cannot diagnose them. If you write in a strictly-typed and enforced
language you don't get that problem. And as for C's insistence that all
arrays start from zero, how arcane is that? Hell, even Algol had
non-zero-based arrays. Algol 68 was a great language, Modula-2 is a great
language, and I really like T as a language. Don't get me started on Java,
that's something for another time.
--
Paul Curtis, Rowley Associates Ltd http://www.rowley.co.uk
CrossWorks for ARM, MSP430, AVR, MAXQ, and now Cortex-M3 processors

(You need to be a member of AT91SAM -- send a blank email to AT91SAM-subscribe@yahoogroups.com )
Re: Re: AT91SAM7S USB Woes - Russell Shaw - Feb 3 6:41:09 2008
Paul Curtis wrote:
> Hi,
>
>>> 2. int (*x)[3];
>>>
>>> A Pointer to an array of 3 ints (starting with index [0] !)
>>>
>>> 3. int u = (*x)[3];
>>>
>>> Derefence the pointer and get the fourth (!) element from the int
>>> array - obviously a big big fault, since the pointer points to an
>>> array of three elements.
>> Oh, is that all. That's just a matter of remembering zero-based
>> counting which i never have any problem with.
>
> No. As I pointed out, you have obviously demonstrated *exactly* why
> programmers have problems because not only have you missed the fact that I'm
> indexing beyond the end of an array, you have also missed the absolute
> howler in the code. The mistake *everybody* makes at one time or another.
I knew that was wrong, but i thought the context of the discussion at that
point was different. Just my contextual thinking that gets undone.
> One of the other classics that happen over and over again is the "K&R says
> an array is the same as a pointer, right? I mean, I can pass an array to
> something that needs a pointer to its elements, ok?"
>
> No, this is not "ok" in the slightest. Arrays and pointers are distinct
> objects and have distinct types. Yes, you can index a pointer and arrays
> can decay to pointers. But don't ever make the mistake that they are the
> same thing.
I used to think that until i read the C faq which everyone should do:
http://c-faq.com/aryptr/index.html
The problems become more evident when passing multidimensional arrays
to functions.
> Let's take this:
>
> void foo (char dst[], char src[]);
> void foo (char *dst, char *src);
>
> Both are the same prototype and can be compiled in the same file without
> error. You can use [] to mean "an array" and * to mean the same thing.
>
> By extension, in File1.c:
>
> int x[10];
>
> File2.c:
>
> extern int *x; // external array "x" with unknown size
>
> Compiles, links, should work shouldn't it given C treats arrays and pointers
> as the same thing? I mean, the prototypes of foo above are identical and
> the C compiler doesn't complain. So what's wrong with it?
When passing arrays to functions, they decay to pointers, but only for
functions.
In file declarations, int *x allocates memory only for the pointer, whereas
int x[10] allocates space for 10 ints with x representing the start of the
array. Obviously there's different type information in both cases so the types
are different. Arrays decay to pointers when passed to functions only as a
convenience.

(You need to be a member of AT91SAM -- send a blank email to AT91SAM-subscribe@yahoogroups.com )
Re: AT91SAM7S USB Woes - Russell Shaw - Feb 3 6:51:15 2008
Paul Curtis wrote:
> Hi,
>
>>> This indexes into the non-existent array x; x is a pointer, and only a
>>> pointer, so x[0] is valid and is identical to *x, but x[3] is invalid. x[2]
>>> is invalid. x[1] is invalid. &x[0] and &x[1] are a valid address
>>> expressions by the C standard, but &x[2] is not, nor is &x[-1]. What more
>>> can I say?
>> When i say the code looked ok, it was from the context of the C
>> standard and those individual lines rather than that obvious overrun error in
>> the code as a whole.
>
> There are two classes of error in there; the C compiler and many programmers
> cannot diagnose them. If you write in a strictly-typed and enforced
> language you don't get that problem. And as for C's insistence that all
> arrays start from zero, how arcane is that? Hell, even Algol had
> non-zero-based arrays. Algol 68 was a great language, Modula-2 is a great
> language, and I really like T as a language. Don't get me started on Java,
> that's something for another time.
I can't find a use for functional languages. Lisp trades flexibility for a
loss of visual syntactic clues. I know lisp basics.
Running everything in a JVM only makes sense for web browsers IMO.
http://www.paulgraham.com/thist.html

(You need to be a member of AT91SAM -- send a blank email to AT91SAM-subscribe@yahoogroups.com )
Re: AT91SAM7S USB Woes - Ralph Hempel - Feb 3 8:43:22 2008
Russell Shaw wrote:
> I can't find a use for functional languages. Lisp trades flexibility for a
> loss of visual syntactic clues. I know lisp basics.
>
> Running everything in a JVM only makes sense for web browsers IMO.
That may be becasue you have tried to write procedural style
code in a functional language :-)
Ralph

(You need to be a member of AT91SAM -- send a blank email to AT91SAM-subscribe@yahoogroups.com )
RE: AT91SAM7S USB Woes - Paul Curtis - Feb 3 11:21:15 2008
Hi,
> I can't find a use for functional languages. Lisp trades flexibility
> for a loss of visual syntactic clues. I know lisp basics.
I find it astonishing that you can dismiss a whole class of languages with
no more than a basic knowledge--Modula-2 and Lisp-like languages such as
Scheme and T. Having programmed and implemented Lisp interpreters and
compilers, I find Lisp one of the easiest languages to get *anything* done
in. Lisp scales easily to parallel execution, not many other languages do
that without inventing new data types like "vector".
--
Paul Curtis, Rowley Associates Ltd http://www.rowley.co.uk
CrossWorks for ARM, MSP430, AVR, MAXQ, and now Cortex-M3 processors

(You need to be a member of AT91SAM -- send a blank email to AT91SAM-subscribe@yahoogroups.com )