====== 6. Úvod do Mikrokontrolérů ====== ===== Cíle cvičení ===== - Seznámení se s architekturou, paměťového prostoru a základních bloků mikrokontroléru řady STM32F4 - Registry platformy STM32 - RCC, GPIO - Konfigurace projektu - Ovládání LED a tlačítka ===== Co je třeba si připravit ===== Nainstalovat prostředí pro vytváření programu podle preferencí každého. Všechna prostředí produkují stejný výsledek, takže záleží na každém, co bude používat. Jednotlivý cvičící používají tyto programy: * Skalický - [[courses:b2m37mam:tutorials:keil:start|Keil uVision]] * Vítek, Nentvich - [[courses:b2m37mam:tutorials:stm32ide:start|STM32CubeIDE]] * Krška - [[courses:b2m37mam:tutorials:ses:start|Segger Embedded Studio (SES)]] ===== Podklady pro cvičení ===== {{ :courses:b2m37mam:labs:mam_2023-cviceni_6.pdf | Podklady pro 6. Cvičení - Skalický}} {{ :courses:b2m37mam:labs:mam_2022-konfigurace_gpio_bran.pdf | Podklady pro cvičení - Konfigurace GPIO}} {{ :courses:b2m37mam:labs:Přístup k jednotlivým vývodům uP.pdf | Přístup k jednotlivým vývodům uP.pdf}} {{ :courses:b2m37mam:labs:moznosti_debug_keil.pdf | Možnosti debug v prostředí KEIL }} {{ :courses:b2m37mam:labs:debug.zip | Příklady využití debug režimů v prostředí KEIL }} ===== Dokumentace ===== {{ :courses:b2m37mam:labs:cortex-m4_generic_user_guide.pdf | Jádro ARM M4}} {{ :courses:b2m37mam:labs:stm32f401re.pdf | Datasheet STM32F401 }} {{ :courses:b2m37mam:stm32f401_refmanual.pdf | Referenční manuál STM32F401 }} {{ :courses:b2m37mam:stm32f4_instruction_set.pdf | Instrukční sada STM32F4}} {{ :courses:b2m37mam:nucleo_64_pins.pdf | Datasheet Nucleo F401RE}} [[courses:b2m37mam:tutorials:dev_kits:nucleof401| Podklady pro Nucleo STM32F401]] ===== Projekty ===== {{ :courses:b2m37mam:labs:nastaveni_gpio.zip | Funkce - Nastavení GPIO }} ===== Kódy pro cvičení ===== #define BITSET(reg, bit) ((reg) |= (1U << (bit))) #define BITCLEAR(reg, bit) ((reg) &= (~(1U << (bit)))) #define BITTOGGLE(reg, bit) ((reg) ^= (1U << (bit))) #define BITGET(reg, bit) ((reg & (1U << bit)) >> bit) ===== Mikrokontrolér ===== Mikrokontrolér (MCU) je sekvenční programovatelný obvod se zabudovanými periferiemi a pamětí uvnitř čipu. Některé MCU disponují ještě externí pamětí, kterou lze využít na rozšířenou RAM paměť nebo další periferie. Činnost MCU závisí na posloupnosti příkazů strojového kódu programu uloženou v paměti ROM nebo dočasně v paměti RAM. Každá instrukce vyžaduje určitý strojový čas na jeho provedení (min. 1 strojový cyklus na instrukci) během kterého se vykonají tři fáze (fetch-decode-execute). Aby bylo možné zvýšit rychlost mikrokontroléru, byl vymyšlena tzv. pipeline příkazů, kde v daný okamžik se může vykonávat více fází instrukce najednou a tím urychlit běh programu. Instrukce se vykonají podle toho, jak jsou napsané v programu za sebou, kde každá část fetch-decode-execute se vykoná na jeden hodinový takt se zpožděním, viz. následující schéma nebo {{ :courses:b2m37mam:stm32f401_refmanual.pdf#page=48 | Referenční manuál STM32F401 }} na straně 48. {{ :courses:b2m37mam:labs:apo_pipeline.png?600 |}}Blokové schéma MIPS procesoru {{ :courses:b2m37mam:labs:stm32_pipeline.jpg?600 |}}Pipeline v ARM Cortex M4 (ARMv7E-M) ===== Struktura MCU ===== {{ :courses:b2m37mam:labs:stm32_structure.jpg?1000 |}} ===== Paměťový prostor ===== Architektura jádra ARM je navržena s lineárním 32-bitovým paměťovým prostorem, kde pro jednotlivé části je vyhrazeno zpravidla 512 MB paměti, což odpovídá adresám pro: * ROM paměť (programová) ''0x0000 0000'' až ''0x1FFF FFFF'' * RAM paměť (datová) ''0x2000 0000'' až ''0x3FFF FFFF'' * Periferie ''0x4000 0000'' až ''0x5FFF FFFF'' V případě, že mikrokontrolér má paměť pro oblast ROM a RAM menší než 512 MB, je využita zpravidla pouze spodní část adres, pro STM32F401RE konkrétně: * ROM paměť (programová) ''0x0000 0000'' až ''0x0007 FFFF'' (512 kB) * RAM paměť (datová) ''0x2000 0000'' až ''0x2001 7FFF'' (96 kB) {{ :courses:b2m37mam:labs:stm32_memory.jpg?600 |}} ===== Periferie MCU ===== Každý mikrokontrolér obsahuje sadu registrů pro ovládání jednotlivých periferií nebo interních obvodů/bloků. Abychom mohli s mikrokontrolérem pracovat, je třeba se seznámit se základní konfiguraci pro následujícími registry: ''RCC'', ''GPIOx'', ''NVIC'', ''EXTI'' a pochopit jejich použití. Obecně architektura ARM pracuje na bázi skupiny registrů, které jsou umístěny do adresového prostoru bázovou adresou a následně konfiguračními registry, které představují offset od bázové adresy. Přístup z jazyka C se po vložení hlavičkového souboru provádí přes strukturu daného registru, např. pro skupinu RCC a registr AHB1ENR ''RCC->AHB1ENR'' Pro přístup z jazyka symbolických adres se využívá nastavení pomocných registrů a offsetu instrukce **LDR**, viz příklad [[courses:b2m37mam:priklady:stm32:01-gpio|01 - GPIO LED]] a [[courses:b2m37mam:tutorials:asm_stm32|Vybraná instrukční sada pro STM32]] Na následujících řádcích je práce s registrem ''RCC->AHB1ENR'', který je na bázové adrese ''0x40023800'' s posunem o ''0x30''. Výsledná adresa je následně v registru R2. ldr R0, #0x40023800; ldr R1, #0x30; ldr R2, [R0, R1]; Při nastavování registru zpravidla pracujeme na úrovni bitů. Je třeba dbát na to, aby při operaci nastavení nebyly ovlivněny bity registru, které s danou operací nesouvisí. ==== RCC (Reset and clock control) ==== ** Bázová adresa je:** ''0x40023800'' Skupina registrů RCC povoluje hodinové signály do jednotlivých periferií (GPIO, TIMER, ADC, ...) podle schématu výš. K aktivaci příslušné periferii, kterou chceme používat, je třeba nejprve zavést hodinový signál do příslušného bloku, který obstarávají registry **AHBxxx** nebo **APBxxx**. Pokud se hodinový signál nezavede, daný blok nebude funkční a nebude registrovat žádné instrukce. Taktéž zajišťuje nastavení hodinových kmitočtů pro jednotlivé periferie i jádro procesoru. ----- == RCC->AHB1ENR == ** Offset registru je:** ''0x30'' Registr AHB1ENR zajišťuje povolení hodin pro GPIO brány a DMA signály. Podle následujícího obrázku např. nastavením nultého bitu do logické 1 povolíme hodinový signál do brány GPIOA, nastavením do 0 naopak hodinový signál z brány GPIOA odebereme. {{ :courses:b2m37mam:labs:rcc_ahb1enr.jpg |}} ==== GPIOx ==== ** Bázové adresy jsou pro port:** * GPIOA ''0x4002 0000'' * GPIOB ''0x4002 0400'' * GPIOC ''0x4002 0800'' * GPIOD ''0x4002 0C00'' * GPIOE ''0x4002 1000'' * GPIOH ''0x4002 1C00'' Obecná GPIOx brána je 16-ti bitová brána, která může být použita jak vstupně-výstupní port pro digitální periferie, tak i analogová brána, pokud se na dané bráně nachází analogové vstupy nebo výstupy. Digitální GPIO piny mohou být řízeny jednat softwarově, tak je možné využít i alternativní funkci předem definovaných bloků, které jsou harwarově namapované na konkrétní piny procesoru (jeden blok může být namapován i na více pinů, ale v tomto případě je třeba se rozhodnout na kterých pinech se daný blok bude používat). Namapování alternativních funkcí lze přehledně nalézt v {{ :courses:b2m37mam:stm32f401.pdf#page=45 |datahsheetu}} od strany 45 v tabulce alternativních funkcí. Na následujícím obrázku je schéma jednoho GPIO pinu {{ :courses:b2m37mam:labs:stm32_gpio.jpg?800 |}} ----- == GPIOx->MODER == ** Offset registru je:** ''0x00'' Mód pinu se nastavuje dvojicemi sousedních bitů pro každý GPIO pin portu. 00 – Input (pin bude vstupní) 01 – Output (pin bude výstupní) 11 – Analog (pin bude analogový vstup) 10 – Alternate function (pin bude sloužit k alternativní funkci, například bude připojen k jiné periferii v procesoru) {{ :courses:b2m37mam:labs:stm32_gpio_moder.jpg?800 |}} ----- == GPIOx->OTYPER == ** Offset registru je:** ''0x04'' Registrem určujeme, zda bude výstupní pin dvojčinný (push-pull) nebo s otevřeným kolektorem, který je nezbytný pro připojení k datovým sběrnicím. Každý pin dané brány je nastaven právě jedním bitem, je tedy využito dolních 16 bitů registru. 0 – Push-pull (dvojčinný) 1 – Open-drain (otevřený kolektor) {{ :courses:b2m37mam:labs:stm32_gpio_otyper.jpg?800 |}} ----- == GPIOx->OSPEEDR == ** Offset registru je:** ''0x08'' 32b registr. Opět dvojce bitů přísluší jednomu pinu. Pomocí toho registru lze nastavit maximální frekvenci výstupního signálu (samotný procesor je natolik rychlý, že by výstupní frekvence mohla být velmi vysoká, ovšem to je při delších vedeních nevyhovující a delším vedením lze pro vysoké frekvence považovat i vodič délky pár centimetrů). Ovšem snížení frekvence znamená i prodloužení doby náběžné a sestupné hrany. To ale také znamená menší dodávaný proud a tím i ušetřená energie. 00 – Low speed 01 – Medium speed 10 – Fast speed 11 – High speed Rychlosti záleží na typu procesoru, je třeba nahlédnout do datasheetu. {{ :courses:b2m37mam:labs:stm32_gpio_ospeedr.jpg?800 |}} ----- == GPIOx->PUPDR == ** Offset registru je:** ''0x0C'' 32b registr. Pro nastavení správných úrovní na vstupním pinu lze zapnout interní pull-up nebo pull-down rezistor. Pokud není připojen, úroveň na vstupním pinu je nedefinovaná (floating input) a může vést k nesprávnému vyhodnocení stavu brány. 00 – Źádné rezistory 01 – Pull-up (rezistor na napájecí napětí) 10 – Pull-down (rezistor na zem) 11 – nevyužitá kombinace {{ :courses:b2m37mam:labs:stm32_gpio_pupdr.jpg?800 |}} ----- == GPIOx->IDR == ** Offset registru je:** ''0x10'' 16b registr. Obsahuje údaj o logické hodnotě na vstupních pinech dané brány. Pin musí být nastaven jako vstupní digitální, aby mělo smysl vstup číst, protože v případě nastavení pinu jako analogového je vstupní digitální obvod odpojen. {{ :courses:b2m37mam:labs:stm32_gpio_idr.jpg?800 |}} ----- == GPIOx->ODR == ** Offset registru je:** ''0x14'' 16b registr. Nastavením bitů registru je ovládána logická úroveň jednotlivých pinů brány. Pin musí být nastaven jako vstupní digitální, aby mělo smysl výstup zapisovat, protože v případě nastavení pinu jako analogového je výstupní digitální obvod odpojen. {{ :courses:b2m37mam:labs:stm32_gpio_odr.jpg?800 |}} ----- == GPIOx->BSRR == ** Offset registru je:** ''0x18'' Registr, kterým lze nastavit nebo resetovat jednotlivé GPIO piny brány přímo, aniž by bylo třeba vstupní hodnotu číst. Spodních 16 bitů slouží pro nastavení (log. 1) pinu, vrchních 16 bitů slouží pro resetování pinu (log. 0). BSRR registr je určený pouze pro zápis a nelze z něj číst (resp. se přečte hodnota 0). 0 - Bit GPIOx portu se nezmění 1 - Bit GPIOx portu se nastaví (spodních 16 bitů) nebo vynuluje (vrchních 16 bitů) {{ :courses:b2m37mam:labs:stm32_gpio_bsrr.jpg?800 |}}