在移植4.16内核到tiny4412的过程中遇到一个问题,官方的uboot2012引导内核成功卡在staring the kernel没有了下文,看来内核还没有到注册uart驱动就已经挂掉了,尝试打开 early printk ,让内核自解压之后能够及时的打印信息。
说句题外话,内核启动卡在staring the kernel,在2440的时代,未使用设备树,这种情况往往是机器ID设置错误,或者是串口波特率等方面的原因导致,在设备树的时代,机器ID已经被废除,最有可能的问题可能就是出在设备树的身上。
make menuconfigKernel hacking --->[*] Kernel low-level debugging functions (read help!)Kernel low-level debugging port (Use Samsung S3C UART 0 for low-level debug)[*] Early printk
设置环境变量
Add earlyprintk to your kernel parameters to enable this console
在 bootargs 中添加 earlyprintk
arch/arm/kernel/early_printk.c
extern void printascii(const char *);static void early_write(const char *s, unsigned n)
{char buf[128];while (n) {unsigned l = min(n, sizeof(buf)-1);memcpy(buf, s, l);buf[l] = 0;s += l;n -= l;printascii(buf);}
}static void early_console_write(struct console *con, const char *s, unsigned n)
{early_write(s, n);
}static struct console early_console_dev = {.name = "earlycon",.write = early_console_write,.flags = CON_PRINTBUFFER | CON_BOOT,.index = -1,
};static int __init setup_early_printk(char *buf)
{early_console = &early_console_dev;register_console(&early_console_dev);return 0;
}early_param("earlyprintk", setup_early_printk);
在内核启动进入C语言阶段,start_kernel->parse_early_param 就会第一时间解析early_param(“earlyprintk”, setup_early_printk);
然后调用 register_console(&early_console_dev);
可以看到 early_console 的 write 函数最终靠 printascii 来实现,同样,直接调用 earlyprintk 也会调用 printascii
void __init early_print(const char *str, ...)
{extern void printascii(const char *);char buf[256];va_list ap;va_start(ap, str);vsnprintf(buf, sizeof(buf), str, ap);va_end(ap);#ifdef CONFIG_DEBUG_LLprintascii(buf);
#endifprintk("%s", buf);
}
printascii:arch/arm/kernel/debug.S
ENTRY(printascii)addruart_current r3, r1, r2
1: teq r0, #0ldrneb r1, [r0], #1teqne r1, #0reteq lr
2: teq r1, #'n'bne 3fmov r1, #'r'waituart r2, r3senduart r1, r3busyuart r2, r3mov r1, #'n'
3: waituart r2, r3senduart r1, r3busyuart r2, r3b 1b
ENDPROC(printascii)
.macro addruart_current, rx, tmp1, tmp2addruart tmp1, tmp2, rxmrc p15, 0, rx, c1, c0tst rx, #1moveq rx, tmp1movne rx, dm
addruart_current 和 addruart 都是宏定义
各个平台实现自己的 addruart 宏:4412的位于:arch/arm/include/debug/exynos.S
.macro addruart, rp, rv, tmpmrc p15, 0, tmp, c0, c0, 0and tmp, tmp, #0xf0teq tmp, #0xf0 @@ A15beq 100fmrc p15, 0, tmp, c0, c0, 5and tmp, tmp, #0xf00teq tmp, #0x100 @@ A15 + A7 but boot to A7
100: ldreq rp, =EXYNOS5_PA_UARTmovne rp, #EXYNOS4_PA_UART @@ EXYNOS4ldr rv, =S3C_VA_UART
#if CONFIG_DEBUG_S3C_UART != 0add rp, rp, #(0x10000 * CONFIG_DEBUG_S3C_UART)add rv, rv, #(0x10000 * CONFIG_DEBUG_S3C_UART)
#dm
这里返回的是 uart0 的基地址,虚拟地址和物理地址,EXYNOS4_PA_UART=0x13800000
有了基地址还不够,能需要UTXHn的偏移地址才行
arch/arm/include/debug/samsung.S
.macro senduart,rd,rxstrb rd, [rx, # S3C2410_UTXH]
.endm
include/linux/serial_s3c.h
#define S3C2410_UTXH (0x20)
因此,可以得知,内核earlyprintk不会去初始化串口,直接使用Uboot初始化ok的,这是个好消息~
C语言阶段,可以调用early_printk,那么在自解压之后,C语言之前的汇编阶段,如何打印呢?
参考:
__error_p:
#ifdef CONFIG_DEBUG_LLadr r0, str_p1bl printasciimov r0, r9bl printhex8adr r0, str_p2bl printasciib __error
str_p1: .asciz "nError: unrecognized/unsupported processor variant (0x"
str_p2: .asciz ").n".align
#endif
ENDPROC(__error_p)
注意:汇编阶段调用函数,一定记得保护现场,否则会破坏原有寄存器,引入不必要的麻烦
内核自解压阶段也可以调用早期的打印函数,需要针对自己的平台稍加修改(addruart 宏定义),这个阶段可能出现的问题,内核自解压把设备树覆盖了,导致卡在 staring the kernel 我这里就是如此~~,修改Uboot设备树的重定位地址即可。
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -24,6 +24,7 @@* 100% relocatable. Any attempt to do so will result in a crash.* Please select one of the following when turning on debugging.*/
+#define DEBUG#ifdef DEBUG#if defined(CONFIG_DEBUG_ICEDCC)
@@ -67,7 +68,7 @@.endm#else.macro loadsp, rb, tmp
- addruart rb, tmp
+ addruart rb, tmp, dm#endif#endif
@@ -554,6 +555,12 @@ not_relocated: mov r0, #0* r7 = architecture ID* r8 = atags pointer*/
+ stmfd sp!, {r0-r3, r10-r12, lr}
+ mov r0, r8
+ bl memdump
+ kputc #'n'
+ ldmfd sp!, {r0-r3, r10-r12, lr}
+mov r0, r4mov r1, sp @ malloc space above stackadd r2, sp, #0x10000 @ 64k max
@@ -563,6 +570,12 @@ not_relocated: mov r0, #0bl cache_offmov r1, r7 @ restore architecture numbermov r2, r8 @ restore atags pointer
+
+ stmfd sp!, {r0-r3, r10-r12, lr}
+ mov r0, r8
+ bl memdump
+ kputc #'n'
+ ldmfd sp!, {r0-r3, r10-r12, lr}#ifdef CONFIG_ARM_VIRT_EXT
参考:.html
参考:.html
本文发布于:2024-01-31 17:48:35,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170669451730280.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |