Pobierz prezentację z tego wydarzenia.
Transkrypt
Pobierz prezentację z tego wydarzenia.
#2 - BarCamp Semihalf System wbudowany? Zrób to sam! Maciej Czekaj Kto mówi? ● Inżynier systemów wbudowanych ● Linux, ARMv7, ARMv8 ● … dużych systemów wbudowanych Quiz #1 Gdzie jest interakcja z OS? 1 2 3 4 5 6 7 8 9 #include <stdio.h> #include <stdlib.h> int main(int argc, char **argv) { char *s = (char *) malloc(64); sprintf(s, "Hello, World! argc = %d", argc); puts(s); return 0; } Plan 1. 2. 3. 4. 5. Co to jest SOC? Co to jest Bootowanie? Przestrzeń adresowa SOC-a Przestrzeń adresowa programu Mój pierwszy program rozruchowy Plan 1. 2. 3. 4. 5. Co to jest SOC? Co to jest Bootowanie? Przestrzeń adresowa SOC-a Przestrzeń adresowa programu Mój pierwszy program rozruchowy SOC od środka CPU SRAM CPU 0 CPU 1 ROM Wewnętrzna szyna danych Kontroler FLASH Kontroler DDR UART ... Kontroler SATA SOC a CPU ● SOC = wszystko na jednym krzemie ○ ● CPU = budowa modularna ○ ● prawie wszystko za wyjątkiem: ■ pamięci trwałej (FLASH) ■ pamięci operacyjnej (DRAM) ■ zasilania peryferia na zewn szynie, n.p. PCI Hybrydy: ○ ○ Intel Xeon D ■ - zintegrowany Ethernet 10G Serwerowe ARM-y:, np ThunderX, X-Gene ■ wewnętrzna i zewnętrzna szyna PCI Alwinner A20 Cubieboard 2 Plan 1. 2. 3. 4. 5. Co to jest SOC? Co to jest Bootowanie? Przestrzeń adresowa SOC-a Przestrzeń adresowa programu Mój pierwszy program rozruchowy Bootowanie na SOC-u Allwinner A20 SD SD SD 48KB SRAM DDR DDR Boot ROM Linux Boot 0 Boot 1 U-Boot Dlaczego tak wiele etapów? ● Ekonomia bootowania: ○ ○ ● ROM ~ kilka KB kodu, SRAM (cache L1) <= 32 Kb Elastyczność ○ ○ ○ U-boot nie musi “znać” całego SOC-a Standardowe ładowanie OS Podział S/W na bloki: ■ firmware platformowy ■ loader ■ OS Plan 1. 2. 3. 4. 5. Co to jest SOC? Co to jest Bootowanie? Przestrzeń adresowa SOC-a Przestrzeń adresowa programu Mój pierwszy program rozruchowy Co to jest przestrzeń adresowa? ● ● ● ● Jedna szyna na wszystkie dane Wartość adresu decyduje o przeznaczeniu To jest pamięć fizyczna! MMU pozwala “przemapować” ma dowolną przestrzeń wirtualną CPU 32 - bitowa szyna danych SRAM ROM DDR UART (I/O) Mapa pamięci Allwinner-a A20 4GB Boot ROM 4GB - 64KB= 0xFFFF 0000 3GB = 0xC000 0000 DRAM 1GB = 0x4000 0000 I/O 28MB = 0x01C0 0000 48KB = 0x0000 C000 SRAM 0x0000 0000 Plan 1. 2. 3. 4. 5. Co to jest SOC? Co to jest Bootowanie? Przestrzeń adresowa SOC-a Przestrzeń adresowa programu Mój pierwszy program rozruchowy Quiz #2 Gdzie trafią zmienne? static int x[1]; static int y[1] = {0xbabababa}; void foo(const char *s,int *i, int *j) {} void _start(void) { foo("Hello World", y, x); } Co robi linker? Idx Name 0 .text ENTRY(_start) SECTIONS Size 0000004c VMA 00008094 LMA File off 00008094 00000094 Algn 2**2 CONTENTS, ALLOC, LOAD, READONLY, CODE 1 .rodata { 0000000c 000080e0 000080e0 000000e0 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA . = 0x2000 2 .data .text : { hello.o (.text) 00000004 000100ec 000000ec 2**2 000000f0 2**2 CONTENTS, ALLOC, LOAD, DATA 3 .bss *(.text) 00000004 000100f0 000100f0 ALLOC } <...> .rodata : { *(.rodata) } Contents of section .text: .data : { *(.data) } <...> .bss : { *(.bss COMMON) } Contents of section .rodata: } 000100ec 80e0 48656c6c 6f20576f 726c6400 Hello World . Contents of section .data: 100ec babababa <...> .... Plan 1. 2. 3. 4. 5. Co to jest SOC? Co to jest Bootowanie? Przestrzeń adresowa SOC-a Przestrzeń adresowa programu Mój pierwszy program rozruchowy Wprowadzenie do ARMv7-a ● ● ● Wszystkie rejestry to 32 bity Boot w SVC | HYP | Monitor Przełączanie trybu: ○ ○ ○ http://www.keil.com/support/man/docs/armasm/armasm_dom1359731128950.htm CPSR (status) SP (stos) PC (bieżąca instrukcja) CPSR - Current Program Status Register SPSR - Saved Program Status Register http://www.freescale.com/files/training_pdf/FTF/2014/americas/WBNR_FTF2014_NET_F0143.pdf?lang_cd=en Rozruch Allwinner-a A20 Boot0 wyszukuje program Boot1: 1. 2. 3. 4. 5. 6. Jeśli pin diagnostyczny jest włączony, wchodzi do trybu FEL Zewn karta SD NAND Flash 2-ga karta SD SPI Flash FEL Tryb diagnostyczny USB: FEL 1. 2. Boot0 uruchamia programator USB FEL oczekuje na komendy z zewnątrz, np z PC: a. b. c. d. zapis do pamięci bloku danych (może to być obraz programu) zapis do pamięci wartości (np. rejestr) odczyt z pamięci wartości (np. rejestr) skok pod adres (wykonanie programu) $ fel write 0x2000 image.bin $ fel exe 0x2000 Schemat działania programu rozruchowego 1. Boot ROM wchodzi w FEL 1.1. 2. Skok do 0x2000 2.1. 3. Zapis programu pod 0x2000 Przygotowanie minimalnego środowiska uruch. dla C Skok do main() Szybki kurs asemblera ARM .global _start /* Zachowaj na stosie rejestry sp, lr */ push {r0, lr} _start: /* Zablokuj przerwania , ustaw tryb na SVC */ mrs r0, cpsr @ r0 = rejestr specjalny CPSR bic r0, r0, #0x1f @ r0 &= 0x1f, wyczyść CPSR[0-4] orr r0, r0, #0xd3 @ r0 |= 0xd3 FIQ=0 IRQ=0 tryb=SVC msr cpsr,r0 @ CPSR = r0 /* Zachowaj rejestr sp */ mov r0, sp @ sp = r0, r0=stos dla FEL /* Ustaw nowy stos dla funkcji main() */ ldr sp, =stack_top @ sp = adres symbolu stack_top bl main @ wywołaj funkcję main /* Przyrwóć ze stosu sp, lr */ pop {r0, lr} mov sp, r0 /* Wróć do trybu FEL */ bx lr @ powrót z funkcji /* Pułapka */ end: b end Stos programowy stack_top -4 -8 Stos Boot0 ... Kod Boot0 ... sp lr main .data ... Funkcja main() void uart_putc( char c) { while (!TX_READY) ; writel(c, UART_THR); } void uart_puts( const char *s) { while (*s) uart_putc(*s++); } void main(void) { uart_init(); uart_puts( "Hello world! \n\r"); } Skrypt linkera ENTRY(_start) SECTIONS { . = 0x2000; /* Zaczynaj od 0x2000 */ .text : { start.o (.text) *(.text) } .rodata : { *(.rodata) } .data : { *(.data) } .stack : { . = ALIGN(8); /* Stos wyrównany do 8 */ . = . + 0x400; /* 1KB */ stack_top = .; } .bss ALIGN(4) : { /* .bss wyrównany do 4 */ bss_start = .; *(.bss COMMON) bss_end = ALIGN(4) /* .bss kończy się wyrównaniem do 4 */; } } Kompilacja arm-linux-gnueabihf-gcc -g -marm arm-linux-gnueabihf-gcc -c -o main.o main.c -c -o start.o start.S arm-linux-gnueabihf-ld -T image-sram.lds -Ttext=0x2000 main.o start.o -o image.elf Map=image.map arm-linux-gnueabihf-objcopy -O binary image.elf image.bin ● ● ld - “surowy” linker (gcc dodaje biblioteki + skrypt) objcopy - konwersja pliku wykonywalnego Źródła ● Boot ROM Allwinner-a ○ ● U-Boot ○ ● https://github.com/allwinner-zh/bootloader/tree/master/basic_loader/boot0 http://git.denx.de/?p=u-boot.git;a=summary Linux Sunxi ○ https://linux-sunxi.org/Main_Page Dziękuję! UART UART_RBR 0x00 UART Receive Buffer Register UART_THR 0x00 UART Transmit Holding Register UART_DLL 0x00 UART Divisor Latch Low Register UART_DLH 0x04 UART Divisor Latch High Register UART_LCR 0x0C UART Line Control Register void uart_init(void) { volatile uint32_t *uart_clock = (uint32_t *) 0x01C2006C; ... /* Włączenie zegara dla urządzenia UART na szynie APB */ *uart_clock &= ~(1 << (16 + UART_PORT)); /* Trzeba odczekać parę cykli zegara */ delay(100); *uart_clock |= (1 << (16 + UART_PORT)); /* Ustaw piny 22 i 23 portu B na UART0 RX & UART0_TX */ *PB2 |= 2 << 28 | 2 << 24; /* Piny muszą być wysterowane jako pullup (wartość 2) dla pinów 22 i 23 portu B */ *PB_PULL1 |= (2 << ((22 - 16) * 2)) | (2 << ((23 - 16) * 2)); /* Aktywuj konfigurację szybkości transmisji */ writel(UART_LCR_DLAB, UART_LCR); /* Ustaw prędkość portu na 115200 baud */ writel(0, UART_DLH); writel(BAUD_115200, UART_DLL); /* Wyłącz konf. trasmisji i ustaw: brak parzystości, 1 bit stopu, długość słowa 8 bitów */ writel(LC_8_N_1, UART_LCR); /* Czekaj 100 cykli */ delay(100); } Typy pamięci w ARMv7-a ● Normal ○ ○ ● Strongly Ordered ○ ● dostęp niedeterministyczny pamieć operacyjna (SRAM,DDR) dostęp sekwencyjny (I/O, np. operacje DMA) Device ○ ○ dostęp z efektami ubocznymi urządzenia i ich rejestry