Uboot2016 for tiny4412调试
来源:互联网 发布:cda数据分析师认证 编辑:程序博客网 时间:2024/06/05 22:08
前面已经添加了点灯代码了,那就让我们开始调试吧。
前面添加点灯代码的时候我们就知道,代码是能够成功运行到crt0.S中的_main的,那我们就可以直接从crt0.S中开始分析了。分析前大家可以花点时间看看crt0.S文件最上面的注释,看完应该就对_main所做的事情有所了解了。另外,我们还可以通过指令arm-none-eabi-objdump -S ./spl/u-boot-spl > u-boot-spl.S 将./spl/u-boot-spl这个可执行文件反汇编,这样就可以通过反汇编代码了解uboot真正的执行流程了。
先看下面的反汇编代码:
02024af0 <_main>: */#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK) ldr sp, =(CONFIG_SPL_STACK)#else ldr sp, =(CONFIG_SYS_INIT_SP_ADDR) 2024af0: e3a0d781 mov sp, #33816576 ; 0x2040000#if defined(CONFIG_CPU_V7M) /* v7M forbids using SP as BIC destination */ mov r3, sp bic r3, r3, #7 mov sp, r3#else bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ 2024af4: e3cdd007 bic sp, sp, #7#endif mov r0, sp 2024af8: e1a0000d mov r0, sp bl board_init_f_alloc_reserve 2024afc: eb000004 bl 2024b14 <board_init_f_alloc_reserve> mov sp, r0 2024b00: e1a0d000 mov sp, r0 /* set up gd here, outside any C code */ mov r9, r0 2024b04: e1a09000 mov r9, r0 bl board_init_f_init_reserve 2024b08: eb000004 bl 2024b20 <board_init_f_init_reserve> mov r0, #0 2024b0c: e3a00000 mov r0, #0 bl board_init_f 2024b10: ebffff5e bl 2024890 <board_init_f>
可以看到,在_main中,会对全局变量和栈进行初始化,其中 board_init_f_alloc_reserve 和 board_init_f_init_reserve 这两个函数的代码较少,大家看注释也可了解它们具体做了什么事情。接下来我们重点分析board_init_f这个函数。board_init_f在/arch/arm/mach-exynos/spl_boot.c中实现
void board_init_f(unsigned long bootflag){ __aligned(8) gd_t local_gd; __attribute__((noreturn)) void (*uboot)(void); setup_global_data(&local_gd); if (do_lowlevel_init()) power_exit_wakeup(); copy_uboot_to_ram(); /* Jump to U-Boot image */ uboot = (void *)CONFIG_SYS_TEXT_BASE; (*uboot)(); /* Never returns Here */}
接下来先分析do_lowlevel_init()实现了什么功能,代码在/arch/arm/mach-exynos/lowlevel_init.c中,在之前,我曾经在board_init_f函数跳转到u-boot前添加过点灯代码,所以先可以确定do_lowlevel_init()中的代码执行是没有问题的,但是之后再细看的时候,发现uart的初始化也是在do_lowlevel_init()完成的,追踪uart初始化的代码过程是:debug_uart_init()–>_debug_uart_init()–>s5p_serial_init(),首先做如下修改:
diff --git a/arch/arm/mach-exynos/lowlevel_init.c b/arch/arm/mach-exynos/lowlevel_init.cindex 1e090fd..1000785 100644--- a/arch/arm/mach-exynos/lowlevel_init.c+++ b/arch/arm/mach-exynos/lowlevel_init.c@@ -218,8 +218,9 @@ int do_lowlevel_init(void) #ifdef CONFIG_DEBUG_UART #if (defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_SERIAL_SUPPORT)) || \ !defined(CONFIG_SPL_BUILD)- exynos_pinmux_config(PERIPH_ID_UART3, PINMUX_FLAG_NONE);+ exynos_pinmux_config(PERIPH_ID_UART0, PINMUX_FLAG_NONE); debug_uart_init();+ printascii("UART Init finish!\n"); #endif #endif
如果UART初始化成功,那么调用printascii函数后,就能将需要输出的内容通过串口输出了。但是做了如上修改后,编译烧写运行发现串口并没有任何的输出,表明UART的初始化还是有问题,接着只能看s5p_serial_init()的代码
static void __maybe_unused s5p_serial_init(struct s5p_uart *uart){ /* enable FIFOs, auto clear Rx FIFO */ writel(0x3, &uart->ufcon); writel(0, &uart->umcon); /* 8N1 */ writel(0x3, &uart->ulcon); /* No interrupts, no DMA, pure polling */ writel(0x245, &uart->ucon);}
对照4412的芯片手册看,上面的初始化过程并没有任何问题,但是为什么串口就是没有输出呢?根据以前的经验,串口的初始化还和时钟频率是有关系的,在之前的所有修改中,我们都没有对时钟频率进行初始化,很有可能之前的时钟频率初始化的代码是无效的,开发板就一直以晶振24MHz运行。其实从arch/arm/mach-exynos/clock_init_exynos4.c的system_clock_init()函数看就知道CMU的寄存器设置是有问题的,大家当然可以照着4412的芯片手册修改这个函数里面的值,但是我找到了一个更适合的函数,位于board/samsung/odroid/odroid.c中的board_clock_init()函数,为什么会找到这个函数呢,我是通过exynos4x12_clock这个结构体找到这个时钟初始化函数的,在原来的system_clock_init()函数中使用的是exynos4_clock,明显不能适配所有情况。不过board_clock_init()只是将APLL时钟设置到1GHZ,4412芯片的APLL时钟是可以到达1.4GHz的。不过只要修改个别数值就可以了。
因为这部分内容修改太多,我将代码上传到github了,想了解具体修改了什么内容的朋友可以上去下载,通过git diff来查看前后的修改。
通过上面的修改,串口就能够运行起来了,也能将信息打印到串口。接下来分析copy_uboot_to_ram()这个函数,这个函数看函数名就知道作用了,这个函数是将u-boot拷贝到DRAM中继续运行的。最主要的是作如下修改:
diff --git a/arch/arm/mach-exynos/spl_boot.c b/arch/arm/mach-exynos/spl_boot.cindex 7df0102..72aae50 100644--- a/arch/arm/mach-exynos/spl_boot.c+++ b/arch/arm/mach-exynos/spl_boot.c@@ -222,9 +222,14 @@ void copy_uboot_to_ram(void) break; #endif case BOOT_MODE_SD:+ /* offset = BL2_START_OFFSET; size = BL2_SIZE_BLOC_COUNT; copy_bl2 = get_irom_func(MMC_INDEX);+ */+ offset = UBOOT_START_OFFSET;+ size = UBOOT_SIZE_BLOC_COUNT;+ copy_bl2 = get_irom_func(MMC_INDEX); break; #ifdef CONFIG_SUPPORT_EMMC_BOOT case BOOT_MODE_EMMC:@@ -253,9 +258,32 @@ void copy_uboot_to_ram(void) default: break; }-+#ifdef CONFIG_TINY4412 if (copy_bl2)+ {+ unsigned int i , count = 0;+ unsigned char *buffer = (unsigned char *)0x02050000;+ unsigned char *dst = (unsigned char *)CONFIG_SYS_TEXT_BASE;+ unsigned int step = (0x10000 / 512);++ for (count = 0; count < UBOOT_SIZE_BLOC_COUNT; count += step)+ {+ copy_bl2((u32)(UBOOT_START_OFFSET+count), (u32)step, (u32)buffer);++ for (i = 0; i < 0x10000; i++)+ {+ *dst++ = buffer[i];+ }+ }+ printascii("copy_uboot_to_ram done! \n");+ }+#else+ if (copy_bl2) {+ printascii("Go to copy_bl2().\n"); copy_bl2(offset, size, CONFIG_SYS_TEXT_BASE);+ printascii("copy_bl2 finish! \n");+ }+#endif } void memzero(void *s, size_t n)
上面的代码的主要作用是通过一个缓存区域,最后将u-boot拷贝到CONFIG_SYS_TEXT_BASE位置,然后跳转到CONFIG_SYS_TEXT_BASE处运行。当然,代码要能够在DRAM中运行的话,DRAM的初始化过程是必须的,本人对DRAM的初始化过程并不是很熟悉,大家有兴趣的可以上网查资料看看,大概修改如下:
diff --git a/arch/arm/mach-exynos/dmc_init_exynos4.c b/arch/arm/mach-exynos/dmc_init_exynos4.cindex 1d3c388..92867b3 100644--- a/arch/arm/mach-exynos/dmc_init_exynos4.c+++ b/arch/arm/mach-exynos/dmc_init_exynos4.c@@ -124,6 +124,10 @@ static void dmc_init(struct exynos4_dmc *dmc) writel(mem.memconfig0, &dmc->memconfig0); writel(mem.memconfig1, &dmc->memconfig1);+#ifdef CONFIG_TINY4412+ writel(0x8000001F, &dmc->ivcontrol);+#endif+ /* Config Precharge Policy */ writel(mem.prechconfig, &dmc->prechconfig); /*@@ -175,7 +179,8 @@ void mem_ctrl_init(int reset) * 0: full_sync */ writel(1, ASYNC_CONFIG);-#if (defined CONFIG_ORIGEN) || (defined CONFIG_TINY4412)+#ifndef CONFIG_TINY4412+#ifdef CONFIG_ORIGEN /* Interleave: 2Bit, Interleave_bit1: 0x15, Interleave_bit0: 0x7 */ writel(APB_SFR_INTERLEAVE_CONF_VAL, EXYNOS4_MIU_BASE + APB_SFR_INTERLEAVE_CONF_OFFSET);@@ -204,6 +209,7 @@ void mem_ctrl_init(int reset) ABP_SFR_SLV_ADDRMAP_CONF_OFFSET); #endif #endif+#endif /* DREX0 */ dmc = (struct exynos4_dmc *)samsung_get_base_dmc_ctrl(); dmc_init(dmc);
最后还有一点就是,SD卡的布局情况,SD卡的布局情况和之前文章中提到的布局有部分不同,主要是在BL2区域后还有一片区域是用于保存一些环境变量信息的,所以还需要做如下修改:
diff --git a/include/configs/tiny4412.h b/include/configs/tiny4412.hindex 2c2b5b7..3c2bba9 100644--- a/include/configs/tiny4412.h+++ b/include/configs/tiny4412.h@@ -112,8 +112,9 @@ #define CONFIG_SYS_MMC_ENV_DEV 0 #define CONFIG_ENV_SIZE (16 << 10) /* 16 KB */ #define RESERVE_BLOCK_SIZE (512)-#define BL1_SIZE (16 << 10) /*16 K reserved for BL1*/-#define CONFIG_ENV_OFFSET (RESERVE_BLOCK_SIZE + BL1_SIZE)+#define BL1_SIZE (8 << 10) /*8 K reserved for BL1*/+#define BL2_SIZE (16<< 10) /*16 K reserved for BL2 */+#define CONFIG_ENV_OFFSET (RESERVE_BLOCK_SIZE + BL1_SIZE + BL2_SIZE) #define CONFIG_SPL_LDSCRIPT "board/samsung/common/exynos-uboot-spl.lds" #define CONFIG_SPL_MAX_FOOTPRINT (14 * 1024)
到这里,我们就可以编译运行了,连接串口可以看到开发板已经运行到新的位置了
从截图中可以看到,开发板卡在DRAM的大小识别部分了,显然还有部分内容没有修改,导致开发板对DRAM的大小识别有误,不过要想让其运行起来,可以先做如下修改,将tiny4412.h文件中:
#define CONFIG_NR_DRAM_BANKS 4
修改为
#define CONFIG_NR_DRAM_BANKS 2
开发板就可以正常执行了,只是识别的DRAM大小有误,在下一篇文章中会继续修改分析,这篇就先到这里了!
代码可以通过如下指令下载:
git clone https://github.com/xiaojimmychen/u-boot.git
Thanks!
- Uboot2016 for tiny4412调试
- 为u-boot-2016 for tiny4412添加点灯调试代码
- ubuntu16 dnw for tiny4412
- Ubuntu 14.04 编译 Android 4.2.2 for Tiny4412
- Gps driver for Tiny4412+Android4.2.2(by liukun321咕唧咕唧)
- 第六章——uboot for tiny4412中MMU虚拟地址设置
- uboot for tiny4412 SD驱动问题修复,SD卡启动内核
- Tiny4412 uboot
- Tiny4412 小试牛刀
- 【Tiny4412】 Tiny4412开发环境搭建
- chrome调试for js
- eclipse for php zendDebugger调试
- qt for windows 安装调试
- IAR FOR STM8S 调试信息
- tiny4412 SD卡烧录命令
- tiny4412编译android出错
- tiny4412看门狗的禁用
- tiny4412预装apk
- Linux下查看tomcat日志及乱码解决方案
- ICLR 2017 | Attention 和 Memory Networks
- 导出Excel(npoi)
- NIPS 2016 | Best Paper, Dual Learning, Review Network, VQA 等论文选介
- golang实时消息平台NSQ的使用
- Uboot2016 for tiny4412调试
- ACL 2016 | Modeling Coverage for Neural Machine Translation
- ACL 2016 | CopyNet 和 Pointer Softmax
- irq change
- 干货 | 你真的了解 Convolutional Neural Networks 么
- 干货 | Generative Adversarial Networks(GAN)的现有工作
- Laravel数据库操作之-DB facade
- Laravel数据库操作之-增删改查CURD操作
- 编码(一):编码简介