Viertens, die zweite Stufe

globale Daten

Stellungnahme

# < lib_arm\board.c >

DECLARE_GLOBAL_DATA_PTR;

Definition

# < include\asm\global_data.h >

typedef struct globale_daten {

bd_t *bd;

unsigned long flags;

vorzeichenlose lange Baudrate;

unsigned long have_console; /* serial_init() wurde aufgerufen */

unsigned long env_addr; /* Adresse der Umgebungsstruktur */

unsigned long env_valid; /* Prüfsumme der Umgebung gültig? */

unsigned long fb_base; /* Basisadresse des Framebuffers */

#ifdef CONFIG_VFD

unsigned char vfd_type; /* Anzeigetyp */

#endif

#wenn 0

unsigned long cpu_clk; /* CPU-Takt in Hz! */

unsigned long bus_clk;

phys_size_t ram_size; /* RAM-Größe */

unsigned long reset_status; /* Statusregister beim Booten zurücksetzen */

#endif

nichtig **jt; /* Tabelle springen */

} gd_t;

// Deklarieren Sie einen gd_t-Typ-Zeiger gd, der in Register r8 gespeichert ist

#define DECLARE_GLOBAL_DATA_PTR registrieren flüchtig gd_t *gd asm ("r8")

Feld Beschreibung

bd_t *bd: Board-Info-Datenstrukturdefinition, befindet sich in der Datei include/asm-arm/u-boot.h definition, hauptsächlich um die relevanten Parameter des Entwicklungsboards zu speichern.

    typedef struct bd_info {

        int bi_baudrate; /* Baudrate der seriellen Konsole */

        unsigned long bi_ip_addr; /* IP Adresse */

        struct Umgebung_s *bi_env;

        ulong bi_arch_number; /* eindeutige ID für dieses Board */

        ulong bi_boot_params; /* wo dieses Board Parameter erwartet */

        struct /* RAM-Konfiguration */

        {

            Vorsprung;    

   Kopf Größe;

        }bi_dram[CONFIG_NR_DRAM_BANKS];

    } bd_t;

unsigned long env_addr: Die Adresse der Umgebungsvariable.

unsigned long ram_top: die oberste Adresse des RAM-Bereichs

unsigned long relocaddr: Adresse nach UBOOT-Umleitung

phys_size_t ram_size: Größe des physischen Arbeitsspeichers

unsigned long irq_sp: Interrupt-Stack-Adresse

unsigned long start_addr_sp: Stapeladresse

unsigned long reloc_off: Verschiebungsoffset von uboot

struct global_data *new_gd: die umgeleitete struct global_data-Struktur

const void *fdt_blob: die dtb-Adresse unseres Geräts

void *new_fdt: dtb-Adresse nach Umzug

unsigned long fdt_size: die Länge von dtb

struct udevice *cur_serial_dev: aktuell verwendetes serielles Gerät.

Initialisierungssequenz (Board-Initialisierungsfunktionssequenz)

Prototyp

# < lib_arm\board.c >

typedef int (init_fnc_t) (void);

int print_cpuinfo (leer);

init_fnc_t *init_sequence[] = {

#falls definiert(CONFIG_ARCH_CPU_INIT)

arch_cpu_init, /* grundlegende Arch-CPU-abhängige Einrichtung */

#endif

board_init, /* grundlegende kartenabhängige Einrichtung */

#falls definiert(CONFIG_USE_IRQ)

interrupt_init, /* Ausnahmen einrichten */

#endif

timer_init, /* Timer initialisieren */

env_init, /* Umgebung initialisieren */

init_baudrate, /* Baudrateneinstellungen initialisieren */

serial_init, /* Einrichtung der seriellen Kommunikation */

console_init_f, /* Stage 1 Initialisierung der Konsole */

display_banner, /* sagen, dass wir hier sind */

#falls definiert(CONFIG_DISPLAY_CPUINFO)

print_cpuinfo, /* CPU-Info (und Geschwindigkeit) anzeigen */

#endif

#falls definiert(CONFIG_DISPLAY_BOARDINFO)

Schachbrett, /* Brettinfo anzeigen */

#endif

#falls definiert(CONFIG_HARD_I2C) || definiert (CONFIG_SOFT_I2C)

init_func_i2c,

#endif

dram_init, /* verfügbare RAM-Bänke konfigurieren */

#falls definiert(CONFIG_CMD_PCI) || definiert (CONFIG_PCI)

arm_pci_init,

#endif

display_dram_config,

NULL,

};

