[LINUX] So drucken Sie Zeichen auf der Konsole, bevor Sie in ARM starten

Wie kann ich vor dem Booten Zeichen auf der Konsole drucken?

Nach dem Booten von Linux können Sie ein mit der Konsole verbundenes Gerät angeben, indem Sie es mit einer Option wie "console = ttyS0,115200" angeben.

Aber was ist, wenn ich das Protokoll sehen möchte, bevor es startet? Wie zeigen Sie es an? Lassen Sie uns das klären.

Die Umfragebasis ist hier.

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/arch/arm

0. Einleitung

Obwohl es sich um eine Debugging-Routine handelt, die wirksam ist, wenn MM-Probleme oder printk nicht funktionieren, Es dient nur zum Debuggen und soll im Produktkern entfernt werden.

Sie müssen vorsichtig damit umgehen!

arch/arm/kernel/debug.S



/*
 * Some debugging routines (useful if you've got MM problems and
 * printk isn't working).  For DEBUGGING ONLY!!!  Do not leave
 * references to these in a production kernel!
 */

1. Geben Sie beim Start Earlyprintk an.

Es scheint, dass Sie "Earlyprintk" als Boot-Option von Linux angeben sollten.

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/Documentation/admin-guide/kernel-parameters.txt#n1135

Was passiert, wenn Sie dies angeben?

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/arch/arm/kernel/early_printk.c

Die Adresse des anzuzeigenden Zeichens wird an die Funktion printascii () übergeben.

2. Drucken Sie Zeichen mit print ascii

Klicken Sie hier für die Definition von printascii. Im Fall von ARM Assembler ist das Argument in r0. In diesem Fall ist r0 ein Zeiger auf eine Zeichenfolge.

Ich denke.

arch/arm/kernel/debug.S



#ifndef CONFIG_DEBUG_SEMIHOSTING

ENTRY(printascii)
        addruart_current r3, r1, r2 // 2.Erklärt in 1
1:      teq r0, #0
        ldrbne  r1, [r0], #1
        teqne   r1, #0
        reteq   lr
2:      teq     r1, #'\n'
        bne 3f
        mov r1, #'\r'
        waituart r2, r3 // 4.Erklärt in 2
        senduart r1, r3 // 4.Erklärt in 3
        busyuart r2, r3 // 4.Erklärt in 4
        mov r1, #'\n'
3:      waituart r2, r3
        senduart r1, r3
        busyuart r2, r3
        b   1b
ENDPROC(printascii)

<Ausgelassen>

#else

