[ARM] Obsługa peryferiów poprzez API (wskazniki do struktury)

Do you have a question? Post it now! No Registration Necessary

Translate This Thread From Polish to

Threaded View
CzeB6%E6.
Mamy np uC STM32. DostEA%p do portF3%w np ustawienie jakiegoB6%
wyprowadzenia moBF%emy zrobiE6% albo korzystajB1%c z darowanych przez
producenta bibliotek albo poprzez odwoB3%ania do rejestrF3%w, jak np GPIOB-
Quoted text here. Click to load it

I wB3%aB6%nie chodzi mi o ten drugi sposF3%b z uBF%yciem wskaBC%nika. Czy
dokonujB1%c zapisu GPIOB->BRR3D%.. operujemy na zmiennej wskaBC%nikowej?
Inaczej mF3%wiB1%c czy mamy zdefiniowanB1% zmiennB1% *GPIOB?
Nie mogEA% dojB6%E6 do tego jak to dziaB3%a. W plikach jest taka definicja
struktury:
typedef struct
{
  __IO uint32_t CRL;
  __IO uint32_t CRH;
  __IO uint32_t IDR;
  __IO uint32_t ODR;
  __IO uint32_t BSRR;
  __IO uint32_t BRR;
  __IO uint32_t LCKR;
} GPIO_TypeDef;


A potem coB6% takiego
#define GPIOB               ((GPIO_TypeDef *) GPIOB_BASE)  //GPIO_BASE
to liczba

Ale nie widze tutaj BF%adnej definicji zmiennej wskaBC%nikowej? CzyBF%by ni=
e
byB3%a ona potrzebna? To jak to dziaB3%a?

Wiem BF%e dla Was to proste, ale jak siEA% trochEA% zakrEA%ciB3%em i nie wi=
em
juz o co chodzi?

Re: [ARM] Obsługa peryferiów poprzez AP I (wskazniki do struktury)
W dniu 2012-05-26 07:56, slawek7 pisze:
Quoted text here. Click to load it
tutaj: (GPIO_TypeDef *)
W skrócie. GPIOB_BASE to adres bazowy (początkowy) rejestrów I/O portu
B. Rzutujemy tu wskaźnik na do struktury po kolei poukładanych rejestrów
I/O. Dzięki temu jedną strukturą GPIO_TypeDef możemy opisać tyle portów
ile ma dany procesor znając tylko ich adresy bazowe.
GPIOB jest więc wskaźnikiem do struktury.

Michał


Re: Obsługa peryferiów poprzez API (wskazniki do s truktury)

Quoted text here. Click to load it

Ale czy ten wskaBC%nik do struktury to fizycznie jest zmienna? JeB6%li tak
to gdzie jej definicja? Typedef nie definuje i nie rodzi zmiennej, tak
samo jak #define, wiec gdzie siEA% pojawia ta zmienna wskaBC%nikowa?
PrzecieBF% wskaBC%nik to zmienna przechowujB1%ca adres innej zmiennej, w ty=
m
przypadku struktury, czy nie tak?

Re: Obsługa peryferiów poprzez API ( wskazniki do struktury)
Quoted text here. Click to load it

A kto powiedział, że wskaźnik musi być zmienną? W Twoim przykładze jest
akurat stałą, która po rozwinięciu definicji GPIOB_BASE przez
preprocesor zostanie efektywnie zastąpiona natychmiastową stałą liczbową
(adres) zrzutowaną na wskaźnik odpowiedniego typu coby kompilator
wiedział co pod tym adresem siedzi dzięki czemu można w kodzie mieć
odnośniki do konkretnych pól struktury tam umieszczonej. Nie działa to
nic inaczej jak definiowanie stałych liczbowych jako makr preprocesora a
potem używanie ich np. do nadawania wartości zmiennym - tu też dopóki
nie użyjesz, to nigdzie w kodzie ta wartość nie będzie przechowywana.
W Twoim przykładzie jest tylko jedno istotne założenie tzn. że wskaźnik
do struktury jest co do warotści równy jej fizycznemu adresowi czyli nie
ma wirtualizacji pamięci (czytaj: brak OSa z prawdziwego zdarzenia).