Ergebnis

init_fnc_t *init_sequence[] = {

board_init, /* grundlegende kartenabhängige Einrichtung */

timer_init, /* Timer initialisieren */

env_init, /* Umgebung initialisieren */

init_baudrate, /* Baudrateneinstellungen initialisieren */

serial_init, /* Einrichtung der seriellen Kommunikation */

console_init_f, /* Stage 1 Initialisierung der Konsole */

display_banner, /* sagen, dass wir hier sind */

dram_init, /* verfügbare RAM-Bänke konfigurieren */

display_dram_config,

NULL,

};

Eingabefunktion

Eingang

# < lib_arm\board.c >

void start_armboot (nichtig)

Bewerben Sie sich für gd globale Daten

gd = (gd_t*)(_armboot_start - CONFIG_SYS_MALLOC_LEN - sizeof(gd_t));

Verhindert, dass die gcc-Optimierung für hohe Versionen Fehler generiert

    _asm__ __volatile__("": ​​: :"Speicher");

veranschaulichen:

1) __asm__ wird verwendet, um den Compiler anzuweisen, hier Assembly-Anweisungen einzufügen.

2) __volatile__ wird verwendet, um dem Compiler mitzuteilen, dass es strengstens verboten ist, die Assembly-Anweisung hier mit anderen Anweisungen neu zu kombinieren und zu optimieren. Das heißt: Die Baugruppe wird hier so verarbeitet, wie sie ursprünglich war.

3) Speicher zwingt den gcc-Compiler anzunehmen, dass alle Speichereinheiten im RAM durch Assembler-Anweisungen modifiziert werden, sodass die Daten in den Registern in der CPU und den zwischengespeicherten Speichereinheiten im Cache ungültig werden. Die CPU muss die Daten im Speicher bei Bedarf erneut lesen. Dies verhindert, dass die CPU die Daten in Registern und im Cache verwendet, um Anweisungen zu optimieren und den Zugriff auf den Speicher zu vermeiden.

4) ""::: bedeutet, dass dies eine leere Anweisung ist. barrier() muss hier keine Serialisierungs-Assembler-Anweisung einfügen.

klare globale Daten

    memset ((void*)gd, 0, sizeof (gd_t));

    gd->bd = (bd_t*)((char*)gd - sizeof(bd_t));

    memset (gd->bd, 0, sizeof (bd_t));

Flagbit setzen (aktueller Code im RAM)

    gd->flags |= GD_FLG_RELOC;

Holen Sie sich die gesamte uboot-Länge

monitor_flash_len = _bss_start - _armboot_start;

veranschaulichen:

_bss_start ist die Startadresse von bss, _armboot_start ist die Startcodeadresse von Uboot, wobei monitor_flash_len die Länge des gesamten Uboot erhält

mit einer Folge von Initialisierern initialisieren

    für (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr)

    {

        if ((*init_fnc_ptr)() != 0) //Der Rückgabewert der Funktion ist nicht Null, direkt in die Endlosschleife eintreten

        {

            hang (); // Endlosschleife { for(;;); }

        }

    }

Initialisieren Sie den Speicher-Heap-Bereich

mem_malloc_init (_armboot_start - CONFIG_SYS_MALLOC_LEN, CONFIG_SYS_MALLOC_LEN);

veranschaulichen:

_armboot_start = TEXT_BASE = 0x33F80000

# < common\dlmalloc.c >

void mem_malloc_init (Vorsprung, Kopfgröße)

