Tutoriál si klade za cíl seznámit vás formou komentovaných příkladů se správou clocku v čipech Atmel SAMD9 a SAMD10. Rozhodně se nebudu snažit o vyčerpávající tutoriál, který by porkýval všechny možnosti, protože jich je nespočet. Zaměřím se jen na to co sám používal. Spolu s ovládáním pinů tvoří správa clocku jakousi vstupní bránu k provozování těchto mikrokontrolerů, protože skoro každá aplikace bude vyžadovat aby jste clock vhodně nakonfigurovali. V první části tutoriálu si budete moct přečíst lehký přehled celého systému a v dalších částech pak budou komentované příklady. Ty mohou klidně sloužit jako šablona, kterou nakopírujete do projektu a upravíte dle svých potřeb (minimálně já je tak používám). Pro ty, kteří k tutoriálu přistupují opakovaně právě jako k šablonám uvedu seznam příkladů hned v úvodu.
Systém distribuce a správy clocku v SAMD10 je flexibilní. Je dost pružný na to aby mi pomocí dvou laciných čipů (SAMD9) umožnil vytvořit na první pohled vyloženě odpornou dvojici frekvencí (10MHz a 15.90528MHz) odvozených od jednoho časového normálu (30MHz). Díky tomu se nám daří dlouhodobé stabilizovat otáčeky dvou motorů s dvěma odlišnými drivery. Bohužel spolu s touto flexibilitou jde ruku v ruce i jistá složitost. Bloky, které správu provádí můžete vidět na obrázku 14-1. Vlevo je blok SYSCTRL v němž (dá-li se to tak říct) clock "vzniká". Vývody GCLK_IO slouží k přivádění nebo vyvádění kloku ven z čipu. Velký blok Generic Clock Controler je obří matice multiplexerů a děliček a v dalším textu se s ní seznámíme blíže. Vpravo pak vidíte "konzumenty" clocku. Jednotlivé periferie a blok PM - Power Manager upravující clock pro jádro mikrkontroléru (GCLK_MAIN).
Jako první se podíváme na blok SYSCTRL a něco si povíme o možnostech generování clocku. Opět si pomůžeme blokovým schematem z datasheetu (obrázek 16-1). Vidíte že krom clocku je v bloku SYSCTRL zahrnuta správa napěťové reference a monitoringu napájení (Brown out detekce), těmi se ale zabývat nebudeme. V horní části je pak patrný bohatý seznam oscilátorů. Na čipu máte k dispozici hned tři. Interní 8MHz RC oscilátor, relativně přesný 32.768kHz oscilátor a nízkoodběrový (nepřesný) 32kHz oscilátor. Naprostou samozřejmostí pak je klasický krystalový oscilátor v rozsahu 400kHz-32MHz. Suveréně nejzajímavější je FDPLL (Fractional Digital Phase Locked Loop). Tento systém je schopný připravit širokou škálu frekvencí v rozsahu 48-96MHz a teprve s ním můžete vyhnat jádro procesoru na nejvyšší frekvenci (48MHz). Podobné, byť ne tak bohaté možnosti má i systém DFLL, který také může generovat frekvenci 48MHz, ale jeho konfigurace je složitější a upřímě mi uniká proč v systému je. Moc rád bych vám na tomto místě předložil pár ukázkových příkladů jak konfigurovat jednotlivé oscilátory, ale nemůžu. Protože i když oscilátor správně rozběhnete, musíte ho umět prohnat skrze Generic Clock Controler. Teprve pak se dostane k jádru nebo ho budete moct vypustit na některý z výstupů čipu. Proto se před prvními pokusy musíme seznámit ještě s blokem Generic Clock Controler.
Na obrázeku 13-1 si můžete prohlédnout schéma distribuce clocku. Něco podobného už jste viděli v úvodu, ale tady si můžete navíc všimout že Generic Clock Controler (GCLK) se skládá z několika dalších bloků. GCLK Generator je vlastně programovatelná dělička a máte jich k dispozici celkem šest. GCLK Multiplexer je už podle názvu multiplexer, který vybírá každé periferii zdroj taktovacího signálu. Takže například čítač má svůj multiplexer, kterým si může vybrat clock z jednoho ze šesti generátorů. Obecně tedy platí že v čipu může žít a pracovat až šest defakto nezávislých taktovacích signálů. Z toho také vyplývají jisté peripetie se synchronizací různých akcí. Ale o tom až později. Na obrázku 14-2. vidíte vtnitřní strukturu GCLK detailně. Kromě GCLK1 jsou všechny ostatní bloky generátorů (GCLK0..GCLK5) shodné. Vstupem kažédmu z nich může být libovolný signál z bloku SYSCTRL (tedy libovolný z výše zmiňovaných oscilátorů) a navíc má každý z generátorů k dispozici jeden pin procesoru. Ten může mimo jiné sloužit jako vstup vnějšího signálu. Generátoru 0,2,3,4 a 5 pak může být vstupem navíc výstup Generátoru 1. Což se v praxi může hodit. Například v případě že přivádíte clock čipu na vnější pin a moudře si vyberete že to bude pin GCLK_IO[1]. Srkze GCLK1 jej pak můžete distribuovat všem generátorům a každý jej může zpracovat (podělit) jinak. Podíváte-li se na výstupy z Generátorů můžete vidět že krom multiplexerů vedou také ná piny procesoru (GCLK_IO). Této možnosti budeme při prvních testech s clockem hojně využívat protože nám umožní kontrolovat zda je naše nastavení správné. Z Generátoru 0 vede GCLK_MAIN což je takt pro jádro mikrokontroléru. Z multiplexerů už pak vedou signály do jednotlivých periferií. V konečném důsledku to vlastně není nijak zvlášť složitý systém.
Podívejme se teď do jednoho Generátoru. Jeho vnitřní schema je na obrázku 14-3. Modře podbarvené obdélníky s názvy registrů a ovládacích bitů vám napoví, že jsme došli až na dřeň věci. Skupina bitů GENCTRL.SRC vybírá každému generátoru vstupní clock. GENDIV.DIV a GENCTRL.DIVSEL pak konfiguruje děličku a nakonec GENCTRL.GENEN spouští a vypíná generátor (nebo přesněji řečeno vypouští nebo nevypouští clock z generátoru ven). K řidicím registrům jednotlivých generátorů nemáte přímý přístup. To vytváří jisté komplikace při čtení, ale to budete dělat zříkdakdy. Naopak zápis je velice jednoduchý, do skupiny bitů ID zapíšete pořadové číslo generátoru pro nějž je konfigurace určena. Na tomto místě vám doporučuji prohlédnout si seznam registrů v tabulce 14-1. v datasheetu. Registry GENCTRL a GENDIV konfigurují generátory, registr CLKCTRL pak multiplexery. Podívejme se tedy ve stručnosti na obsah registru GENCTRL.
Jak už název napovídá XOSC je krystalový oscilátor. Krystal se běžně připojuje k vývodům XIN (PA08) a XOUT (PA09) a může to být buď hodinový krystal o frekvenci 32.768kHz nebo vysokofrekvenční krystal (0.4-32MHz). Softwarově je možné oscilátor přemostit a využít tak pin XIN k přivedení vnějšího zdroje hodin (k čemuž mohou sloužit také piny GCLK_IO). Oscilátoru lze softwarově řídit zisk, případně povolit automatické řízení zisku, což by dledatasheetu mělo vést k nižší spotřebě. Stejně tak je možné konfigurovat jeho dobu náběhu. Třeba hodinové krystaly se mohou rozbíhat klidně i několik vteřin než jejich amplituda dosáhne stabilní hodnoty. Veškerá konfigurace se provádí v registru XOSC pomocí následujících bitů (nebo bitových polí).
Na naší vývojové desce není k mikrokontroléru žádný krystal připojen. Namísto toho je z programátoru (mEDBG) přiveden 8MHz signál na pin PA08 (XIN). Ukážeme si proto jednoduchý postup jak spustit krystalový oscilátor v režimu bez krystalu (tedy s externím signálem) a jak takový clock zpracovat pomocí GCLK. Abychom si ověřili že se děje to co předpokládáme, vyvedeme si zpracovaný clock na některý z GCLK_IO pinů. Řekněme, že je naším úkolem připravit frekvenci 1MHz a vyvést ji na pin PA14. Pin PA14 má funkci GCLK_IO[4], může jej tedy ovládat Clock Generátor 4. Celá konfigurace tedy bude vypadat tak že nejprve rozběhneme oscilátor (XOSC) a počkáme než bdue stabilní. Pak nakonfigurujeme Generátor 4. Zvolíme dělení 8mi, zdorj signálu mu vybereme XOSC a povolíme mu vypustit signál GCLK_IO. Nakonec nakonfigurujeme pin PA14 aby pracoval jako GCLK_IO[4] (což je jedna z 9ti alternativních funkcí, které může zastávat). Zdrojový kód a celkem nudný výsledek si můžete prohlédnout dále.
// Nastaví Generic Clock Controller 4 se vstupem XOSC (zde externí clock na XIN - PA08), dělí signál 8, a přivede na GCLK_IO[4] (PA14) void gclk4_init(void){ // spustit XOSC s externím clockem (s krystalem by bylo potřeba XTALEN a nastavit gain...) SYSCTRL->XOSC.reg = SYSCTRL_XOSC_ENABLE; while(!(SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_XOSCRDY)){}; // počkat na naběhnutí XOSCK // nastavit parametry generátoru 4 GCLK->GENDIV.reg = GCLK_GENDIV_ID(4) | GCLK_GENDIV_DIV(8); // generátor 4, dělíme /8 // povolit generátor 4, povolit výstup na pin GCLK_IO[4], vybrat zdroj signálu - XOSC GCLK->GENCTRL.reg = GCLK_GENCTRL_ID(4) | GCLK_GENCTRL_OE | GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_XOSC_Val; // nastavení pinu PA14 PORT->Group[0].PINCFG[14].reg |= PORT_PINCFG_PMUXEN; // nastavit PA14 jako Alternativní fci PORT->Group[0].DIRSET.reg = PORT_PA14; // nasatvit PA14 jako výstup PORT->Group[0].PMUX[14/2].reg = PORT_PMUX_PMUXE(PORT_PMUX_PMUXE_H_Val) ; // vybrat příslušnou alternativní fci (PA14 ... H - GCLK_IO) }
Home
| V0.10 x.xx.~2016 /
| By Michal Dudka (m.dudka@seznam.cz) /