wtorek, 4 czerwca 2019

ATSAML10 - spotkanie z SPI.

Generalnie wszystko co napisałem kiedyś o ATSAML21 dotyczy również ATSAML10 i ATSAML11. Ta sama seria L oznacza, że wspólne peryferia są opisane tymi samymi rejestrami. Więc przenośność kodu jest bardzo wysoka. Nie będę zatem ponownie powtarzał wiedzy przedstawionej w artykule ATSAML21 - uruchamiamy SPI czyli SERCOM nie tylko dla orłów. Bo większość tego co zostało napisane w tamtym artykule możemy zastosować do ATSAML10 i 11. Po krótce przyjrzymy się jak wygląda droga do uruchomienia SPI w naszym ATSAML10E16. Na pewno nie będzie nudno bo ATSAM-y są nietrywialnymi mikrokontrolerami i z nimi nie można się nudzić :)

W ATSAML10E16 mamy do dyspozycji 3 x SERCOM ,ponumerowane SERCOM0...SERCOM2. Dla przypomnienia SERCOM to moduł z którego można wyczarować m.in  SPI, I2C, USART. Jakie są docelowe możliwości konfiguracji SERCOM-ów w naszym MCU prezentuje poniższa tabelka :



Za pomocą aplikacji webowej ATMEL START robię wizualizację dystrybucji zegara i modyfikuję go sobie po swojemu tak aby od strony zapisów w rejestrach jak najmniej się namachać.. Takie zobrazowanie jest pomocne aby sobie wyobrazić co należy z grubsza zrobić w zakresie dystrybucji zegara dla wybranego modułu SERCOM. Najpierw jednak zdefiniujmy jakieś założenia. Ponieważ moim zamiarem jest komunikacja z wyświetlaczem LCD jaki mam na mojej płytce developerskiej dlatego potrzebuję skonfigurować SPI tak aby na pinie PA24 było MOSI a na pinie PA25 SCK. MISO jest mi w tym przypadku zbędne. Do konfiguracji użyję SERCOM0 i w efekcie SPI0.



Moduł SERCOM0 wykorzystuje do swojej pracy trzy zegary :
  • CLK_SERCOM0_APB - SERCOM bus clock
  • GCLK_SERCOM0_CORE - SERCOM core clock
  • GCLK_SERCOM0_SLOW - SERCOM slow clock
Przy czym pierwszy zegar czyli SERCOM bus clock jest po resecie włączony, więc nie musimy sobie nim głowy zaprzątać. Ustawienie tego zegara dla modułu SERCOM znajdziemy w module zegara synchronicznego MCKL rejestr APBCMASK. O ile zegar SERCOM core clock nie wydaje się czymś dziwnym to już na pewno jest nim SERCOM slow clock. Dowiadujemy się, że jest to zegar wykorzystywany przez niektóre funkcje. Operacja zapis/odczyt do niektórych rejestrów wymaga takiego zegara. Jeśli zobaczymy w jakimś module peryferyjnym rejestr SYNCBUSY to pola bitowe tego rejestru pokazują , które rejestry wymagają zegara slow clock. Wiąże się to z aspektem przeprowadzenia tzw synchronizacji między  slow clock a  core clock po wykonaniu operacji na takich rejestrach. Ale spokojnie wszystko wymyślił człowiek i również człowiek jest w stanie to ogarnąć.

Wynika stąd , że ustawień zegara szukamy tylko w bloku zegara asynchronicznego (GCLK).

Jedyną wymaganą czynnością jaką musimy w części zegarowej zrobić opierając się na naszej wizualizacji zegara to podpięcie modułu SERCOM0 (na obrazku SPI0) do bloku Generatora nr 0. W szczególe takie podpięcie realizowane jest za pomocą kanału  i to właśnie kanałem łączymy moduł SERCOM0 z Generatorem nr 0. Fizycznie podpinamy się przy użyciu rejestru PCHCTRLm (Peripheral Channel Control). Zróbmy zatem odpowiednie wpisy , na razie postać ogólna :

GCLK_SERCOM[0,1,2]_SLOW :
PCHCTRL10 --> CHEN --> 1  włącz kanał dystrybucji zegara SERCOM_slow
PCHCTRL10 --> SRC --> 0x0 (ten zapis jest zbędny bo po resecie tak jest ustawione)