Pozdr
Portal

Re: [ARM] Obsługa peryferiów poprzez API (wskazniki do struktury)
Dnia Fri, 25 May 2012 22:56:32 -0700 (PDT), slawek7 napisał(a):
Quoted text here. Click to load it

Zapis
(costam *) liczba

mowi "skonwertuj 'liczba' na typ: wskaznik na 'costam'"

poniewaz wskaznik to adres liczbowy, czyli po prostu liczba, wiec poza
nielicznymi wyjatkami zadna konwersja nie musi byc wykonywana.

Ale ... takie wyrazenie jest dalej traktowane jak wskaznik na obiekt typu
"costam", wiec mozesz uzywac zwyczajnych dla wskaznikow konstrukcji, np
GPIOB->pole  //to jest element struktury
*GPIOB.pole  //to samo co wyzej
itd.

P.S. Uwaga na nawiasy, przy takich rozwinieciach przez preprocesor cuda
moga sie zdarzyc, ktos moglby napisac

#define GPIOB               (GPIO_TypeDef *) GPIOB_BASE

a potem ktos inny

#define GPIOB_BASE       GPIOB_BASE_1 + 0x80
....
GPIOB->BRR = 5


I nieszczescie gotowe.
Im wiecej nawiasow tym lepiej.

J.

Re: Obsługa peryferiów poprzez API (wskazniki do s truktury)
W ksiB1%BFce o ARMach AT91SAM7 znalazB3%em jeszcze  coB6% takiego przy
deklaracji struktury:

typedef struct s_TC
{
  __IO uint32_t CONTROL_R;
  __IO uint32_t MODE_R;
  __IO uint32_t COUNTER_VALUE;
  __IO uint32_t INT_STATUS;

} S_TC, *PS_TC;

Potem
#define TC0 ((PS_TC)0xFFFA0000)

liczbEA% rzutujemy na wskaBC%nik, ale dlaczego bez gwiazdki?
Czy nie powinno byE6%
#define TC0 ((*PS_TC)0xFFFA0000)
skoro typedef utworzyB3% typ wskaBC%nikowy?

Re: Obsługa peryferiów poprzez API (wska zniki do struktury)
W dniu 2012-05-26 17:09, slawek7 pisze:
Quoted text here. Click to load it

No włąśnie. Rzutujesz liczbę na wskażnik. TO samo robiłeś tu:

#define GPIOB               ((GPIO_TypeDef *) GPIOB_BASE)

GPIOB  to rzut liczby GPIOB na _wskaĹşnik_ do typu GPIO_TypeDef.

int a to liczba
int * b  to wskaĹşnik do liczby.

GPIO_TypeDef A;  to strukturka
GPIO_TypeDef * bla; to skaĹşnik do strukturki.


Quoted text here. Click to load it

Wtedy TC0 byłby wskaźnikeim do wskaźnika do struktury typu S_TC.

pzdr
bartekltg



Re: Obsługa peryferiów poprzez API (wska zniki do struktury)
Quoted text here. Click to load it


Tak jak piszesz (wskaźnik na wskaźnik) to by było gdyby zdefiniować:
#define TC0 ((PS_TC *)0xFFFA0000)
tymaczsem konstrukcja:
#define TC0 ((*PS_TC)0xFFFA0000)
zwyczajnie się nie skompiluje jeżeli spróbuje się użyć w źródle
odniesienia do TC0.

Co do reszty zgoda - PS_TC juĹź jest typem wskaĹşnikowym i gwiazdek mu nie
potrzeba. Zamiennie można użyć:
#define TC0 ((S_TC *)0xFFFA0000)

Pozdr
Portal


Re: Obsługa peryferiów poprzez API (wska zniki do struktury)
W dniu 2012-05-26 18:25, Portal pisze:
Quoted text here. Click to load it