ENTRY(printascii)
        mov r1, r0
        mov r0, #0x04       @ SYS_WRITE0
    ARM(    svc #0x123456   )
#ifdef CONFIG_CPU_V7M
    THUMB(  bkpt    #0xab       )
#else
    THUMB(  svc #0xab       )
#endif
        ret lr
ENDPROC(printascii)

Das Verhalten ändert sich abhängig davon, ob DEBUG_SEMIHOSTING aktiviert ist oder nicht.

Wenn es ungültig ist, wird versucht, Zeichen auszugeben, indem adduart_current / waituart / senduart vollständig verwendet wird. Dies wird eine produktspezifische Implementierung sein (siehe unten).

Was ist, wenn es gültig ist? 0x04 wird im r0-Register gesetzt, und das anzuzeigende Zeichen wird im r1-Register gesetzt, und 0x123456 wird im ARM-Modus SVCed. Dies ist eine Funktion, die unabhängig vom Modell verwendet werden kann und (wahrscheinlich) über einen Debugger wie JTAG angezeigt werden kann.

2.1 Überprüfen Sie adduart_current

Ich werde adduart_current erklären, ein Prozess, der allen Modellen gemeinsam ist.

arch/arm/kernel/debug.S


#ifdef CONFIG_MMU
        .macro  addruart_current, rx, tmp1, tmp2
        addruart    \tmp1, \tmp2, \rx // 4.Erklärt in 1
        mrc     p15, 0, \rx, c1, c0
        tst     \rx, #1
        moveq       \rx, \tmp1
        movne       \rx, \tmp2
        .endm

#else /* !CONFIG_MMU */
        .macro  addruart_current, rx, tmp1, tmp2
        addruart    \rx, \tmp1, \tmp2
        .endm

#endif /* CONFIG_MMU */

rx [out] zugängliche Adresse von tmp1 / tmp2 temp1 [tmp]: Wird vorübergehend verwendet temp2 [tmp]: Wird vorübergehend verwendet

Wenn MMU aktiviert ist, schalten Sie PHYS / VIRT entsprechend dem Status der MMU um. Wenn MMU deaktiviert ist, verwenden Sie PHYS.

Mit anderen Worten wird dem ersten Register (r3) die entsprechende Adresse zur Steuerung des UART-Geräts zugewiesen.

3. Entscheiden Sie, welches Assembler-Modell mit printascii gelesen werden soll

Nun wollen wir sehen, wo jede in printascii aufgerufene Funktion definiert ist.

arch/arm/Kconfig.debug



# These options are only for real kernel hackers who want to get their hands dirty.
config DEBUG_LL
	bool "Kernel low-level debugging functions (read help!)"
	depends on DEBUG_KERNEL
	help
	  Say Y here to include definitions of printascii, printch, printhex
	  in the kernel.  This is helpful if you are debugging code that
	  executes before the console is initialized.

	  Note that selecting this option will limit the kernel to a single
	  UART definition, as specified below. Attempting to boot the kernel
	  image on a different platform *will not work*, so this option should
	  not be enabled for kernels that are intended to be portable.

choice
	prompt "Kernel low-level debugging port"
	depends on DEBUG_LL

	config DEBUG_ALPINE_UART0
		bool "Kernel low-level debugging messages via Alpine UART0"
		depends on ARCH_ALPINE
		select DEBUG_UART_8250
		help
		  Say Y here if you want kernel low-level debugging support
		  on Alpine based platforms.

Diese Optionen sind für echte Kernel-Hacker gedacht, die sich die Hände schmutzig machen möchten

Wählen Sie Y, um printascii, printch und printhex im Kernel zu definieren. Dies ist nützlich, wenn Sie den Code debuggen möchten, der vor der Initialisierung der Konsole ausgeführt wird.

Beachten Sie, dass die Auswahl dieser Option den Kernel auf eine einzelne UART-Definition beschränkt, wie unten gezeigt. Aktivieren Sie diese Option nicht auf tragbaren Kerneln, da sie * nicht funktioniert *, wenn Sie versuchen, das Kernel-Image auf einer anderen Plattform zu starten.

Also, es ist wirklich solide hier, also ist es ein Fix, der es weniger portabel macht.

Wenn DEBUG_ALPINE_UART0 usw. in den obigen Einstellungen definiert ist, wird DEBUG_UART_8250 usw. angegeben und durch die Definition des einzuschließenden Assembler-Codes ersetzt.

arch/arm/Kconfig.debug


config DEBUG_LL_INCLUDE
    string
    default "debug/sa1100.S" if DEBUG_SA1100
    default "debug/palmchip.S" if DEBUG_UART_8250_PALMCHIP
    default "debug/8250.S" if DEBUG_LL_UART_8250 || DEBUG_UART_8250
    default "debug/at91.S" if DEBUG_AT91_UART
    default "debug/asm9260.S" if DEBUG_ASM9260_UART
    default "debug/clps711x.S" if DEBUG_CLPS711X_UART1 || DEBUG_CLPS711X_UART2
    default "debug/dc21285.S" if DEBUG_DC21285_PORT
    default "debug/meson.S" if DEBUG_MESON_UARTAO
    default "debug/pl01x.S" if DEBUG_LL_UART_PL01X || DEBUG_UART_PL01X
    default "debug/exynos.S" if DEBUG_EXYNOS_UART
    default "debug/efm32.S" if DEBUG_LL_UART_EFM32
    default "debug/icedcc.S" if DEBUG_ICEDCC

Infolgedessen wird CONFIG_DEBUG_LL_INCLUDE zur Zeichenfolge "debug / *. S", die # eingeschlossen ist.

arch/arm/kernel/debug.S



#if !defined(CONFIG_DEBUG_SEMIHOSTING)
#include CONFIG_DEBUG_LL_INCLUDE
#endif

Klicken Sie hier, um Definitionen wie CONFOG_DEBUG_UART_PHTS anzuzeigen, die in Kürze in 4.1 verwendet werden.

arch/arm/Kconfig.debug


config DEBUG_UART_PHYS
    hex "Physical base address of debug UART"
    default 0x01c20000 if DEBUG_DAVINCI_DMx_UART0
    default 0x01c28000 if DEBUG_SUNXI_UART0
    default 0x01c28400 if DEBUG_SUNXI_UART1
    default 0x01d0c000 if DEBUG_DAVINCI_DA8XX_UART1
    default 0x01d0d000 if DEBUG_DAVINCI_DA8XX_UART2
    default 0x01f02800 if DEBUG_SUNXI_R_UART
    default 0x02530c00 if DEBUG_KEYSTONE_UART0
    default 0x02531000 if DEBUG_KEYSTONE_UART1
    default 0x03010fe0 if ARCH_RPC
    :

config DEBUG_UART_VIRT
    hex "Virtual base address of debug UART"
    default 0xc881f000 if DEBUG_RV1108_UART2
    default 0xc8821000 if DEBUG_RV1108_UART1
    default 0xc8912000 if DEBUG_RV1108_UART0
    default 0xe0010fe0 if ARCH_RPC
    default 0xf0000be0 if ARCH_EBSA110
    default 0xf0010000 if DEBUG_ASM9260_UART
    default 0xf0100000 if DEBUG_DIGICOLOR_UA0
    default 0xf01fb000 if DEBUG_NOMADIK_UART
    default 0xf0201000 if DEBUG_BCM2835 || DEBUG_BCM2836
    default 0xf1000300 if DEBUG_BCM_5301X
    default 0xf1000400 if DEBUG_BCM_HR2
    default 0xf1002000 if DEBUG_MT8127_UART0
    default 0xf1006000 if DEBUG_MT6589_UART0
    default 0xf1009000 if DEBUG_MT8135_UART3
    default 0xf1023000 if DEBUG_BCM_IPROC_UART3
    default 0xf11f1000 if DEBUG_VERSATILE
    default 0xf1600000 if DEBUG_INTEGRATOR
    :
    :

4. Assembler, der tatsächlich in printascii verwendet wird

Der eigentliche Assembler-Code wird jeweils unter include / debug implementiert. Verwenden Sie hier den bcm-Code, der den kürzesten Quellcode zu haben scheint. Überprüfen Sie einfach die Definition der bereitgestellten Funktion. 4.1 adduart, rp,rv,tmp

/arch/arm/include/debug/bcm63xx.S


	.macro	addruart, rp, rv, tmp
	ldr	\rp, =CONFIG_DEBUG_UART_PHYS
	ldr	\rv, =CONFIG_DEBUG_UART_VIRT
	.endm

rp [out] : CONFIG_DEBUG_UART_PHYS rv [out] : CONFIG_DEBUG_UART_VIRT tmp [out]: Daten an waituart / busyuart übergeben

Diese Funktion wird auch indirekt von der mmu-Steuerung aufgerufen. Vielleicht wird dies nicht verwendet, wenn die iomap-Tabelle definiert ist ...

arch/arm/mm/mmu.c



    /*
     * Ask the machine support to map in the statically mapped devices.
     */
    if (mdesc->map_io)
        mdesc->map_io();
    else
        debug_ll_io_init();

:
:


#ifdef CONFIG_DEBUG_LL
void __init debug_ll_io_init(void)
{
    struct map_desc map;

    debug_ll_addr(&map.pfn, &map.virtual);
    if (!map.pfn || !map.virtual)
        return;
    map.pfn = __phys_to_pfn(map.pfn);
    map.virtual &= PAGE_MASK;
    map.length = PAGE_SIZE;
    map.type = MT_DEVICE;
    iotable_init(&map, 1);
}
#endif

arch/arm/kernel/debug.S



#ifdef CONFIG_MMU
ENTRY(debug_ll_addr)
        addruart r2, r3, ip
        str r2, [r0]
        str r3, [r1]
        ret lr
ENDPROC(debug_ll_addr)
#endif

4.2 waituart, rd,rx

/arch/arm/include/debug/bcm63xx.S



	.macro	waituart, rd, rx
1001:	ldr	\rd, [\rx, #UART_IR_REG]
	tst	\rd, #(1 << UART_IR_TXEMPTY)
	beq	1001b
	.endm

rd [tmp]: Wird vorübergehend verwendet rx [in]: UART-Geräteport

Lesen Sie den Speicher in OFFSET von UART_IR_REG des UART-Geräteports und wiederholen Sie die Schleife, bis er mit # (1 << UART_IR_TXEMPTY) übereinstimmt.

4.3 senduart, rd,rx

/arch/arm/include/debug/bcm63xx.S



	.macro	senduart, rd, rx
	/* word access do not work */
	strb	\rd, [\rx, #UART_FIFO_REG]
	.endm

rd [in]: Zeichenkette exportieren rx [in]: UART-Geräteport

4.4 busyuart, rd,rx

/arch/arm/include/debug/bcm63xx.S



	.macro	busyuart, rd, rx
1002:	ldr	\rd, [\rx, #UART_IR_REG]
	tst	\rd, #(1 << UART_IR_TXTRESH)
	beq	1002b
	.endm

rd [tmp]: Wird vorübergehend verwendet rx [in]: UART-Geräteport

Lesen Sie den Speicher in OFFSET von UART_IR_REG des UART-Geräteports und wiederholen Sie die Schleife, bis er mit # (1 << UART_IR_TXTRESH) übereinstimmt.

Zusammenfassung

das ist alles.

Recommended Posts

So drucken Sie Zeichen auf der Konsole, bevor Sie in ARM starten
So drucken Sie Debug-Meldungen auf der Django-Konsole
So überschreiben Sie die Ausgabe auf die Konsole
So löschen Sie die von Python ausgegebenen Zeichen
Wie man Python auf Android genießt !! Programmieren für unterwegs !!
Verwendung des Generators
So drucken Sie Zeichen als Tabelle mit der Druckfunktion von Python
So stellen Sie Pybot, das einfachste Python-Lehrbuch, auf Heroku bereit
Hinweise zur Verwendung von Marshmallow in der Schemabibliothek
Wie benutzt man den Dekorateur?
So erhöhen Sie die Achse
So starten Sie die erste Projektion
Ein Hinweis zum Überprüfen der Verbindung zum Lizenzserver-Port
Wie einfach ist es, ein Medikament auf dem Markt zu synthetisieren?
Verwendung von Jupyter am Frontend von Spacon ITO
Ein Befehl zum einfachen Überprüfen der Netzwerkgeschwindigkeit auf der Konsole
So aktualisieren Sie die Python-Version von Cloud Shell in GCP
Wie berechnet man den Autokorrelationskoeffizienten?
Verwendung der Zip-Funktion
Verwendung von Dataiku unter Windows
Hinweise zur Verwendung von Pywinauto
So installieren Sie VMware-Tools unter Linux
Lesen des SNLI-Datensatzes
So stellen Sie den Django-Kompressor unter Windows bereit
So erhalten Sie die Python-Version
Hinweise zur Verwendung von featuretools
So installieren Sie OpenCV auf einem Mac
So installieren Sie PyPy unter CentOS
Missverständnisse beim Verbinden von cnn
So installieren Sie TensorFlow unter CentOS 7
So installieren Sie Maven unter CentOS
Verwendung des ConfigParser-Moduls
Hinweise zum Schreiben von require.txt
So installieren Sie Musik 21 unter Windows
So wechseln Sie einfach die von Conda auf Jupyter erstellte virtuelle Umgebung
[C-Sprache] Verwendung der Krypta-Funktion unter Linux [Passwort-Hashing]
TLE schien beängstigend zu sein, je nachdem, wie die Eingabe empfangen wurde
So registrieren Sie nur eine Daten auf dem Django-Verwaltungsbildschirm
So machen Sie Word Cloud-Zeichen monochromatisch
So zeigen Sie den Fortschrittsbalken an (tqdm)
Ich möchte kühl auf die Konsole ausgeben
So installieren Sie das aws-session-manager-Plugin unter Manajro Linux
Wie man pydoc auf Python Interpreter liest
So installieren Sie drobertadams / toggl-cli auf einem Mac
So überprüfen Sie die Version von Django
[Kivy] So installieren Sie Kivy unter Windows [Python]
Wie man Mecab, neologd-ipadic auf Colab verwendet
So lösen Sie das Problem beim Verpacken des Behälters
So stellen Sie die Serverzeit auf japanische Zeit ein
Wie man Hello, World mit #Nix baut
So aktualisieren Sie den AMP-Cache manuell
[Linux] Verwendung des Befehls echo
So aktualisieren Sie PHP unter Amazon Linux 2
So verwenden Sie Google Assistant unter Windows 10
So löschen Sie Python 2.x auf einem Mac.