SCALETTA LEZIONE SERT E7 -- 15 novembre 2012 1 ***** Stato attuale dello sviluppo: +--------------------------------+ |void noop(void) | |{ | | int *led; | | int state = 0; | | int c; | | | | led = (int *) 0x80840020; | | for (;;) { | | state = 1-state; | | *led ^= 2*state+1; | | for (c=0; c<100000; ++c) | | *led = *led; | | } | |} | +--------------------------------+ 1.1 ATTENZIONE: il programma NON e' corretto: funziona solo "per caso" 1.1.1 Problema principale: le variabili automatiche possono essere memorizzate sullo stack, che non e' stato predisposto 1.1.2 In questo caso le variabili sono cosi' poche che il compilatore puo' limitarsi ad usare registri 2 ****** Organizzazione del codice sorgente 2.1 Cancellare noop.c 2.2 Organizzazione dei file sorgente 2.2.1 File ts7250.h: definizioni per hardware 2.2.2 File comm.h: definizioni per software 2.2.3 File main.c: programma principale 2.3 Modifica entry point in Makefile 2.4 Scrittura funzione c_entry() in main.c +--------------------------------+ |void c_entry(void) | |{ | | int lv = 1; | | for (;;) { | | delay(1000000UL); | | lv = 1-lv; | | iomem[LED] ^= 2*lv+1; | | } | |} | +--------------------------------+ 2.5 Scrittura di delay() in main.c: +------------------------------+ |void delay(unsigned long d) | |{ | | while (d-- > 0) | | __memory_barrier(); | |} | +------------------------------+ 2.6 Scrittura di __memory_barrier() in comm.h: +---------------------------------------------+ |#define __memory_barrier() \ | | __asm__ __volatile__ ("" : : : "memory") | +---------------------------------------------+ 2.7 Definire array iomem e costante LED in ts7250.h +------------------------------------------------+ |#include | |typedef uint32_t u32; | |static volatile u32 * const iomem = (u32 *)0; | |static const unsigned int LED = 0x80840020 / 4; | +------------------------------------------------+ 2.8 Provare il programma: non funziona! Manca lo stack!! 3 *** Inizializzazione dell'ambiente di esecuzione 3. Organizzazione di un file eseguibile in sezioni e segmenti 3.1 Sezione di codice ".text" 3.1.1 Codice eseguibile del programma 3.2 Sezione di dati ".data" 3.2.1 Variabili globali non inizializzate 3.2.2 Variabili globali inizializzate a non zero 3.2.3 Variabili automatiche statiche non inizializzate 3.2.4 Variabili automatiche statiche inizializzate a non zero 3.3 Sezione di dati inizializzati a zero ".bss" 3.3.1 Variabili globali inizializzate a zero 3.3.2 Variabili statiche inizializzate a zero 3.4 Sezione di dati read-only ".rodata" 3.4.1 Costanti 3.4.2 Stringhe di caratteri 3.5 Stack del programma 3.5.1 Variabili automatiche non statiche 3.6 Heap del programma 3.6.1 Memoria allocata dinamicamente tramite malloc(), new(), ... 3.7 Esempio: +--------------------------------------------------+ |int v_glob; /* .data o .bss (common) */ | |int v_glob_init0 = 0; /* .bss */ | |int v_glob_init1 = 1; /* .data */ | |static int v_stat_glob; /* .bss */ | |static int v_stat_glob_init0 = 0; /* .bss */ | |static int v_stat_glob_init1 = 1; /* .data */ | |int main() /* .text */ | |{ | | int v_auto; /* stack */ | | int v_auto_init0 = 0; /* stack */ | | int v_auto_init1 = 1; /* stack */ | | static int v_stat_auto; /* .bss */ | | static int v_stat_auto_init0 = 0; /* .bss */ | | static int v_stat_auto_init1 = 1; /* .data */ | |} | +--------------------------------------------------+ 4. Organizzazione della memoria (provvisoria) 4.1 Segmento .text (codice eseguibile) 4.1.1 Entry point a 0x60000 4.2 Segmento .data (dati) 4.3 Stack (lunghezza 4KB, "full descending") 5. Scrivere linker script sert.lds +---------------------------+ |ENTRY(_reset) | |mem_start = 0x0060000; | |mem_end = 0x1ff9000; | |SECTIONS | |{ | | . = mem_start; | | .startup . : { | | startup.o(.text) | | . = ALIGN(4); | | } | | .text : { | | *(.text) | | . = ALIGN(4); | | } | | .rodata : { | | *(.rodata) | | . = ALIGN(4); | | } | | .data : { | | *(.data) | | . = ALIGN(4); | | } | | _stack_top = mem_end; | |} | +---------------------------+ 6. Scrivere file Assembly startup.S +----------------------------+ | .text | | .code 32 | | | | .global _reset | |_reset: | | ldr sp,=_stack_top | | bl c_entry | | b . | +----------------------------+ 7. Aggiornare Makefile per compilare file Assembler 8. Aggiornare Makefile per utilizzare sert.lds 9. Inizializzazione della sezione .bss 9.1 Aggiunta al linker script sert.lds (prima dello stack) +---------------------+ | .bss : { | | _bss_start = .; | | *(.bss) | | *(COMMON) | | . = ALIGN(4); | | _bss_end = .; | | } | +---------------------+ 9.2 Creazione file init.c per inizializzazione +------------------------------------------+ |#include "comm.h" | |#include "ts7250.h" | |extern int main(void); | |static void fill_bss(void) | |{ | | extern u32 _bss_start, _bss_end; | | u32 *p; | | for (p=&_bss_start; p<&_bss_end; ++p) | | *p = 0UL; | |} | |void _init(void) | |{ | | fill_bss(); | | main(); | |} | +------------------------------------------+ 9.3 Modifica in main.c: funzione c_entry() cambia nome in main() 9.4 Modifica in startup.S: salto a _init invece che c_entry =====