GCLK_SERCOM0_CORE :
PCHCTRL11 --> CHEN --> 1 włącz kanał dystrybucji zegara SERCOM0 Core
PCHCTRL11 --> SRC --> 0x0 (ten zapis jest zbędny bo po resecie tak jest ustawione)

Powyższe wpisy a w szczególności numerki 10 i 11 wynikają z tabelki poniżej :


Załatwione mamy podpięcie modułu SERCOM0 do bloku Generatora nr 0 za pomocą kanału. Zdaję sobie sprawę , że dystrybucja zegara może na początku przygody z ATSAM-ami  sprawiać problemy z opanowaniem czy zrozumieniem. Ale zapewniam , że jak raz zatrybimy całą ideę to będzie to dla nas pestka a nawet da się to polubić.

Aby ustawić SERCOM w tryb SPI MASTER musimy wpisać w rejestrze CTRLA bit MODE wartość 0x3.
CTRLA --> MODE --> 0x3  / włącz tryb SPI MASTER dla SERCOM

Przed grzebaniem w rejestrach SERCOM SPI należy wyłączyć SPI a robimy to wpisem :

CTRLA --> ENABLE --> 0 / wyłącz SPI
 
Pamiętać należy aby po skonfigurowaniu SPI , należy włączyć peryferium zapisem :
CTRLA --> ENABLE --> 1 / włącz SPI
 
Kolejnym punktem w inicjalizacji jest wyłączenie opcji odbioru (nie korzystamy z MISO) robimy to zapisem:
CTRLB --> RXENABLE --> 0 / wyłącz RX

Kolejnym punktem inicjalizacji jest ustawienie prędkości SPI za pomocą Baud register (BAUD). Im mniejsza wartość tym szybciej, dla 0 mamy połowę pełnej wartości zegara SERCOM core clock  , w naszym przypadku jest to 2 MHz. Nasz zegar jest na starcie ustawiony na 4 MHz. Najszybszy dostępny zegar to 32MHz , czyli SPI popędzimy maksymalnie na 16 MHz.

BAUD --> BAUD --> 0 /
ustaw na 8 bitach wartość Baud Generator 


Aby podpiąć peryferium fizycznie do pinu musimy dokonać wpisu w rejestr, PINCFG  bit PMUXEN oraz PMUX.

Odłączamy piny od modułu PORT a podłączamy je do modułu PMUX:
 
PORTA --> PINCFG24 --> PMUXEN --> 1
/ podłącz pin PA24 do modułu PMUX
PORTA --> PINCFG25 --> PMUXEN --> 1
/ podłącz pin PA25 do modułu PMUX


Teraz za pomocą rejestru PMUXn dokonamy przyporządkowania pinów PA24 i PA25 do peryferium SERCOM0.  Ta operacja wymaga pewnego skupienia i tutaj dosyłam po szczegóły do mojego artykułu w którym w miarę dokładnie to opisałem : ATSAML21 - uruchamiamy SPI czyli SERCOM nie tylko dla orłów. 


PORTA --> PMUX12 --> PMUXE --> 0x2 / podłącz pin PA24 (parzysty pin 2*n) do modułu SERCOM0 (literka C), Pin  24 = 2*n stąd n = 24/2 = 12
PORTA --> PMUX12 --> PMUXO --> 0x2
/ podłącz pin PA25 (nieparzysty pin 2*n+1) do modułu SERCOM0 (literka C) , Pin  25 = 2*n+1 stąd n = (25 - 1)/2 = 12


Kolejnym krokiem jest przyporządkowanie pinom PA24 i PA25 funkcji SPI czyli MOSI i SCK w naszym przypadku. PA24 do MOSI i PA25 do SCK
Z datasheet z tabelki na str 21 w kolumnie C odczytamy , że pin PA24 jest opisany jako PAD[2] a pin PA25 jako PAD[3]. Te informacje będą potrzebne do przyporządkowania poszczególnych funkcji SPI naszym pinom. Przechodzimy zatem do tej czynności. Interesuje nas tutaj rejestr  CTRLA i bity opisane jako DOPO (Data Out Pinout) i DIPO (Data In Pinout).