{

mem_malloc_start = starten;

mem_malloc_end = Anfang + Größe;

mem_malloc_brk = starten;

memset((void *)mem_malloc_start, 0, Größe);

}

Initialisierung des Flash-Treibers

#ifndef CONFIG_SYS_NO_FLASH

    /* Verfügbare FLASH-Bänke konfigurieren */

    display_flash_config (flash_init ());

#endif /* CONFIG_SYS_NO_FLASH */

veranschaulichen:

# < lib_arm\board.c >

Statisch void display_flash_config (Ulong-Größe)

{

setzt ("Flash: ");

print_size (Größe, "\n");

}

Nand-Laufwerk initialisieren

#falls definiert(CONFIG_CMD_NAND)

    setzt ("NAND: ");

    nand_init(); /* NAND initialisieren */

#endif

veranschaulichen:

# <include\configs\mini2440.h>

#define CONFIG_SYS_MAX_NAND_DEVICE 1

# < Treiber\mtd\nand\nand.c >

void nand_init(void)

{

int ich;

unsigned int Größe = 0;

für (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++) {

nand_init_chip(&nand_info[i], &nand_chip[i], base_address[i]);

Größe += nand_info[i].size / 1024;

if (nand_curr_device == -1)

nand_curr_device = ich;

}

printf("%u MiB\n", Größe / 1024);

#ifdef CONFIG_SYS_NAND_SELECT_DEVICE

/*

* Wählen Sie den Chip im Board-/CPU-spezifischen Treiber aus

*/

board_nand_select_device(nand_info[nand_curr_device].priv, nand_curr_device);

#endif

}

Initialisierung der Umgebungsvariablen

    env_relocate ();

Holen Sie sich die IP-Adresse aus der Umgebungsvariable

    gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr");

veranschaulichen:

IPaddr_t getenv_IPaddr (char *var)

{

return (string_to_ip(getenv(var)));

}

char *getenv (char *name)

{

int i, nxt;

WATCHDOG_RESET();

        // Komfort für alle Strings

for (i=0; env_get_char(i) != '\0'; i=nxt+1)

        {

int val;

                // Finden Sie einen String heraus (mit '\0' abgeschlossen)

for (nxt=i; env_get_char(nxt) != '\0'; ++nxt)

                {

if (nxt >= CONFIG_ENV_SIZE)

                        {

Rückgabe (NULL);

}

}

if ((val=envmatch((uchar *)name, i)) < 0) // ermittle den Namen

weitermachen;

return ((char *)env_get_addr(val));

}

Rückgabe (NULL);

}

uchar env_get_char_memory (int-Index)

{

if (gd->env_valid) {

return ( *((uchar *)(gd->env_addr + index)) );

} anders {

return ( default_environment [index] );

}

}

uchar *env_get_addr (int-Index)

{

if (gd->env_valid) {

return ( ((uchar *)(gd->env_addr + index)) );

} anders {

return (&default_environment[index]);

}

}

Standardeingabe, Standardausgabe, Standardfehlerinitialisierung ("stdin", "stdout", "stderr")

    stdio_init()

int stdio_init (leer)

{ //Der Rest des Codes ist aufgrund von Makros blockiert

drv_system_init ();

Rückkehr (0);

}

statische void drv_system_init (void)

{

struct stdio_dev dev;

memset (&dev, 0, sizeof (dev));

strcpy (dev.name, "serial");

dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM;

dev.putc = serial_putc;

dev.puts = serial_puts;

dev.getc = serial_getc;

dev.tstc = serial_tstc;

stdio_register (&dev);

}

struct stdio_dev {

int-Flags; /* Geräteflags: Eingabe/Ausgabe/System */

im Text; /* Unterstützte Erweiterungen */

Zeichenname[16]; /* Gerätename */

/* ALLGEMEINE Funktionen */

int (*start) (leer); /* Um das Gerät zu starten */

int (*stop) (leer); /* Um das Gerät zu stoppen */

/* OUTPUT-Funktionen */

void (*putc) (const char c); /* Um ein Zeichen zu setzen */

void (*puts) (const char *s); /* Um einen String einzufügen (Beschleuniger) */

/* INPUT-Funktionen */

int (*tstc) (nichtig); /* Um zu testen ob ein Char bereit ist... */

int (*getc) (leer); /* Um dieses Zeichen zu bekommen */

/* Andere Funktionen */

ungültig *priv; /* Private Erweiterungen */

struct list_head list;

};

