RTV forum PL | NewsGroups PL

Problemy z bootloaderem na ATMega128 w WinAVR błędy adresów i linkera

Czy WinAVR radzi sobie z kodem dla ATMega128?

NOWY TEMAT

elektroda NewsGroups Forum Index - Elektronika Polska - Problemy z bootloaderem na ATMega128 w WinAVR błędy adresów i linkera

Dariusz Zolna
Guest

Sat Jan 24, 2009 11:45 pm   



Z bootloaderem przygód ciąg dalszy.
Na ATMega8 wszystko pięknie działa, chcę teraz zrobić podobną rzecz na
ATMega128 i znowu dzieją się jakieś jaja. Bootloader jest duży, ponad
6kB, więc rezerwuję na niego największy możliwy 8kB obszar począwszy od
$00F000. Dla linkera podaję adres początkowy segmentu .text jako
0x1e000, ale w pliku .hex mam :10E00000 a na dodatek pierwsza linia
tego pliku wygląda tak :020000021000EC, czyli że 2 bajty zapisywane są
pod adresem $000000.
Po wgraniu tego pliku przy użyciu AVR Studio, nic się nie dzieje. Fuse
bity ustawione prawidłowo. Jeśli adres startowy ustawię na $00000 to
program działa (choć oczywiście niczego nie programuje, ale wiadomo że
to nie jest jakiś zwis czy błąd w kodzie).
No i teraz zupełnie nie wiem gdzie szukać błędu - w kompilatorze,
linkerze, programatorze czy jeszcze gdzieś.

Dariusz Żołna

Sebastian Bialy
Guest

Sun Jan 25, 2009 7:26 am   



Dariusz Zolna wrote:
Quote:
No i teraz zupełnie nie wiem gdzie szukać błędu - w kompilatorze,
linkerze, programatorze czy jeszcze gdzieś.

Sprawdź:

avr-objdump -h -S prg.elf >prg.lst

Powinno się sporo wyjaśnić.

Dariusz Zolna
Guest

Sun Jan 25, 2009 9:14 am   



Sebastian Bialy pisze:
Quote:
Sprawdź:

avr-objdump -h -S prg.elf >prg.lst

Powinno się sporo wyjaśnić.

Program jest ok, zaczyna się od $1e000 i kończy na $1f762, więc jest we
właściwym miejscu. Wektory przerwań (oprócz wykorzystywanego przeze mnie
TWI pokazują na instrukcję skoku pod $1e000, a pod $1e000 jest skok na
początek programu).
Mam wrażenie, że problem leży jednak w pliku .hex, w którym brakuje
jednej cyfry adresu (nie ma $1e000, jest $e000), no chyba że dla układów
z flashem większym niż 64kB, pliki .hex są jakoś specjalnie obsługiwane.

Dariusz Żołna

Sebastian Bialy
Guest

Sun Jan 25, 2009 1:03 pm   



Dariusz Zolna wrote:
Quote:
Mam wrażenie, że problem leży jednak w pliku .hex, w którym brakuje
jednej cyfry adresu (nie ma $1e000, jest $e000)

A probowałeś wygenerować plik .bin zamiast hex i załadować go?

I po drugie - czy odczyt pamięci z mikrokontrolera daje ten sam plik co
zapis?

Quote:
, no chyba że dla układów
z flashem większym niż 64kB, pliki .hex są jakoś specjalnie obsługiwane.

Nie wiem jak dla narzędzi avr, ale IntelHEX może być 32 bitowy i chyba
taki powinien własnie tu byc.

Guest

Sun Jan 25, 2009 1:45 pm   



On 24 Sty, 23:45, Dariusz Zolna <ans...@usenet.com> wrote:
Quote:
Z bootloaderem przygód ciąg dalszy.
Na ATMega8 wszystko pięknie działa, chcę teraz zrobić podobną rzecz na
ATMega128 i znowu dzieją się jakieś jaja. Bootloader jest duży, ponad
6kB, więc rezerwuję na niego największy możliwy 8kB obszar począwszy od
$00F000. Dla linkera podaję adres początkowy segmentu .text jako
0x1e000,  ale w pliku .hex mam :10E00000 a na dodatek pierwsza linia
tego pliku wygląda tak :020000021000EC, czyli że 2 bajty zapisywane są
pod adresem $000000.

Wszystko jest OK. Wpis :020000021000EC stanowi rozszerzenie
przestrzeni
adresowej bo adresowanie jest 16 bitowe. Proponuję poczytać jak
wygląda
format IntelHEX.
pozdrawiam
Robert Zemła

T.M.F.
Guest

Sun Jan 25, 2009 3:34 pm   



