Architektura ARM. Marcin Peczarski. 17 lutego Instytut Informatyki Uniwersytetu Warszawskiego

Podobne dokumenty
Architektura ARM. Materiały do wykładu. Marcin Peczarski. 19 maja Instytut Informatyki Uniwersytet Warszawski

Programowanie mikrokontrolerów 2.0

(Rysunek z książki T.Starecki. Mikokontrolery jednoukładowe rodziny 51. NOZOMI W-wa 1996)

Programowanie mikrokontrolerów 2.0

Programowanie mikrokontrolerów 2.0

Programowanie mikrokontrolerów 2.0

Szkolenia specjalistyczne

Jak przenieść kod z ARM7 do Cortex-M3?

PMiK Programowanie Mikrokontrolera 8051

Kompilator języka C na procesor 8051 RC51 implementacja

METODY I JĘZYKI PROGRAMOWANIA PROGRAMOWANIE STRUKTURALNE. Wykład 02

Programowanie mikrokontrolerów 2.0

/* dołączenie pliku nagłówkowego zawierającego deklaracje symboli dla wykorzystywanego mikrokontrolera */ #include <aduc834.h>

Wykład 9. Obsługa przerwań

Technika mikroprocesorowa I Studia niestacjonarne rok II Wykład 2

Wykład. Materiały bazują częściowo na slajdach Marata Dukhana

Typy złożone. Struktury, pola bitowe i unie. Programowanie Proceduralne 1

Instytut Teleinformatyki

Programowanie w asemblerze ARM wprowadzenie

PRZERWANIA. 1. Obsługa zdarzeń, odpytywanie i przerwania Obsługa zdarzeń jest jedną z kluczowych funkcji w prawie każdym systemie czasu rzeczywistego.

Programowanie hybrydowe C (C++) - assembler. MS Visual Studio Inline Assembler

Wykład 2. Mikrokontrolery z rdzeniami ARM

Programowanie mikroprocesorów jednoukładowych

Wstęp. do języka C na procesor (kompilator RC51)

3. Sygnały zegarowe i ich konfiguracja, mechanizmy bezpieczeństwa... 47

Inżynieria Wytwarzania Systemów Wbudowanych

MIKROKONTROLERY I MIKROPROCESORY

Technika mikroprocesorowa I Wykład 2

Wykład 1

Metody obsługi zdarzeń

XMEGA. Warsztaty CHIP Rok akademicki 2014/2015

Podstawy programowania. Wykład: 5. Instrukcje sterujące c.d. Stałe, Typy zmiennych c.d. dr Artur Bartoszewski -Podstawy programowania, sem 1 - WYKŁAD

Mikrokontroler ATmega32. System przerwań Porty wejścia-wyjścia Układy czasowo-licznikowe

PROGRAMOWANIE w C prolog

4 Literatura. c Dr inż. Ignacy Pardyka (Inf.UJK) ASK MP.01 Rok akad. 2011/ / 24

1. Wartość, jaką odczytuje się z obszaru przydzielonego obiektowi to: a) I - wartość b) definicja obiektu c) typ oboektu d) p - wartość

Programowanie mikrokontrolerów AVR

Podstawowe urządzenia peryferyjne mikrokontrolera ATmega8 Spis treści

Wątek - definicja. Wykorzystanie kilku rdzeni procesora jednocześnie Zrównoleglenie obliczeń Jednoczesna obsługa ekranu i procesu obliczeniowego

Zygmunt Kubiak Instytut Informatyki Politechnika Poznańska

Programowanie mikrokontrolerów 2.0

Wykład 2. Mikrokontrolery z rdzeniami ARM

PROGRAMOWALNE SYSTEMY MECHATRONIKI

Mikrokontroler ATmega32. Język symboliczny

Wykład VII. Programowanie. dr inż. Janusz Słupik. Gliwice, Wydział Matematyki Stosowanej Politechniki Śląskiej. c Copyright 2014 Janusz Słupik

Instytut Teleinformatyki

Architektura komputerów