W polu bitowym DIPO wybieramy na którym PAD[x] chcemy mieć MISO w trybie MASTER lub MOSI w trybie SLAVE. My akurat MISO nie potrzebujemy do szczęścia, więc nic nie wpisujemy do pola DIPO .Natomiast w polu bitowym DOPO ustawiamy MOSI i SCK  zgodnie z opisem w tabelce na stronie 775 i 776. Schematyczny wpis jaki należy dokonać poniżej :

CTRLA --> DOPO -->  0x1 / w trybie MASTER przyporządkuj do PAD[2] MOSI a do PAD[3] CLK
 

I to już w zasadzie wszystko jeśli chodzi o konfigurację SPI dla potrzeb sterowania wyświetlaczem LCD znajdującym się na mojej płytce developerskiej. 
Nie wspomniałem o trybach pracy SPI, ale wspominałem o tym w artykule o ATSAML21.
Specyfika ATSAM-ów w zakresie peryferiów nie jest trywialna i nie jednego może wprowadzić w konsternację lub zawrót głowy :). Moim zdaniem ta nie trywialność ma swój urok . Z ATSAM-ami nie można się po prostu nudzić a to sprawia, że chce się z nimi obcować. Na koniec jak nasza konfiguracja SPI wygląda od strony kodu :





A poniżej przykładowy kod jak możemy sobie sprawdzić czy SPI działa. Potrzebny oczywiście analizator stanów logicznych.



Efekt działania przykładowego kodu na analizatorze stanów logicznych wszystko działa bez zająknięcia co mnie cieszy :



Konfiguracja SPI poszła jak po maśle, nie natrafiłem nawet na cień problemu ale jest to wynik poznania wcześniej ATSAML21 i w sumie dobrej dokumentacji. Programowanie ATSAM-ów z wykorzystaniem rejestrów daje dużą satysfakcję i pełną kontrolę nad tym co robimy. Gdybym posłużył się bibliotekami ASF stworzonymi przez  ATMELA co jest odpowiednikiem HAL dla STM32 to w sumie zeszlibyśmy w pewnym uproszczeniu na poziom programowania ARDUINO czyli wpisz funkcję , która zrobi "milion" rzeczy za ciebie ale ty nadal nie będziesz wiedział jak to działa. Nie każdy dobrze się czuje z takim podejściem. No ale wszystko ma swoje wady i zalety , biblioteki typu HAL zostały stworzone m.in po to aby zwiększyć przenośność kodu pomiędzy różnymi rodzinami MCU w obrębie jednego producenta. Ale z drugiej strony inwestowanie wiedzy w biblioteki typu HAL ma w/g mnie poważną wadę, mianowicie ta wiedza kompletnie jest nie przydatna jeśli zmieniamy producenta. Jeśli np chcemy przenieść się z STM32 na ATSAM-y to o kant dupy potłuc wiedza o HAL i migracja z tą wiedzą jest nie efektywna. Natomiast np. programując STM32 na rejestrach, bez HAL  i poznając od podszewki działanie  peryferiów i architektury MCU etc to bardzo szybko odnajdziemy się w rejestrach ATSAM-ów pomimo odmiennej specyfiki. Na bibliotekach typu HAL po prostu mózg tępieje a my się nie rozwijamy :). Pracując natomiast na rejestrach zwiększamy liczbę połączeń neuronowych w mózgu czyli się rozwijamy :). Takie są moje osobiste odczucia i spostrzeżenia . Można się z tym oczywiście nie zgodzić bo to co jest dla jednego człowieka dobre niekoniecznie musi być dobre dla drugiego . Mnie jednak grzebanie w rejestrach dało potężnego kopa w samorozwoju a jeszcze nie dawno nie miałem pojęcia co to jest mikrokontroler. Z perspektywy czasu cieszę się , że nie poszedłem w nurt Arduino tylko od samego początku rzuciłem się na głęboką wodę.

W kolejnym wpisie będę uruchamiał bibliotekę dla wyświetlacza LCD ILI9341 2.2" jaki znajduje się na mojej płytce developerskiej.


Pozdrawiam
picmajster.blog@gmail.com
 


Linki :

ATSAML10E16 - strona produktu  

Brak komentarzy:

Prześlij komentarz