avr-gcc-list
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [avr-gcc-list] Data Array alignment


From: Ned Konz
Subject: Re: [avr-gcc-list] Data Array alignment
Date: Mon, 05 Jun 2006 09:16:25 -0700
User-agent: Thunderbird 1.5.0.4 (Macintosh/20060530)

Trampas wrote:
Ok, I know somewhere there is a manual where this information exists, but I
have not found it. I am using a buffer in an ISR
#define BUFF_SIZE 0x1F
UINT8 Data[BUFF_SIZE];

Actually, that should be BUFF_SIZE+1 (that is, indexes from 0 to 0x1f would require a buffer that's 0x20 long). Better to say:

#define BUFF_SIZE 0x20
#define BUFF_MASK (BUFF_SIZE-1)

and then use BUFF_MASK to and with.

volatile UINT8 Read;
volatile UINT8 Write;

ISR(xxx)
{
        //OK to over write if not read in time
        Data[Write++]=mydata;
Write=Write & BUFF_SIZE; }

Void Data_Sink()
{
        If (Read!=Write)
        {
                Mydata=Data[Read++];
                Read=Read & BUFF_SIZE;
        }
}

I was wondering if someone had a clever way of speeding this up, by maybe
aligning the data buffer in memory and using pointers?

If you're willing to use assembly language, and a 256-byte buffer aligned so that it starts at xx00, you could maybe shave a cycle or two. Remember too that code like the above *will* use pointers (that is, the X, Y, or Z registers), at least at the assembly level.

To do something similar in C, you can tell the loader to place your buffer at a specific address (starting at a BUFF_SIZE boundary) and then use the section attribute:


// compile with
// avr-gcc -mmcu=atmega128 -g -std=c99 -Os -Wa,-ahlds=buftest.lst -Wl,--section-start,mybuffer=0x801000,-Tdata,0x801020 -o buftest.elf buftest.c
//      avr-objdump -S buftest.elf > buftest.lss

#include <avr/io.h>
#include <avr/interrupt.h>

#define BUFF_SIZE 0x20
#define BUFF_MASK (BUFF_SIZE-1)


// must initialize it!
volatile uint8_t myBuffer[BUFF_SIZE] __attribute__((section ("mybuffer"))) = { 0 };

typedef union { uint8_t *cp; uint8_t b[2]; } nvbufPtr;
typedef union { volatile uint8_t *cp; uint8_t b[2]; } vbufPtr;

nvbufPtr writePtr = { .cp = (uint8_t*)myBuffer };
vbufPtr readPtr = { .cp = myBuffer };

ISR(USART0_RX_vect)
{
        *writePtr.cp = UDR0;
        writePtr.b[1] = (writePtr.b[1] + 1) & BUFF_MASK;
}

int main(void)
{
        for (;;)
        {
                uint8_t c = *readPtr.cp;
                readPtr.b[1] = (readPtr.b[1] + 1) & BUFF_MASK;
                UDR0 = c;       // silly!
        }
}



Which results in not-too-bad code:


ISR(USART0_RX_vect)
{
  ca:   1f 92           push    r1
  cc:   0f 92           push    r0
  ce:   0f b6           in      r0, 0x3f        ; 63
  d0:   0f 92           push    r0
  d2:   11 24           eor     r1, r1
  d4:   8f 93           push    r24
  d6:   ef 93           push    r30
  d8:   ff 93           push    r31
        *writePtr.cp = UDR0;
  da:   e0 91 00 01     lds     r30, 0x0100
  de:   f0 91 01 01     lds     r31, 0x0101
  e2:   8c b1           in      r24, 0x0c       ; 12
  e4:   80 83           st      Z, r24
        writePtr.b[1] = (writePtr.b[1] + 1) & BUFF_MASK;
  e6:   80 91 01 01     lds     r24, 0x0101
  ea:   8f 5f           subi    r24, 0xFF       ; 255
  ec:   8f 71           andi    r24, 0x1F       ; 31
  ee:   80 93 01 01     sts     0x0101, r24
  f2:   ff 91           pop     r31
  f4:   ef 91           pop     r30
  f6:   8f 91           pop     r24
  f8:   0f 90           pop     r0
  fa:   0f be           out     0x3f, r0        ; 63
  fc:   0f 90           pop     r0
  fe:   1f 90           pop     r1
 100:   18 95           reti

00000102 <main>:
}

int main(void)
{
 102:   cf ef           ldi     r28, 0xFF       ; 255
 104:   d0 e1           ldi     r29, 0x10       ; 16
 106:   de bf           out     0x3e, r29       ; 62
 108:   cd bf           out     0x3d, r28       ; 61
        for (;;)
        {
                uint8_t c = *readPtr.cp;
 10a:   e0 91 02 01     lds     r30, 0x0102
 10e:   f0 91 03 01     lds     r31, 0x0103
 112:   90 81           ld      r25, Z
                readPtr.b[1] = (readPtr.b[1] + 1) & BUFF_MASK;
 114:   80 91 03 01     lds     r24, 0x0103
 118:   8f 5f           subi    r24, 0xFF       ; 255
 11a:   8f 71           andi    r24, 0x1F       ; 31
 11c:   80 93 03 01     sts     0x0103, r24
                UDR0 = c;       // silly!
 120:   9c b9           out     0x0c, r25       ; 12
 122:   f3 cf           rjmp    .-26            ; 0x10a <main+0x8>



--
Ned Konz
address@hidden
http://bike-nomad.com




reply via email to

[Prev in Thread] Current Thread [Next in Thread]