Środowisko Keil. Spis treści. Krzysztof Świentek. Systemy wbudowane. 1 Trochę teorii. 2 Keil

Programowanie mikrokontrolerów 2.0

Architektura Systemów Komputerowych. Jednostka ALU Przestrzeń adresowa Tryby adresowania

Przerwania, polling, timery - wykład 9

Opóźnienia w STM32 (2)

Przerwania w systemie mikroprocesorowym. Obsługa urządzeo wejścia/wyjścia

Język C - podstawowe informacje

Technika mikroprocesorowa. W. Daca, Politechnika Szczecińska, Wydział Elektryczny, 2007/08

Co to jest sterta? Sterta (ang. heap) to obszar pamięci udostępniany przez system operacyjny wszystkim działającym programom (procesom).

Ćwiczenie nr 6. Programowanie mieszane

Architektura mikroprocesorów TEO 2009/2010

Programowanie mikrokontrolerów 2.0

wykład III uzupełnienie notatek: dr Jerzy Białkowski Programowanie C/C++ Język C - zarządzanie pamięcią, struktury,

Połączenie DS18B20 z STM32. Projekt dla środowiska CooCox

Wykład 15. Literatura. Kompilatory. Elementarne różnice. Preprocesor. Słowa kluczowe

Układ wykonawczy, instrukcje i adresowanie. Dariusz Chaberski

Zadanie Zaobserwuj zachowanie procesora i stosu podczas wykonywania następujących programów

Wstęp do wiadomości teoretycznych (nie, nie jest to masło maślane ani wstęp, wstępów proszę cierpliwie czytać)

Programowanie Niskopoziomowe

Programowanie mikrokontrolerów AVR z rodziny ATmega.

Spis treœci. Co to jest mikrokontroler? Kody i liczby stosowane w systemach komputerowych. Podstawowe elementy logiczne

Wprowadzenie do podstaw programowania AVR (na przykładzie mikrokontrolera ATmega 16 / 32)

Temat 7. Programowanie mikrokontrolerów z rodziny PIC16 w języku C przy użyciu HI-TECH C for PIC10/12/16

Instytut Teleinformatyki

Poradnik programowania procesorów AVR na przykładzie ATMEGA8

Projektowanie klas c.d. Projektowanie klas przykład

Procesor ma architekturę rejestrową L/S. Wskaż rozkazy spoza listy tego procesora. bgt Rx, Ry, offset nand Rx, Ry, A add Rx, #1, Rz store Rx, [Rz]

PRZERWANIA. P1 - Procedura obslugi przerwania. Obsługa zdarzenia Z1 poprzez procedurę obsługi przerwania P1

1. Wprowadzenie Programowanie mikrokontrolerów Sprzęt i oprogramowanie... 33

Język C zajęcia nr 11. Funkcje

Języki programowania C i C++ Wykład: Typy zmiennych c.d. Operatory Funkcje. dr Artur Bartoszewski - Języki C i C++, sem.

Funkcja (podprogram) void

Język programowania: Lista instrukcji (IL Instruction List)

Architektura Systemów Komputerowych. Rozwój architektury komputerów klasy PC

Instytut Teleinformatyki

PROGRAMOWANIE NISKOPOZIOMOWE. Adresowanie pośrednie rejestrowe. Stos PN.04. c Dr inż. Ignacy Pardyka. Rok akad. 2011/2012

PROGRAMOWANIE SYSTEMÓW CZASU RZECZYWISTEGO

Instrukcja do ćwiczeń

1.2. Architektura rdzenia ARM Cortex-M3...16

Podstawowe urządzenia peryferyjne mikrokontrolera ATmega8 Spis treści

Co nie powinno być umieszczane w plikach nagłówkowych:

Wstęp Architektura... 13

Systemy operacyjne system przerwań

Prezentacja systemu RTLinux

Wstęp do programowania

Układ sterowania, magistrale i organizacja pamięci. Dariusz Chaberski

Wykład 4. Przegląd mikrokontrolerów 16-bit: - PIC24 - dspic - MSP430