Dariusz Zolna pisze:
Quote:
Z bootloaderem przygód ciąg dalszy.
Na ATMega8 wszystko pięknie działa, chcę teraz zrobić podobną rzecz na
ATMega128 i znowu dzieją się jakieś jaja. Bootloader jest duży, ponad
6kB, więc rezerwuję na niego największy możliwy 8kB obszar począwszy od
$00F000. Dla linkera podaję adres początkowy segmentu .text jako
0x1e000, ale w pliku .hex mam :10E00000 a na dodatek pierwsza linia
tego pliku wygląda tak :020000021000EC, czyli że 2 bajty zapisywane są
pod adresem $000000.

Tak jak poprzednio - nie wiem czy linker nie przyjmuje adresu jako
slowa, a nie bajty.

Quote:
Po wgraniu tego pliku przy użyciu AVR Studio, nic się nie dzieje. Fuse
bity ustawione prawidłowo. Jeśli adres startowy ustawię na $00000 to
program działa (choć oczywiście niczego nie programuje, ale wiadomo że
to nie jest jakiś zwis czy błąd w kodzie).
No i teraz zupełnie nie wiem gdzie szukać błędu - w kompilatorze,
linkerze, programatorze czy jeszcze gdzieś.

Toolchain raczej bym wykluczyl, tyle osob to testowalo, ze szansa, ze
nie wyszlaby do tej pory tak gruba rzecz jest zadna.
Zobacz jak wygladaja wygenerowane pliki .map i .lss. Tam bedziesz mial
dokladnie pokazane co jest pod jakim adresem umieszczone i jak wyglada
wygenerowany kod assemblerowy.
Jesli nie chcesz nam pokazac listingow programu to napisz jakis krotki
programik, ktory produkuje ten sam blad. Wtedy bedzie mozna powiedziec
cos wiecej.

Paweł
Guest

Sun Jan 25, 2009 6:42 pm   



Quote:
na dodatek pierwsza linia
tego pliku wygląda tak :020000021000EC, czyli że 2 bajty zapisywane są
pod adresem $000000.

Nie
To jest extended segment address record.

Paweł

Dariusz Zolna
Guest

Mon Jan 26, 2009 1:12 pm   



T.M.F. pisze:
Quote:
Tak jak poprzednio - nie wiem czy linker nie przyjmuje adresu jako
slowa, a nie bajty.

Jako bajty. Ale ten trop też sprawdzałem, program wtedy się odpali,a le
nie jako bootloader i co oczywiste nie zapisuje pamięci.



Quote:
Toolchain raczej bym wykluczyl, tyle osob to testowalo, ze szansa, ze
nie wyszlaby do tej pory tak gruba rzecz jest zadna.
Zobacz jak wygladaja wygenerowane pliki .map i .lss. Tam bedziesz mial
dokladnie pokazane co jest pod jakim adresem umieszczone i jak wyglada
wygenerowany kod assemblerowy.

Oglądałem i wszystko jest ok.

Quote:
Jesli nie chcesz nam pokazac listingow programu to napisz jakis krotki
programik, ktory produkuje ten sam blad. Wtedy bedzie mozna powiedziec
cos wiecej.

Z pokazaniem kodu jest tylko jeden problem - jest za długi żeby tu
wklejać. Ale żeby pokazać, że jest ok, wkleję co istotniejsze fragmenty.

bootloader.elf: file format elf32-avr

Sections:
Idx Name Size VMA LMA File off Algn
0 .data 00000004 00800100 0001f764 000017f8 2**0
CONTENTS, ALLOC, LOAD, DATA
1 .text 00001764 0001e000 0001e000 00000094 2**1
CONTENTS, ALLOC, LOAD, READONLY, CODE
2 .bss 00000452 00800104 00800104 000017fc 2**0

[...]

0001e000 <__vectors>:
1e000: 0c 94 a4 f1 jmp 0x1e348 ; 0x1e348 <__ctors_end>
1e004: 0c 94 c4 f1 jmp 0x1e388 ; 0x1e388 <__bad_interrupt>
1e008: 0c 94 c4 f1 jmp 0x1e388 ; 0x1e388 <__bad_interrupt>

[...]

0001e348 <__ctors_end>:
1e348: 11 24 eor r1, r1
1e34a: 1f be out 0x3f, r1 ; 63
[...]
1e380: 0e 94 14 f6 call 0x1ec28 ; 0x1ec28 <main>
1e384: 0c 94 b0 fb jmp 0x1f760 ; 0x1f760 <_exit>

0001e388 <__bad_interrupt>:
1e388: 0c 94 00 f0 jmp 0x1e000 ; 0x1e000 <__vectors>

