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