2 Przygotował: mgr inż. Maciej Lasota

Procesory firmy ARM i MIPS

Część I - Sterownik przerwań 8259A i zegar/licznik 8253

MARM. Laboratorium 1 system zegarów, porty wejścia/wyjścia. M. Suchenek

Podstawy programowania komputerów

Programowanie mikrokontrolerów 2.0

Transkrypt:

Architektura ARM Marcin Peczarski Instytut Informatyki Uniwersytetu Warszawskiego 17 lutego 2012

ARM Międzynarodowa firma, mająca główną siedzibę w Cambrdge w Wielkiej Brytanii. Projektuje i sprzedaje licencje na rdzenie ARM. Nie produkuje chipów. Podobno ok. 3/4 telefonów komórkowych i systemów wbudowanych zawiera rdzenie ARM.

Przegląd aktualnych wersji architektury ARM Źródło: http://www.arm.com

Zapowiadana 64-bitowa wersja architektury ARM Źródło: http://www.arm.com

ARM = Advanced RISC Machines Zestaw instrukcji wzorowany na RISC, aby łatwo potokować: ldr r3, [r1, #36] adds r2, r3, #1 RISC-owe wywoływanie procedur: bl bx etykieta lr Prawie każda instrukcja może być wykonywana warunkowo: movge r7, r4 Argument można przesunąć przed wykonaniem operacji: orr r1, r1, r4, lsl #12 str r2, [r4, r0, lsl #2] Występują instrukcje typowo CISC-owe: push pop {r4, r5, lr}; prolog funkcji {r4, r5, pc}; epilog funkcji

Cortex-M3/M4 Rdzenie do zastosowań mikrokontrolerowych Cienkokońcówkowe Jednolita przestrzeń adresowa architekura typu Princeton Osobne szyny do pamięci danych i programu organizacja typu Hardward Na kolejnych slajdach omawiam architekturę Cortex-M3, posługując się przykładami przetestowanymi na mikrokontrolerach z rodziny STM32.

Przykład mikrokontrolera z rdzeniem Cortex-M3 Źródło: http://www.st.com

Przestrzeń adresowa Źródło: http://mcu.ee

Bezpośrednie adresowanie bitów bitaddr = baseaddr + 32 dwordoffset + 4 bitnumber Źródło: http://www.kimura-lab.net

Organizacja pamięci programu Flash sidata = etext.data.rodata RAM stack heap estack end ebss.bss.text edata = sbss 0x08000000.isr vector.data sdata = 0x20000000

Kod startowy deklaracje extern unsigned long _sidata; extern unsigned long _sdata; extern unsigned long _edata; extern unsigned long _sbss; extern unsigned long _ebss; extern unsigned long _estack; int main(void);

Kod startowy wykonywany po wyzerowaniu static void Reset_Handler(void) { unsigned long *src, *dst; for (dst = &_sdata, src = &_sidata; dst < &_edata; ++dst, ++src) *dst = *src; for (dst = &_sbss; dst < &_ebss; ++dst) *dst = 0; main(); for (;;); }

Tablica przerwań attribute ((section(".isr_vector"))) void (* const g_pfnvectors[])(void) = { (void*)&_estack, Reset_Handler, /* Przerwania rdzenia Cortex-M3 */ NMI_Handler, HardFault_Handler, MemManage_Handler, BusFault_Handler, UsageFault_Handler,... SysTick_Handler, /* Przerwania układów peryferyjnych */... };

Zaślepki dla nieużywanych przerwań static void Default_Handler(void) { for (;;); } #define WEAK attribute ((weak)) void WEAK NMI_Handler(void); #pragma weak NMI_Handler = Default_Handler

Połączenie tego w całość (1) MEMORY { FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 128K RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 20K } _minimum_stack_and_heap = 2560; SECTIONS {... }

Połączenie tego w całość (2).text : { KEEP(*(.isr_vector)) *(.text) *(.text.*) *(.rodata) *(.rodata.*). = ALIGN(4); _etext =.; _sidata = _etext; } >FLASH =0xff

Połączenie tego w całość (3).data : AT(_sidata) {. = ALIGN(4); _sdata =.; *(.data) *(.data.*). = ALIGN(4); _edata =.; } >RAM =0

Połączenie tego w całość (4).bss : {. = ALIGN(4); _sbss =.; *(.bss) *(.bss.*) *(COMMON). = ALIGN(4); _ebss =.; } >RAM

Połączenie tego w całość (5) _estack = (ORIGIN(RAM) + LENGTH(RAM)) & 0xFFFFFFFC; ASSERT(_ebss + _minimum_stack_and_heap <= _estack, "There is not enough space in RAM.") PROVIDE(end = _ebss);...

Zaświecenie diody hard-code Dioda jest podłączona do wyprowadzenia PB8. typedef volatile uint32_t reg_t; uint32_t tmp; *(reg_t*)(0x40021000 + 0x18) = 0x00000008; tmp = *(reg_t*)(0x40010c00 + 0x04); tmp &= 0xfffffff0; tmp = 0x00000001; *(reg_t*)(0x40010c00 + 0x04) = tmp; *(reg_t*)(0x40010c00 + 0x10) = 1 << 8;

Biblioteki CMSIS Cortex Microcontroller Software Interface Standard STM32... x StdPeriph Driver biblioteka obsługująca peryferie specyficzne dla danego modelu mikrokontrolera

Zaświecenie diody z użyciem CMSIS Trzeba włączyć właściwy plik nagłówkowy (jeden): #include <stm32f10x.h> #include <stm32f2xx.h> #include <stm32l1xx.h> Potem już jest łatwiej: uint32_t tmp; RCC->APB2ENR = RCC_APB2ENR_IOPBEN; tmp = GPIOB->CRH; tmp &= ~(GPIO_CRH_MODE8_1 GPIO_CRH_CNF8_0 GPIO_CRH_CNF8_1); tmp = GPIO_CRH_MODE8_0; GPIOB->CRH = tmp; GPIOB->BSRR = GPIO_BSRR_BS8;

Zaświecenie diody z użyciem StdPeriph Driver Trzeba włączyć właściwe pliki nagłówkowe, np.: #inlcude <stm32f10x_gpio.h> #inlcude <stm32f10x_rcc.h> Potem już jest łatwo, choć nie zawsze wydajnie: GPIO_InitTypeDef GPIO_InitStruct; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); GPIO_StructInit(&GPIO_InitStruct); GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz; GPIO_Init(GPIOB, &GPIO_InitStruct); GPIO_WriteBit(GPIOB, GPIO_Pin_8, Bit_SET);

CMSIS dostarcza funkcji dla operacji niedostępnych w języku C Włączamy odpowiedni plik nagłówkowy: #include <stm32...x.h> I możemy używać różnych ciekawych funkcji: #define htons(x) REV16(x) #define htonl(x) REV(x)

Używając GCC, można je zdefiniować nieco bardziej efektywnie #if defined GNUC #define htons(x) ({ \ uint16_t result; \ asm ("rev16 %0, %1" : "=r" (result) : "r" (x)); \ result; \ }) #define htonl(x) ({ \ uint32_t result; \ asm ("rev %0, %1" : "=r" (result) : "r" (x)); \ result; \ }) #endif

Rejestry R0 do R12 rejestry ogólnego przeznaczenia SP (R13, MSP, PSP) wskaźnik stosu LR (R14) adres powrotu PC (R15) licznik programu PSR (APSR, IPSR, EPSR) rejestr znaczników PRIMASK, FAULTMASK, BASEPRI rejestry maskujące przerwania CONTROL rejestr sterujący trybami pracy rdzenia

Przerwania Reset NMI Hard fault Memory management fault Bus fault Usage fault Supervisor call PendSV SysTick IRQ0... IRQ67 Zerowanie rdzenia Przerwanie niemaskowalne Błąd podczas obsługi przerwania Naruszenie ochrony pamięci Błąd szyny pamięci Niepoprawna instrukcja lub argument instrukcji Wywołanie usługi systemu operacyjnego za pomocą instrukcji SVC Wywołanie planisty w celu przełączenia kontekstu, w założeniu niski priorytet Licznik systemowy, cykliczne przerwanie systemu operacyjnego, w założeniu wysoki priorytet Przerwania zgłaszane przez peryferie

Eskalacja wyjątków Źródło: http://www.eetimes.com

ABI funkcji i przerwań Pierwsze 4 argumenty funkcji są przekazywane w rejestrach R0 do R3, pozostałe przez stos. Funkcja może dowolnie modyfikować rejestry R0 do R3 i R12. Funkcja musi przywrócić wartości rejestrów R4 do R11, LR i SP sprzed wywołania. Przed wywołaniem procedury przerwania procesor odkłada na stos rejestry R0 do R3, R12, adres powrotu, PSR, LR. Funkcja, która ma obsługiwać przerwanie, to najzwyklejsza funkcja języka C o sygnaturze void Handler(void); Nie są potrzebne żadne dodatkowe atrybuty! attribute ((interrupt))

Łańcuchowa obsługa przerwań Źródło: http://www.arm.com Może dochodzić do zagłodzenia!

Łańcuchowa obsługa przerwań, dalsze przykłady Źródło: http://www.arm.com

ABI przerwań, problem Skąd procesor wie, czy instrukcja bx lr jest powrotem ze zwykłej funkcji, czy z obsługi przerwania (trzeba coś zdjąć ze stosu)? Czy ktoś zauważył problem?

Tryby pracy rdzenia Źródło: http://sigalrm.blogspot.com Są dwa stosy: MSP dla trybów uprzywilejowanych (ang. privileged thread, privileged handler), PSP dla trybu użytkownika (ang. user thread).

ABI przerwań, rozwiązanie problemu Przed wywołaniem funkcji obsługującej przerwanie procesor zapisuje do rejestru LR wartość: 0xfffffff1 powrót do obsługi innego przerwania (ang. privileged handler), odtwórz stan z MSP, po powrocie używaj MSP; 0xfffffff9 powrót do wątku uprzywilejowanego (ang. privileged thread), odtwórz stan z MSP, po powrocie używaj MSP; 0xfffffffd powrót do wątku użytkownika (ang. user thread), odtwórz stan z PSP, po powrocie używaj PSP.

Priorytety przerwań Przerwanie może mieć priorytet od 3 do 15. Czym mniejsza wartość, tym większy priorytet. Trzy przerwania mają ustalony, niekonfigurowalny priorytet: Reset priorytet 3, NMI priorytet 2, HardFault priorytet 1. Pozostałym przerwaniom można nadać priorytet, który jest liczbą 4-bitową i składa się z dwóch pól: priorytet wywłaszczania, podpriorytet. Liczba bitów przeznaczonych na priorytet wywłaszczania jest konfigurowalna. Pozostałe bity są przeznaczone na podpriorytet.

Numery przerwań CMSIS definiuje typ wyliczeniowy: typedef enum IRQn {... }; Przerwania zgłaszane przez rdzeń mają ujemne numery: NonMaskableInt_IRQn = -14, MemoryManagement_IRQn = -12, BusFault_IRQn = -11, UsageFault_IRQn = -10,... SysTick_IRQn = -1, Przerwania zgłaszane przez peryferie mają nieujemne numery: WWDG_IRQn = 0,... TIM2_IRQn = 28,...

Blokowanie przerwań o konfigurowalnych priorytetach Użyjemy CMSIS: #include <stm32f10x.h> #include <stm32f2xx.h> #include <stm32l1xx.h> Makro deklarujące zmienną, przechowującą poprzedni stan: #define SYS_ARCH_DECL_PROTECT(x) \ uint32_t x Makro zapisujące aktualny stan i blokujące przerwania: #define SYS_ARCH_PROTECT(x) \ (x = get_primask(), disable_irq()) Makro przywracające poprzedni stan: #define SYS_ARCH_UNPROTECT(x) \ set_primask(x)

Użycie SYS_ARCH_DECL_PROTECT(x); /* Tutaj może zostać zgłoszone przerwanie w dowolnym momencie. */ SYS_ARCH_PROTECT(x); /* Tutaj kod wykonuje się przy zablokowanych przerwaniach. */ SYS_ARCH_UNPROTECT(x);

Wersja makr dla GCC #if defined GNUC #define SYS_ARCH_DECL_PROTECT(x) \ uint32_t x #define SYS_ARCH_PROTECT(x) ({ \ asm volatile ( \ "mrs %0, PRIMASK\n\t" \ "cpsid i" : \ "=r" (x) : \ ); \ }) #define SYS_ARCH_UNPROTECT(x) ({ \ asm volatile ("msr PRIMASK, %0" : : "r" (x)); \ }) #endif

Konfigurowanie priorytetu przerwania Wystarczą 4 priorytety wywłaszczania i 4 podpriorytety: #define PRE_PRIO_BITS 2 #define SET_IRQ_PREEMPTION_PRIORITY_BITS() \ NVIC_SetPriorityGrouping(7 - PRE_PRIO_BITS) Priorytety (wywłaszczania) wygodnie jest nazwać: #define HIGH_IRQ_PRIO 1 #define MIDDLE_IRQ_PRIO 2 #define LOW_IRQ_PRIO 3 CMSIS dostarcza kilka funkcji: NVIC_SetPriority(SysTick_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), HIGH_IRQ_PRIO, 0));

Konfigurowanie priorytetu przerwania, cd. Przerwania zgłaszane przez peryferie można też konfigurować za pomocą StdPeriph Driver: #include <misc.h> NVIC_InitTypeDef NVIC_InitStruct; NVIC_InitStruct.NVIC_IRQChannel = TIM2_IRQn; NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = LOW_IRQ_PRIO; NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0; NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStruct);

Blokowanie przerwań wg priorytetu Makro deklarujące zmienną, która przechowuje informację o blokowanych przerwaniach: #define IRQ_DECL_PROTECT(prv) \ uint32_t prv Makro zapisujące stan aktualnie blokowanych przerwań i blokujące przerwania o priorytecie niższym lub równym lvl: #define IRQ_PROTECT(prv, lvl) \ (prv = get_basepri(), \ set_basepri((lvl) << (8 - PRE_PRIO_BITS))) Makro przywracające poprzedni stan blokowania przerwań: #define IRQ_UNPROTECT(prv) \ set_basepri(prv)

Wersja makr dla GCC #if defined GNUC #define IRQ_DECL_PROTECT(prv) \ uint32_t prv #define IRQ_PROTECT(prv, lvl) ({ \ uint32_t tmp; \ asm volatile ( \ "mrs %0, BASEPRI\n\t" \ "movs %1, %2\n\t" \ "msr BASEPRI, %1" : \ "=r" (prv), "=r" (tmp) : \ "i" ((lvl) << (8 - PRE_PRIO_BITS)) \ ); \ }) #define IRQ_UNPROTECT(prv) ({ \ asm volatile ("msr BASEPRI, %0" : : "r" (prv)); \ }) #endif

Inna wersja makr dla GCC #if defined GNUC #define IRQ_DECL_PROTECT(prv) \ uint32_t prv #define IRQ_PROTECT(prv, lvl) ({ \ uint32_t tmp; \ tmp = (lvl) << (8 - PRE_PRIO_BITS); \ asm volatile ("mrs %0, BASEPRI" : "=r" (prv)); \ asm volatile ("msr BASEPRI, %0" : : "r" (tmp)); \ }) #define IRQ_UNPROTECT(prv) ({ \ asm volatile ("msr BASEPRI, %0" : : "r" (prv)); \ }) #endif

O czym jeszcze można opowiedzieć? Tryby uśpienia Wsparcie dla DSP Przykłady użycia peryferii...