### Link1| Link2| Link3 »

# Ismerkedés a NuTiny-SDK-NUC140
fejlesztői modullal

# A CPU órajelének beállítása

Az előző projektben eléggé el nem ítélhető módon nem foglalkoztunk a CPU órajelének beállításával, a késleltetést is csak találomra, for ciklusok szervezésével állítottuk be, pedig a projektbe becsatolt függvénykönyvtárak sokkal "professzionálisabb" lehetőségeket kínálnak! Írjuk át most a LED villogtató programot úgy, hogy a CPU ismert frekvenciájú (pl. 48 MHz) órajellel működjön, a késleltetéshez pedig a Cortex-M0 mikrovezérlők beépített Systick időzítőjét használjuk!
A projekt létrehozása az előző oldalon bemutatott módon történhet, a felkínált könyvtári modulok közül most is csak a GPIO-t kell kézzel kiválasztanunk, a többi szükséges modul automatikusan kijelölésre kerül. A main.c állományba az alábbi listán látható forráskódot másoljuk be!
1. lista: A 02_Blinky projekt main.c állományának listája

    // 02_Blinky: Blinks the red LED connected to Pin 10 of Port A
    // pin should be in LOW state to drive the LED
    //
    // This is a slightly modified version of the Smpl_GPIO_LED.c example program
    // written by Richard Kuo, National Taiwan Ocean University
    // Link: http://sourceforge.net/projects/numicronulbnuc1/
    //

    #include "NUC1xx.h"
    #include "Driver\DrvGPIO.h"
    #include "Driver\DrvSYS.h"

    int main (void)
    {
     UNLOCKREG(); // unlock register for programming
     DrvSYS_Open(48000000); // set System Clock to run at 48MHz
     LOCKREG(); // lock register from programming
     DrvGPIO_Open(E_GPA, 10, E_IO_OUTPUT); // GPA10 pin set to output mode
     DrvGPIO_SetBit(E_GPA, 10); // GPA10 pin output Hi to turn off LED

     while (1) // forever loop to keep flashing LED
     {
     DrvGPIO_ClrBit(E_GPA, 10); // output Low to turn on LED
     DrvSYS_Delay(250000); // 250 ms delay
     DrvGPIO_SetBit(E_GPA, 10); // output Hi to turn off LED
     DrvSYS_Delay(250000); // 250 ms delay
     }
    }

A CPU órajelének frekvenciáját legegyszerűbben a SYS periféria kezelő programmodul DrvSYS_Open() függvényével állíthatjuk be. Paraméterként a kívánt órajel frekvenciát kell megadni, Hz-ben. A gyári könyvtárak 25 - 50 MHz közötti értékek megadását engedélyezik. A fenti példában mi 48 MHz-et írtunk elő, ez a kártyán található 12 MHz-es kvarc jeléből PLL (fáziscsatolt hurok) segítségével könnyen előállítható. A hardver korlátozott lehetőségei miatt (csak egész értékű szorzókat és osztókat használhatunk) azonban nem állítható elő tetszőleges órajel. A ténylegesen beállított órajel frekvenciáját a DrvSYS_GetPLLClockFreq( ) függvény hívásával ellenőrizhetjük.
Ügyeljünk arra, hogy a rendszer működését alapvetően befolyásoló védett regiszterek tartalmának felülírása csak akkor lehetséges, ha előtte feloldottuk a regiszterek írásvédelmét. A feloldást kétféle módon is végezhetjük: vagy a NUC1xx.h állományban definiált UNLOCKREG() nevű makró, vagy pedig a DRV_SYS.c állományban definiált DrvSYS_UnlockProtectedReg() függvény meghívásával. Végeredményben ugyanazt csinálja mind a kettő: az 0x59, 0x16, 0x88 bűvös számsort tölti be a 0x5000_0100 címen található REGWRPROT regiszterbe. A regiszterek beállítása után az írásvédelmet úgy állíthatjuk vissza, hogy nullát írunk a REGWRPROT regiszterbe a LOCKREG() makró, vagy DrvSYS_LockProtectedReg() függvény meghívásával.
Az általános célú ki/bemenet (GPIO) beállítása és ki-be kapcsolgatása ugyanúgy történik, ahogy az első példában is mutattuk:

     DrvGPIO_Open(E_GPA, 10, E_IO_OUTPUT); // GPA10 pin set to output mode

A függvény első paramétere a portot (esetünkben az A portról van szó), a második paraméter a port bitjét (0-15), a harmadik paraméter pedig az adott bithez tartozó kivezetés üzemmódját és az adatáramlás irányát (pl. digitális kimenet) adja meg. Bővebben lásd: NUC100 Series Driver Reference Guide v1.05 5. fejezetében!
A késleltetést itt a Cortex-M0 mikrovezérlők Systick számlálóját használó DrvSYS_Delay() függvénnyel oldottuk meg, amelynek mikroszekundumban kell megadni a kívánt várakozási időt. Arra vigyáznunk kell, hogy 335000-nél nagyobb értéket ne adjunk meg!
Magyarázat: a Systick periféria egy 24 bites számláló, amely a kiválasztott órajelet (alaphelyzetben a CPU max. 50 MHz-es órajelét) számlálja. A számlálás a beírt értéktől kezdve visszafelé történik, s amikor a számláló eléri a nullát, bebillen a Systick nullára futás jelzőbitje (a 0xE000_E010 címen található SysTick->CTRL regiszter COUNTFLAG bitje). Ez a bit akkor billen be, amikor a visszafelé számláló 1-ről nullára billen.
A programunkban nem engedélyeztük a programmegszakítást, ezért a COUNTFLAG jelzőbitet a DrvSYS_Delay() függvény lekérdezéses (polling) módban vizsgálja, így dönti el azt, hogy letelt-e már a kívánt késleltetési idő. Ez nem túl hatékony módszer, hiszen a blokkoló típusú várakozás nem teszi lehetővé sem azt, hogy a CPU közben más, hasznos tevékenységgel töltse az idejét, sem azt, hogy közben energiatakarékos módban szundikáljon.Tanulságos lesz megnézni a DrvSYS.c állományban a függvény forráskódját!
2. lista: A DrvSYS_Delay() függvény listája

    //*****************************************************************************
    //
    //! \brief Use the SysTick to generate the delay time and the UNIT is in us. The
    //! SysTick clock source is from HCLK.
    //!
    //! \param us Delay time. The Max value is 335000
    //!
    //! \return None
    //
    //*****************************************************************************
    void DrvSYS_Delay(uint32_t us)
    {
     SysTick->LOAD = us * CyclesPerUs;
     SysTick->VAL = (0x00);
     SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_ENABLE_Msk;

     /* Waiting for down-count to zero */
     while((SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk == 0);
    }

A SysTick_CTRL_CLKSOURCE_Msk és SysTick_CTRL_ENABLE_Msk makrókat a core_cm0.h állomány definiálja (lényegében a Systick->CTRL regiszter BIT2 és BIT0 bitjeinek beállításhoz használjuk ezeket). Ugyanitt van definiálva a SysTick_CTRL_COUNTFLAG_Msk makró is, amely a SysTick->CTRL regiszter COUNTFLAG bitjét választja ki (BIT16). Ez a bit akkor vált 1-be, amikor a beállított késleltetési idő letelt.