[Top][All Lists]
[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
Re: [avr-gcc-list] Data Array alignment,
Ned Konz <=
Re: [avr-gcc-list] Data Array alignment, Dmitry K., 2006/06/05