[...]

nt main( void )
{
1ec28: 1f 93 push r17
// u16 i;

cli();
1ec2a: f8 94 cli
TIMSK = 0; // disable timer interrupts
1ec2c: 17 be out 0x37, r1 ; 55

/* Enable change of interrupt vectors */
MCUCR = (1<<IVCE);
1ec2e: 11 e0 ldi r17, 0x01 ; 1
1ec30: 15 bf out 0x35, r17 ; 53
/* Move interrupts to boot flash section */
MCUCR = (1<<IVSEL);
1ec32: 82 e0 ldi r24, 0x02 ; 2
1ec34: 85 bf out 0x35, r24 ; 5

[...]


Pliki .hex (zapisany i odczytany) wyglądają ok.
A może jest coś czym musi się różnić bootloader na ATMega128 od tego dla
ATMega8?

Dariusz Żołna

Marcin Stanisz
Guest

Mon Jan 26, 2009 2:40 pm   



Dnia Sat, 24 Jan 2009 23:45:50 +0100, Dariusz Zolna napisał(a):
Quote:
Fuse bity ustawione prawidłowo.

Nieśmiało spytam, bo nie śledziłem - M103C = 1 ?

Pozdrawiam
--
Marcin Stanisz

"A lie will go round the world before the truth has got its boots on"
Terry Pratchett, "Truth"

Dariusz Zolna
Guest

Mon Jan 26, 2009 3:00 pm   



Marcin Stanisz pisze:
Quote:
Nieśmiało spytam, bo nie śledziłem - M103C = 1 ?

Nie. Ale właśnie się wyjaśniło.
Kompilator nie ostrzega, że pgm_read_byte() działa tylko z krótkimi
adresami, bootloader siedzi powyżej 64k, a ja wszystkie dane typu
teksty/grafika trzymam we flash, no i jak tylko program dochodził do
miejsca, w którym powinien wyświetlić testowy napis, procek się resetował.
No i jak zwykle nie tam gdzie szukałem :)

Dariusz Żołna

Adam Dybkowski
Guest

Tue Jan 27, 2009 1:22 am   



Dariusz Zolna pisze:

Quote:
Nie. Ale właśnie się wyjaśniło.
Kompilator nie ostrzega, że pgm_read_byte() działa tylko z krótkimi
adresami, bootloader siedzi powyżej 64k, a ja wszystkie dane typu
teksty/grafika trzymam we flash, no i jak tylko program dochodził do
miejsca, w którym powinien wyświetlić testowy napis, procek się resetował.
No i jak zwykle nie tam gdzie szukałem Smile

No to pozostaje korzystać z pgm_read_byte_far() i podobnych. Uważaj też
na funkcje typu strcpy_P, printf_P, memcpy_P itd - nie zadziałają bo
trzeba im podać wskaźniki 16- a nie 32-bitowe. Podobnie bez dodatkowego
"obejścia" nie zadziałają wskaźniki na funkcje, używane np. w tablicach
skoków. Ot taka "zaleta" dużej pamięci w procku bądź co bądź
8/16-bitowym. Przerabiałem to ostatnio w zdwojonej formie walcząc z
jeszcze większym ATmega2561.

--
Adam Dybkowski
http://dybkowski.net/

Uwaga: przed wysłaniem do mnie maila usuń cyfry z adresu.

Dariusz Zolna
Guest

Tue Jan 27, 2009 10:08 am   



Adam Dybkowski pisze:
Quote:
No to pozostaje korzystać z pgm_read_byte_far() i podobnych. Uważaj też
na funkcje typu strcpy_P, printf_P, memcpy_P itd - nie zadziałają bo
trzeba im podać wskaźniki 16- a nie 32-bitowe. Podobnie bez dodatkowego
"obejścia" nie zadziałają wskaźniki na funkcje, używane np. w tablicach
skoków. Ot taka "zaleta" dużej pamięci w procku bądź co bądź
8/16-bitowym. Przerabiałem to ostatnio w zdwojonej formie walcząc z
jeszcze większym ATmega2561.

Tak, już napisałem swoje wersje tych wszystkich funkcji (przynajmniej
tych, które używam). Szkoda tylko, że kompilator nie przypomina o tym.
A właśnie, jak zrobić wskaźniki do funkcji w tablicach? Wprawdzie teraz
nie korzystam z tego, ale może się przydać na przyszłość. Dla wskaźników
w parametrach funkcji mam zrobione makro (choć też troche upierdliwe w
użyciu, bo stringi muszę teraz mieć ponazywane, a nie umieszczone jako
PSTR("...") bezpośrednio w wywołaniu funkcji).

