AVR + GCC + EEPROM = problem...

Aug 21, 2003 5 Replies

Witam,



Mam zaadeklarowana w programie zmienna: uint16_t ee_delay_period __attribute__ ((section(".eeprom"))) = 0x3000;



Potem mam taka linijke: _delay_loop_2( eeprom_read_word( adres_ale_jak ) );



Jak podac argument dla ``eeprom_read_word'' prawidlowo, aby wskazywal na ``ee_delay_period'' dokladnie tak, jak zostala ona wlozona przez linker (czy inne ustrojstwo). Raczej zakladam, ze nie wiadomo w momencie kompilacji, jaki jest jej adres, bo mogly pojawic sie inne zmienne wczesniej, albo cos zostalo zoptymalizowane... A moze jest sposob, aby z eepromu wartosc zostala zmirorrowana w ramie podczas inicjalizacji. Zaznaczam, ze chodzi mi o ktorys blok wykonany przed ``main()'', a wsadzany przez kompiulator automatycznie (jesli cos takiego istnieje).



TIA


Deklaracja powinna wygl±daæ tak: const uint16_t ee_delay_period __attribute__ ((section(".eeprom"))) = 0x3000;

a u¿ycie jak tak jak ka¿dej innej zmiennej w C:

_delay_loop_2( eeprom_read_word( &ee_delay_period ) );

Po to siê u¿ywa C, ¿eby takimi "duperelami" jak adresy bezwzglêde nie zaprz±taæ sobie g³oowy.

Pozdrawiam,

Artur Lipowski

No wlasnie o to chodzi, ze tak nie pojdzie... Ponizej zamieszczam fragment kodu w C i to co wygenerowal GCC. Zaznaczylem miejsce wywolania ``eeprom_read_word'' i przekazany parametr nijak ma sie do adresu 0x10 (taki specjalnie zadeklarowalem, zeby byl nadany dla tej zmiennej w EEPROM-ie).

/* * EEPROM Locations */

uint16_t ee_delay_period __attribute__ ((section(".eeprom=0x10"))) = 0x3000;

/* . . . */

void main( void ) { uint8_t value = 1; direction_t direction = UP;

while( 1 ) { _delay_loop_2( eeprom_read_word( &ee_delay_period ) );

/* . . . */

00000058 : 58: cf ed ldi r28, 0xDF ; 223 5a: d0 e0 ldi r29, 0x00 ; 0 5c: de bf out 0x3e, r29 ; 62 5e: cd bf out 0x3d, r28 ; 61 60: c1 e0 ldi r28, 0x01 ; 1 62: ff 24 eor r15, r15

; TUTAJ JEST WYWOLANIE FUNKCJI ``eeprom_read_word''

64: 80 e0 ldi r24, 0x00 ; 0

; POWINNO BYC ; 64: 80 e0 ldi r24, 0x10 ; 16

66: 90 e0 ldi r25, 0x00 ; 0 68: 18 d0 rcall .+48 ; 0x9a

; . . .

0000009a :

; . . .

b2: 08 95 ret

Pozdrawiam

Roland

... A gdzie i jak to zadeklarowa³e¶?

BTW> A po co deklarowa³e¶ konkretny adres w EEPROM-ie? Tak na szybko to trudno mi znale¼æ zastosowanie dla takiego czego¶.

Pozdrawiam,

Artur Lipowski

No ale jak zadeklarowa³e¶ aby ta zmienna by³a pod adresem 0x10? Podziel sie wiedz± >:->

Widzê, ¿e chyba mylisz warto¶æ w EEPROM-ie z adresem w EEPROM-ie. Deklaracja w Twoim programie mówi o pocz±tkowej warto¶ci zmiennej, anie o jej adresie - wszystko zgodnie ze standardem jêzyka C.

Mo¿e nie zauwa¿y³e¶, ale kompilator prawid³owo wygenerowa³ kod, bo Twoja zmienna jest pod adresem 0 i taki adres przekaza³ do funkcji eeprom_read_word.

BTW> staraj siê nie umieszczac danych w EEPROM-ie AVR-a pod adresem 0.

Pozdrawiam,

Artur Lipowski

tez

Zamieszczam caly kod: Zwroc uwage, ze zapis ".eeprom=0x10" lokuje pod zadanym adresem 0x10

#include #include #include #include #include #include

/* * EEPROM Locations */

/*** zapis ".eeprom=0x10" lokuje pod zadanum adresem 0x10 ***/

uint16_t ee_delay_period __attribute__ ((section(".eeprom=0x10"))) = 0x3000;

/* * Types */

typedef enum { UP, DOWN } direction_t ;

/* * Function prototypes */

void main( void );

void init_system( void ) __attribute__ ((naked)) \ __attribute__ ((section(".init8")));

void main( void ) { uint8_t value = 1; direction_t direction = UP;

while( 1 ) { _delay_loop_2( eeprom_read_word( &ee_delay_period ) ); outb( OCR1AL, value ); switch( direction ) { case UP : if( ++value == 0xFF ) direction = DOWN; break;

case DOWN : if( !--value ) direction = UP; break;

default : break; } /* switch( ... ) */ } /* while( 1 ) ... */ } /* main( void ) */

void init_system( void ) { /* Timer #1 PWM Mode Setup */ outb( TCCR1A, (1 > testach zawsze jest podejrzane, bo ciezko jest stwierdzic co tak na prawde

Mysle, ze jednak dobrze rozumuje... Zwlaszcza jak popatrzysz na asma, to jest to logiczne. Do rejestrow r25:r24 lokuje sie adres komorki EEPROM, ktora chce sie odczytac i wywoluje procedure odczytu. Przytocze ja rowniez, aby bylo jasniej. To jest oczywiscie kod wygenerowany przez kompilator!

0000009a : 9a: e1 99 sbic 0x1c, 1 ; 28 9c: fe cf rjmp .-4 ; 0x9a 9e: 9f bb out 0x1f, r25 ; 31 a0: 8e bb out 0x1e, r24 ; 30 a2: e0 9a sbi 0x1c, 0 ; 28 a4: 01 96 adiw r24, 0x01 ; 1 a6: 0d b2 in r0, 0x1d ; 29 a8: 9f bb out 0x1f, r25 ; 31 aa: 8e bb out 0x1e, r24 ; 30 ac: e0 9a sbi 0x1c, 0 ; 28 ae: 80 2d mov r24, r0 b0: 9d b3 in r25, 0x1d ; 29 b2: 08 95 ret

Wlasnie, ze jest pod adresem 0x10. Chyba, ze jestem slepy... Wtedy prosze mi wybaczyc ;-) Przytaczam kod do EEPROM-a:

:020000000030CE :00000001FF

Moze jednak sie myle???

No niby tak, ale oni to dawno powinni fixnac.

Rowniez

Roland

Join the Discussion

Have something to add? Share your thoughts — no account required.

Didn't find your answer?

Ask the community — no account required