Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Bootloadery i programy bare metal.

1,383 views

Published on

Droga, którą procesor przebywa od włączenia do uruchomienia systemu operacyjnego, jest długa, kręta i pełna pułapek. Prezentacja nakreśla jej przebieg, ze szczególnym uwzględnieniem niełatwych początków uruchamiania systemu. Aplikacja Hello World była pisana na wiele sposobów, a tutaj pojawi się kolejny: Bare Metal.

Published in: Software
  • Login to see the comments

  • Be the first to like this

Bootloadery i programy bare metal.

  1. 1. #2 - BarCamp Semihalf System wbudowany? Zrób to sam! Maciej Czekaj
  2. 2. ● Inżynier systemów wbudowanych ● Linux, ARMv7, ARMv8 Kto mówi?
  3. 3. ● … dużych systemów wbudowanych
  4. 4. Quiz #1 Gdzie jest interakcja z OS? 1 #include <stdio.h> 2 #include <stdlib.h> 3 int main(int argc, char **argv) 4 { 5 char *s = (char *) malloc(64); 6 sprintf(s, "Hello, World! argc = %d", argc); 7 puts(s); 8 return 0; 9 }
  5. 5. Plan 1. Co to jest SOC? 2. Co to jest Bootowanie? 3. Przestrzeń adresowa SOC-a 4. Przestrzeń adresowa programu 5. Mój pierwszy program rozruchowy
  6. 6. Plan 1. Co to jest SOC? 2. Co to jest Bootowanie? 3. Przestrzeń adresowa SOC-a 4. Przestrzeń adresowa programu 5. Mój pierwszy program rozruchowy
  7. 7. SOC od środka Kontroler DDR Kontroler FLASH CPU CPU 0 CPU 1 SRAM ROM UART Kontroler SATA... Wewnętrzna szyna danych
  8. 8. SOC a CPU ● SOC = wszystko na jednym krzemie ○ prawie wszystko za wyjątkiem: ■ pamięci trwałej (FLASH) ■ pamięci operacyjnej (DRAM) ■ zasilania ● CPU = budowa modularna ○ 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
  9. 9. Alwinner A20
  10. 10. Cubieboard 2
  11. 11. Plan 1. Co to jest SOC? 2. Co to jest Bootowanie? 3. Przestrzeń adresowa SOC-a 4. Przestrzeń adresowa programu 5. Mój pierwszy program rozruchowy
  12. 12. Bootowanie na SOC-u Allwinner A20 Boot 0 Boot 1 U-Boot Linux Boot ROM 48KB SRAM SDSD DDR SD DDR
  13. 13. 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
  14. 14. Plan 1. Co to jest SOC? 2. Co to jest Bootowanie? 3. Przestrzeń adresowa SOC-a 4. Przestrzeń adresowa programu 5. Mój pierwszy program rozruchowy
  15. 15. Co to jest przestrzeń adresowa? CPU SRAM ROM DDR 32 - bitowa szyna danych ● Jedna szyna na wszystkie dane ● Wartość adresu decyduje o przeznaczeniu ● To jest pamięć fizyczna! ● MMU pozwala “przemapować” ma dowolną przestrzeń wirtualną UART (I/O)
  16. 16. Mapa pamięci Allwinner-a A20 DRAM I/O SRAM Boot ROM 3GB = 0xC000 0000 0x0000 0000 1GB = 0x4000 0000 4GB - 64KB= 0xFFFF 0000 48KB = 0x0000 C000 28MB = 0x01C0 0000 4GB
  17. 17. Plan 1. Co to jest SOC? 2. Co to jest Bootowanie? 3. Przestrzeń adresowa SOC-a 4. Przestrzeń adresowa programu 5. Mój pierwszy program rozruchowy
  18. 18. 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); }
  19. 19. Co robi linker? Idx Name Size VMA LMA File off Algn 0 .text 0000004c 00008094 00008094 00000094 2**2 CONTENTS, ALLOC, LOAD, READONLY, CODE 1 .rodata 0000000c 000080e0 000080e0 000000e0 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA 2 .data 00000004 000100ec 000100ec 000000ec 2**2 CONTENTS, ALLOC, LOAD, DATA 3 .bss 00000004 000100f0 000100f0 000000f0 2**2 ALLOC <...> Contents of section .text: <...> Contents of section .rodata: 80e0 48656c6c 6f20576f 726c6400 Hello World . Contents of section .data: 100ec babababa .... <...> ENTRY(_start) SECTIONS { . = 0x2000 .text : { hello.o (.text) *(.text) } .rodata : { *(.rodata) } .data : { *(.data) } .bss : { *(.bss COMMON) } }
  20. 20. Plan 1. Co to jest SOC? 2. Co to jest Bootowanie? 3. Przestrzeń adresowa SOC-a 4. Przestrzeń adresowa programu 5. Mój pierwszy program rozruchowy
  21. 21. Wprowadzenie do ARMv7-a http://www.keil.com/support/man/docs/armasm/armasm_dom1359731128950.htm ● Wszystkie rejestry to 32 bity ● Boot w SVC | HYP | Monitor ● Przełączanie trybu: ○ CPSR (status) ○ SP (stos) ○ PC (bieżąca instrukcja)
  22. 22. 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
  23. 23. Rozruch Allwinner-a A20 Boot0 wyszukuje program Boot1: 1. Jeśli pin diagnostyczny jest włączony, wchodzi do trybu FEL 2. Zewn karta SD 3. NAND Flash 4. 2-ga karta SD 5. SPI Flash 6. FEL
  24. 24. Tryb diagnostyczny USB: FEL $ fel write 0x2000 image.bin $ fel exe 0x2000 1. Boot0 uruchamia programator USB 2. FEL oczekuje na komendy z zewnątrz, np z PC: a. zapis do pamięci bloku danych (może to być obraz programu) b. zapis do pamięci wartości (np. rejestr) c. odczyt z pamięci wartości (np. rejestr) d. skok pod adres (wykonanie programu)
  25. 25. Schemat działania programu rozruchowego 1. Boot ROM wchodzi w FEL 1.1. Zapis programu pod 0x2000 2. Skok do 0x2000 2.1. Przygotowanie minimalnego środowiska uruch. dla C 3. Skok do main()
  26. 26. Szybki kurs asemblera ARM .global _start _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 /* Zachowaj na stosie rejestry sp, lr */ push {r0, lr} 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
  27. 27. Stos programowy sp lr stack_top main - 4 ... .data - 8 Stos Boot0 Kod Boot0 ... ...
  28. 28. 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! nr"); }
  29. 29. 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 */; } }
  30. 30. Kompilacja arm-linux-gnueabihf-gcc -g -marm -c -o main.o main.c arm-linux-gnueabihf-gcc -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
  31. 31. Źródła ● Boot ROM Allwinner-a ○ https://github.com/allwinner-zh/bootloader/tree/master/basic_loader/boot0 ● U-Boot ○ http://git.denx.de/?p=u-boot.git;a=summary ● Linux Sunxi ○ https://linux-sunxi.org/Main_Page
  32. 32. Dziękuję!
  33. 33. UART /* Piny muszą być wysterowane jako pull- up (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); } 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;
  34. 34. Typy pamięci w ARMv7-a ● Normal ○ dostęp niedeterministyczny ○ pamieć operacyjna (SRAM,DDR) ● Strongly Ordered ○ dostęp sekwencyjny (I/O, np. operacje DMA) ● Device ○ dostęp z efektami ubocznymi ○ urządzenia i ich rejestry

×