Dariusz Żołna

T.M.F.
Guest

Tue Jan 27, 2009 4:10 pm   



Quote:
No to pozostaje korzystać z pgm_read_byte_far() i podobnych. Uważaj też
na funkcje typu strcpy_P, printf_P, memcpy_P itd - nie zadziałają bo
trzeba im podać wskaźniki 16- a nie 32-bitowe. Podobnie bez dodatkowego
"obejścia" nie zadziałają wskaźniki na funkcje, używane np. w tablicach
skoków. Ot taka "zaleta" dużej pamięci w procku bądź co bądź
8/16-bitowym. Przerabiałem to ostatnio w zdwojonej formie walcząc z
jeszcze większym ATmega2561.

Co do wskaznikow na funkcje to nie wydaje mi sie, zeby w ATMega128 byl z
tym problem. CALL wykorzystuje adres slowa, czyli w 16 bitach moze
skakac po calym 128 kB obszarze. Problem zaczyna sie w ATMega256.
Wewnetrzne tabele skokow generowane przez gcc odbywaja sie poprzez ICALL
i rejestr Z, czyli tez maja mozliwosc skoku po calych 128kB.
Niestety w gcc nie ma zaimplementowanych modeli pamieci, implementacja
24-bitowych wskaznikow ze wzgledu na strukture gcc tez jest trudna, a
32-bitowe to marnotrawstwo. Ale widze, ze powoli jednak rozwoj avr-gcc
idzie w kierunku modeli pamieci i bedziemy mieli cos znane z czasow
Borlanda i 80286.

T.M.F.
Guest

Tue Jan 27, 2009 4:36 pm   



Dariusz Zolna pisze:
Quote:
Adam Dybkowski pisze:
No to pozostaje korzystać z pgm_read_byte_far() i podobnych. Uważaj
też na funkcje typu strcpy_P, printf_P, memcpy_P itd - nie zadziałają
bo trzeba im podać wskaźniki 16- a nie 32-bitowe. Podobnie bez
dodatkowego "obejścia" nie zadziałają wskaźniki na funkcje, używane
np. w tablicach skoków. Ot taka "zaleta" dużej pamięci w procku bądź
co bądź 8/16-bitowym. Przerabiałem to ostatnio w zdwojonej formie
walcząc z jeszcze większym ATmega2561.

Tak, już napisałem swoje wersje tych wszystkich funkcji (przynajmniej
tych, które używam). Szkoda tylko, że kompilator nie przypomina o tym.

Nie ma jak. Zobacz jak wyglada definicja tych funkcji. Jedyna mozliwosc
to wywalanie ostrzezenia przez sama biblioteke przy wywolywaniu ich na
procesorach z >64kB FLASH. Co zreszta ma maly sens, bo gcc domyslnie
umieszcza stale na poczatku programu, czyli dopoki one nie przekrocza
64kB korzystanie z wersji near tych funkcji jest zupelnie ok. Z kolei
wersje far sa bezpieczne (chociaz nie wiem czy dzialaja na procesorach
do 64kB FLASH), ale czasochlonniejsze i FLASHochlonniejsze.
Natomiast jesli korzystales z wersji near, a wskaznik miales
zadeklarowany prawidlowo jako 32-bitowy to kompilator musial wywalic
ostrzezenie (chyba, ze je blokujesz). Tak czy siak, winny byles ty :)

Quote:
A właśnie, jak zrobić wskaźniki do funkcji w tablicach? Wprawdzie teraz
nie korzystam z tego, ale może się przydać na przyszłość. Dla wskaźników
w parametrach funkcji mam zrobione makro (choć też troche upierdliwe w
użyciu, bo stringi muszę teraz mieć ponazywane, a nie umieszczone jako
PSTR("...") bezpośrednio w wywołaniu funkcji).

Np. tak:
const FuncPtr FuncPtrTable[] PROGMEM=
{f1, f2, f3};

I wywolanie:
FPtr=(FuncPtr)pgm_read_word(&FuncPtrTable[funcno]);

*FPtr();

BTW. A propos twojego bootloadera. Piszesz, ze jest strasznie dlugi.
Wiesz, ze w tej sekcji musi byc tylko maly fragment wykonujacy SPM,
raptem pare bajtow, cala reszta moze byc w normalnej pamieci, co
ogranicza rozmiar bootloadera.

elektroda NewsGroups Forum Index - Elektronika Polska - Problemy z bootloaderem na ATMega128 w WinAVR błędy adresów i linkera

NOWY TEMAT

Regulamin - Zasady uzytkowania Polityka prywatnosci Kontakt RTV map News map