int stdio_register (struct stdio_dev * dev)

{

struct stdio_dev *_dev;

_dev = stdio_clone(dev);

wenn(!_dev)

Rückgabe -1;

list_add_tail(&(_dev->list), &(devs.list));

0 zurückgeben;

}

struct stdio_dev* stdio_clone(struct stdio_dev *dev)

{

struct stdio_dev *_dev;

wenn(!dev)

gib NULL zurück;

_dev = calloc(1, sizeof(struct stdio_dev));

wenn(!_dev)

gib NULL zurück;

memcpy(_dev, dev, sizeof(struct stdio_dev));

strncpy(_dev->name, dev->name, 16);

return _dev;

}

Initialisierung der Sprungtabelle

    jumptable_init ();

void jumptable_init (nichtig)

{ //Funktionsadresse

int ich;

gd->jt = (void **) malloc (XF_MAX * sizeof (void *));

für (i = 0; i < XF_MAX; i++)

gd->jt[i] = (void *) dummy;

gd->jt[XF_get_version] = (void *) get_version;

gd->jt[XF_malloc] = (void *) malloc;

gd->jt[XF_free] = (void *) kostenlos;

gd->jt[XF_getenv] = (void *) getenv;

gd->jt[XF_setenv] = (void *) setenv;

gd->jt[XF_get_timer] = (void *) get_timer;

gd->jt[XF_simple_strtoul] = (void *) simple_strtoul;

gd->jt[XF_udelay] = (void *) udelay;

gd->jt[XF_simple_strtol] = (void *) simple_strtol;

gd->jt[XF_strcmp] = (void *) strcmp;

#falls definiert(CONFIG_I386) || definiert (CONFIG_PPC)

gd->jt[XF_install_hdlr] = (void *) irq_install_handler;

gd->jt[XF_free_hdlr] = (void *) irq_free_handler;

#endif /* I386 || PPC */

#falls definiert(CONFIG_CMD_I2C)

gd->jt[XF_i2c_write] = (void *) i2c_write;

gd->jt[XF_i2c_read] = (void *) i2c_read;

#endif

#ifdef CONFIG_CMD_SPI

gd->jt[XF_spi_init] = (void *) spi_init;

gd->jt[XF_spi_setup_slave] = (void *) spi_setup_slave;

gd->jt[XF_spi_free_slave] = (void *) spi_free_slave;

gd->jt[XF_spi_claim_bus] = (void *) spi_claim_bus;

gd->jt[XF_spi_release_bus] = (void *) spi_release_bus;

gd->jt[XF_spi_xfer] = (void *) spi_xfer;

#endif

}

Initialisierung der zweiten Stufe des Endgeräts

    console_init_r ();

Initialisierung unterbrechen

    enable_interrupts ();

veranschaulichen:

Laut Makro: CONFIG_USE_IRQ ist diese Funktion blockiert

void enable_interrupts (nichtig)

{

zurückkehren;

}

Holen Sie sich die Ladeadresse aus der Umgebungsvariablen (nicht verwendet, die Umgebungsvariable hat diesen Parameter nicht)

    if ((s = getenv ("loadaddr")) != NULL) {

        load_addr = simple_strtoul (s, NULL, 16);

    }

Hauptschleife

    für (;;)

    {

        Hauptschleife ();

    }

Beschreibung der Hysterese

Diverse Initialisierungen (init_sequence)

nand-Initialisierung (nand_init)

Initialisierung der Umgebungsvariablen (env_relocate)

Terminal-Initialisierung (console_init_r)

Hauptschleife (main_loop)

 

Guess you like

Origin blog.csdn.net/liutit/article/details/130034421