Aj, racja. Nie sprawdzałem dokłądnie kodu sławka, autokorekta
zadziałała;)


Quoted text here. Click to load it


pzdr
bartekltg


Re: Obsługa peryferiów poprzez API (wskazniki do s truktury)
Zgadza siEA% to co piszecie i zrozumiaB3%em o co chodzi.
PrzecieBF% to jest coB6% takiego
(*(uint32_t*)0x40010C10)3D%0x0000000f;
Powoduje to bezpoB6%redni dostEA%p do rejestru i operacjEA% na porcie PB.

Natomiast nie rozumiem zapisF3%w ktF3%re pojawiajB1% siEA% dokumentacji.
Adres jest 32 bitowy wiEA%c stB1%d zapewne pierwsze rzutowanie ale pojawia
siEA% teBF% informacja BF%e do rejestru moBF%na siEA% dostaE6%
albo jako word, albo jako half-word, albo jako byte? O co tu chodzi?
Jaki adres i jakie rzutowanie wtedy siEA% robi i co jak poda siEA% liczbEA%
word 32 bitowB1% zamiast wymaganB1% half-word 16 bitowB1%?

Re: Obsługa peryferiów poprzez API ( wskazniki do struktury)
Quoted text here. Click to load it


Chyba mylisz trochę postać adresu z typem danych siedzących pod tym adresem.
Operacja:
(*(uint32_t*)0x40010C10)=0x0000000f;
oznacza tyle co zapisz wartość 0x0000000f pod adres 0x40010C10 traktując
ją (wartość, nie adres) jako liczbę 32-bitową bez znaku.

Jeżeli zrobisz podobną operację, ale w postaci:
(*(uint8_t*)0x40010C10)=0x0f;
to pod ten sam adres zapiszesz tylko pojedynczy bajt, pozostawiając
pozostałe trzy bajty 32-bitowego słowa zapisanego pod adresem 0x40010C10
bez zmian.
Kwestia czy nadpisany zostanie najmniej czy najbardziej znaczący bajt
słowa zależy od "endianności" systemu - najczęściej jest to little
endian czyli 0x40010C10 wskazuje na najmniej znaczący bajt słowa,
0x40010C11 na kolejny i tak aż do 0x40010C13.

Przy zapisach 16-bitowych możesz analogicznie zapisać tylko pół rejestru
adresując połówki jako uint16_t pod adresem 0x40010C10 oraz 0x40010C12.
W większości RISCowych architektur dostęp do danych musi uwzględniać
wyrównanie tzn. adresy dla 32-bitowych dostępów muszą być
wielokrotnością czwórki, dla 16-bitowych wielokrotnością dwójki a bajty
można czytać i pisać "zewsząd" (o ile dany fragment przestrzeni
adresowej w ogóle uwzględnia możliwość takiego dostępu - w Twoim
przykładzie jak widać rejestry peryferyjne uwzględniają taką możliwość).

Pozdr
Portal

Re: Obsługa peryferiów poprzez API (wskazniki do s truktury)
Quoted text here. Click to load it

Chyba rozumiem. Bo czy to znaczy BF%e jeB6%li jakiB6% rejestr 32 bitowy ma
moBF%liwoB6%E6 zapisania go wartoB6%ciB1% 16 bitowa bo tak podaje dokument=
acja
to chcB1%c dokonaE6% takiego zapisu liczbB1% 16 bitowB1% uBF%ywam rzutowani=
a 16
bitowego w postaci (*(uint16_t*)0x40010C10)3D%0x1234;
Natomiast jeB6%li rejestr musi byc zapisany tylko wartoB6%ciB1% 32 bitowa b=
o
tak kaBF%e dokumentacja to u zywam (*(uint32_t*)0x40010C10)3D%0x12345678;

