Artur
Guest
Tue Jun 05, 2007 1:45 pm
Dla uC ARM7 i gcc.
Jest np. cos takiego:
typedef struct{
unsigned short a;
unsigned short b;
}struktura;
struktura * st;
char * buff = (char*)malloc(100);
memcpy(buff,"to sa jakies dane",13);
st = (struktura*)(buff+13);
st->a = 0x0006;
Problem polega na tym, że za każdym razem, gdy struktura jest przesunieta w
buforze o nieparzysta liczbe bajtow starszy bajt zmiennej a struktury
zachodzi na ostatni bajt danych wczesniej zapisanych.
Nie wiem czemu tak jest, bo program po skompilowaniu wyglada dobrze, st->a
wypada tam gdzie powinno, ale procesor wykonuje to tak, że zapisuje do
pamieci o jeden bajt wyzej. Moze wie ktos z czego to wynika i jak problem
rozwiazac bo ja juz nie mam pomyslow. Napisalem dokladnie to samo w MS
Visual C++ na PC i tam jest ok.
--
Artur
Mister
Guest
Tue Jun 05, 2007 1:58 pm
Artur
Guest
Tue Jun 05, 2007 3:00 pm
Użytkownik "Mister" <noweprojekty@wp.pl> napisał w wiadomości
news:f43muo$g2u$1@nemesis.news.tpi.pl...
[quote:fb2a5203a8]rozwiazac bo ja juz nie mam pomyslow. Napisalem dokladnie to samo w MS
Visual C++ na PC i tam jest ok.
Klasyka...
A packed nie pomaga?
http://sig9.com/articles/gcc-packed-structures
Nie w tym problem. Wyglada na to, ze np. zapis strh r1,[r0,#1] jest[/quote:fb2a5203a8]
wyrownywany do strh r1,[r0],
podobnie np. str r1,[r0,#3] daje str r1,[r0].
Wlasnie strh generuje kompilator w moim przypadku i stad to przesuniecie.
Dziwne, ze nie uwzglednia tego.
--
Artur
Adam Dybkowski
Guest
Thu Jun 07, 2007 10:04 pm
Artur pisze:
Quote:
Dla uC ARM7 i gcc.
[...]
Problem polega na tym, że za każdym razem, gdy struktura jest
przesunieta w buforze o nieparzysta liczbe bajtow starszy bajt zmiennej
a struktury zachodzi na ostatni bajt danych wczesniej zapisanych.
Zdecydowana większość procesorów z jądrem ARM7TDMI nie może zapisać lub
odczytać niewyrównanej danej do/z pamięci. Czyli słowa 32-bitowe muszą
być zawsze umieszczone pod adresem z zerowymi 2 najmłodszymi bitami,
słowa 16-bitowe pod adresem z wyzerowanym najmłodszym bitem
(parzystymi). Próba dostępu pod niewyrównany adres kończy się wyjątkiem.
Kompilator próbuje temu zaradzić (tam gdzie może) i odpowiednio rozpycha
struktury. Na przykład struktura:
struct
{
unsigned char a;
unsigned long b;
}
zajmie 8 bajtów, bo pole b musi być wyrównane do wielokrotności 4 bajtów
licząc od początku struktury. Oczywiście można wymusić dostęp do
dowolnego adresu przez rzutowanie i inne zabiegi, ale skończy się on
wyjątkiem (np. w AT91SAM7S256 czy AT91RM9200). Nie wiem, jakiego używasz
ARMa, w którym nie dostajesz wyjątku tylko błędne działanie programu.
--
Adam Dybkowski
http://www.amwaw.edu.pl/~adybkows/
Uwaga: przed wysłaniem do mnie maila usuń cyfry z adresu.
Waldemar
Guest
Thu Jun 07, 2007 10:19 pm
Adam Dybkowski schrieb:
Quote:
Artur pisze:
Dla uC ARM7 i gcc.
[...]
Problem polega na tym, że za każdym razem, gdy struktura jest
przesunieta w buforze o nieparzysta liczbe bajtow starszy bajt
zmiennej a struktury zachodzi na ostatni bajt danych wczesniej
zapisanych.
Zdecydowana większość procesorów z jądrem ARM7TDMI nie może zapisać lub
odczytać niewyrównanej danej do/z pamięci. Czyli słowa 32-bitowe muszą
być zawsze umieszczone pod adresem z zerowymi 2 najmłodszymi bitami,
słowa 16-bitowe pod adresem z wyzerowanym najmłodszym bitem
(parzystymi). Próba dostępu pod niewyrównany adres kończy się wyjątkiem.
Kompilator próbuje temu zaradzić (tam gdzie może) i odpowiednio rozpycha
struktury. Na przykład struktura:
struct
{
unsigned char a;
unsigned long b;
}
zajmie 8 bajtów, bo pole b musi być wyrównane do wielokrotności 4 bajtów
licząc od początku struktury. Oczywiście można wymusić dostęp do
dowolnego adresu przez rzutowanie i inne zabiegi, ale skończy się on
wyjątkiem (np. w AT91SAM7S256 czy AT91RM9200). Nie wiem, jakiego używasz
ARMa, w którym nie dostajesz wyjątku tylko błędne działanie programu.
czyli dupa nie kompilator. Kompilator powinien, w przypadku użycia
packed structure przerobić kod na mało efektywny, ale prawidłowy kod
dostępu. Znaczy czytanie słowa i dostęp do bajtu/uint16 itd. Przy
wpisywaniu tak samo: czytaj słowo, wpisz bajt na odpowiednie miejsce,
wpisz spowrotem słowo.
Waldek
Adam Dybkowski
Guest
Fri Jun 08, 2007 12:23 am
Waldemar pisze:
Quote:
Kompilator próbuje temu zaradzić (tam gdzie może) i odpowiednio
rozpycha struktury. Na przykład struktura:
struct
{
unsigned char a;
unsigned long b;
}
zajmie 8 bajtów, bo pole b musi być wyrównane do wielokrotności 4
bajtów licząc od początku struktury. Oczywiście można wymusić dostęp
do dowolnego adresu przez rzutowanie i inne zabiegi, ale skończy się
on wyjątkiem (np. w AT91SAM7S256 czy AT91RM9200). Nie wiem, jakiego
używasz ARMa, w którym nie dostajesz wyjątku tylko błędne działanie
programu.
czyli dupa nie kompilator. Kompilator powinien, w przypadku użycia
packed structure przerobić kod na mało efektywny, ale prawidłowy kod
dostępu. Znaczy czytanie słowa i dostęp do bajtu/uint16 itd. Przy
wpisywaniu tak samo: czytaj słowo, wpisz bajt na odpowiednie miejsce,
wpisz spowrotem słowo.
Nie próbowałem dodawać atrybutu 'packed'. Napisałem w jaki sposób
kompilator zachowuje się domyślnie (arm-elf-gcc 3.4.3).
--
Adam Dybkowski
http://www.amwaw.edu.pl/~adybkows/
Uwaga: przed wysłaniem do mnie maila usuń cyfry z adresu.