Follow Slashdot blog updates by subscribing to our blog RSS feed

 



Forgot your password?
typodupeerror
×
User Journal

Journal Alioth's Journal: [avr] Annoyances

Well, gcc-avr has been trying hard to annoy me all day: firstly, the optimizer seems to be rather over-zealous, optimizing away entire code blocks it thinks does nothing (but which in fact has a profound effect on a routine driven by a timer interrupt). Declaring the variables as 'volatile' as suggested by the documentation had no effect. Putting a useless function call into the code block made it work, or turning optimization off made it work. There are probably some subtleties that I'm missing (given the maturity of the compiler, and the cluelessness of myself).

There also seems to be some oddities with pointer arithmetic.

Basically, the code had to become a bit more complicated. The interrupt routine that picks up the byte coming off the SPI interrupt must be fast. Putting the state machine (that figures out what the host computer is asking the AVR to do) into the interrupt service routine is a non-starter - it'd make the ISR far too slow. So the ISR writes to a buffer, and code elsewhere reads the buffer at its leisure. So long as the code that figures out what to do with the buffer doesn't get more than 8 bytes behind (i.e. the size of the buffer), it can be pretty slow. (Given the biggest command string will be 7 bytes, it'd have to be glacially slow!)

Something seemed to be seriously buggering up pointer arithmetic, though (the same concepts worked perfectly using array indexes). For instance:

while(rxptr > readptr)
{
      if(*readptr == '...')

wouldn't work (the while loop would never be entered)

while(rxidx > readidx)
{
      if(rxbuf[readidx] == '...')

would work fine. Conceptually, both pieces of code do the same thing. The first example, the while loop would never run at all, even though rxptr really was greater than readptr, the condition would never evaluate true. It was quite bizarre.

So in the end, I wrote the circular buffer code using array indices.

It's not the first time I've found C compilers for small architectures to be very quirky - zcc (the Z80 C compiler) has a whole raft of odd quirks waiting to catch you out.

Even with the circular buffer code, the AVR receiver wasn't fast enough to keep up with a 6MHz Z80 throwing data at it. The AVR has an internal clock, the default speed being 1MHz. Gloomily, I thought I'd need to use an external crystal (and I already want to use those I/O pins for something else, so it'd bork my design up), but going through the fuse bits section of the ATtiny2313 datasheet revealed that actually the internal clock is 8MHz, but by default, the fuse bits set a divide-by-8 prescaler. (Fuse bits are just configuration bits in EEPROM, they aren't actually fuses any more). Setting the fuse bits to turn off the prescaler made it plenty fast enough.

This discussion has been archived. No new comments can be posted.

[avr] Annoyances

Comments Filter:

The difficult we do today; the impossible takes a little longer.

Working...