Ale mam wB1%tpliwoB6%E6, czy czasem to rzutowanie nie oznacza tylko
arytmetyki wskaBC%nikF3%w? Tzn za nastEA%pny wskazywany obszar bEA%zie wi=
EA%kszy
albo o 2 bajty albo o 4, jak w przypadku zwykB3%ej arytmetyki wskaBC%nikF3%
w
np
uint16_t *ptr; // wskaBC%nik na liczbEA% 16 bitowB1%
teraz zwiEA%kszamy adres o jeden ptr++; czyli tak naprawdEA% wskaBC%nik
skacze o dwa a nie o jeden adres?

Re: Obsługa peryferiów poprzez API (wskazniki do struktury)
Dnia Mon, 28 May 2012 11:13:59 -0700 (PDT), slawek7 napisał(a):
Quoted text here. Click to load it

Czyli chyba nie rozumiesz

0x40010C10
 to liczba. a moze i adres.

(uint32_t*)0x40010C10
  liczba, zasadniczo ta sama, ale juz typu "wskaznik na cos"

*(uint32_t*)0x40010C10
 obiekt wskazywany przez ten wskaznik. A poniewaz wskaznik mial wskazywac
na uint32, to obiekt jest uint32. Albo inny, jesli tak ustalisz.
  
(*(uint32_t*)0x40010C10)=0x0000000f;
 a tu masz wpisanie wartosci do obiektu.

Przy czym moze nastapic kolejna konwersja wyrazenia z prawej strony, na typ
obiektu z lewej. Np

(*(uint8_t*)0x40010C10)=0x00001234;
  to zapisze jeden bajt, 34

(*(uint32_t*)0x40010C10)=0x9f;
  a to zapisze 0000009f, albo ffffff9f :-)

Quoted text here. Click to load it

A to oczywiscie tez. Tylko trzeba umiejetnie wykorzystywac.

Quoted text here. Click to load it

Tylko wiesz ze nie zapiszesz
((uint8_t*)0x40010C10)++)

ani
((uint32_t *) ptr)++;

Za to mozesz sprobowac
*((uint32_t *)ptr+1)=1 ;

A na koniec masz zadanie domowe
(*((uint32_t **) &ptr))++;

J.

Re: Obsługa peryferiów poprzez API ( wskazniki do struktury)

Quoted text here. Click to load it

Źle podejrzewasz. Przede wszystkim typ użytego wskaźnika determinuje typ
dostępu w kodzie wynikowym tzn. fizycznie na szynie jest wystawiony
rozkaz odczytu lub zapisu tylko pojedynczego bajtu lub 16-bitowego słowa
zamiast pełnego 32-bitowego. Czyli jeżeli zapisujesz uint8_t np. pod
adres 0x00000000, to bajty pod adresami 0x00000001, 0x00000002 i
0x00000003 pozostaną nienaruszone, podczas gdy zrobienie tego samego
jako operacji na uint32_t pod adres 0x00000000 zapisze wszystkie cztery
bajty słowa.

Pozdr
Portal

Re: Obsługa peryferiów poprzez API (wskazniki do s truktury)
Quoted text here. Click to load it

Niestety nie mF3%j poziom, nie wiem.

Re: Obsługa peryferiów poprzez API (wskazniki do s truktury)
Quoted text here. Click to load it

Niestety nie mF3%j poziom, nie wiem.

Re: Obsługa peryferiów poprzez API (wskazniki do s truktury)
Quoted text here. Click to load it

Niestety nie mF3%j poziom, nie wiem.

Re: Obsługa peryferiów poprzez API (wskazniki do s truktury)
Quoted text here. Click to load it

Niestety nie mF3%j poziom, nie wiem.

Re: Obsługa peryferiów poprzez API (wskazniki do struktury)
Hello slawek7,


Quoted text here. Click to load it

Jeszcze kilka razy, bo cztery to za mało :(

--
Best regards,
 RoMan
We've slightly trimmed the long signature. Click to see the full one.
Re: Obsługa peryferiów poprzez API ( wskazniki do struktury)

Quoted text here. Click to load it


Może się cztery razy przymierzał ?

Pozdr
Portal


Site Timeline