linux kernel 4.6 移植到imx280手札

来源:互联网 发布:java怎么配置环境变量 编辑:程序博客网 时间:2024/05/22 02:54

资源简介

周立功过节发招,49元买了imx280核心板:

ARM926EJ-S 架构 arm v5TE 指令集,cpu最高能跑450M

默认光盘资料是 比较老的uboot-2009加linux-2.6内核。

因为本人电脑是ubuntu环境,周立功提供的烧写环境都不适用与我的电脑。

不过众里寻他千百度,终于在开源项目rockbox里面找到一个linux下面的usb烧写工具.

外加一根串口线。我就是移植的全部外部环境。

自己的代码环境在github上面放了个仓库,方面回老家的时候也能够写代码。

https://github.com/QtForQT/imx280_zlg.git


心酸史(一) 串口输出

通过下载了最新的kernel(我移植时2016年5月)发现里面默认支持了imx28这颗芯片。当时高兴呀,以为只要make一下就能运行了。
通过make ARCH=arm CROSS_COMPILE=****  mxs_defconfig && make zImage然后替换周立功bootloader/imx-bootlets-src-10.12.01/ 里面的zImage
发现只有  “Uncompressing Linux... done, booting the kernel.” 然后喜忧参半,高兴的是已经跳到kernel并且解压完成的了,忧伤的是:WTF,只要一句话。
然后开始折腾打印,通过看源码,和google
发现这句话能打印的原因是:bootloader初始化好了串口。也就是arch/arm/boot/compressed/里面能够打印
通过加打印发现解压完成跳进kernel里面就没有打印了。于是看arch/arm/kernel/head.S的代码
里面调用了__error_p然后最终调用了printascii来打印。
__error_p:#ifdef CONFIG_DEBUG_LL        adr     r0, str_p1        bl      printascii        mov     r0, r9        bl      printhex8        adr     r0, str_p2        bl      printascii        b       __errorstr_p1: .asciz  "\nError: unrecognized/unsupported processor variant (0x"str_p2: .asciz  ").\n"        .align#endifENDPROC(__error_p)

注意两点:一个是宏:CONFIG_DEBUG_LL一个是printascii
printascii的实现:

ENTRY(printascii)                addruart_current r3, r1, r2                b       2f1:              waituart r2, r3                senduart r1, r3                busyuart r2, r3                teq     r1, #'\n'                moveq   r1, #'\r'                beq     1b  2:              teq     r0, #0                ldrneb  r1, [r0], #1                teqne   r1, #0                bne     1b                  ret     lr  ENDPROC(printascii)

然后打开了CONFIG_DEBUG_LL宏,查看.config
发现里面会有CONFIG_DEBUG_LL_INCLUDE=“debug/pl01x.S”
然后在arch/arm/include/debug/pl01x.S里面实现了
addruart,senduart,busyuart三个宏。
当然这其中还有因为编译的是mxs_defonfig它里面及支持imx23和imx28需要把imx23 uart相关的去掉。
就这样愉快的加打印直到有一天。。。。。。。。

__turn_mmu_on关了我的世界

当__turn_mmu_on过后串口就没有输出了。看这个货,估计是打开mmu了。更具常识猜测,可能:
1.uart相关的内存没有映射上来
2.uart的虚拟地址不对。
疯狂的看源码,找到了映射虚拟地址的地方:
__create_page_tables:        pgtbl   r4, r8                          @ page table address......................................................................#ifdef CONFIG_DEBUG_LL#if !defined(CONFIG_DEBUG_ICEDCC) && !defined(CONFIG_DEBUG_SEMIHOSTING)        /*         * Map in IO space for serial debugging.         * This allows debug messages to be output         * via a serial console before paging_init.         */        addruart r7, r3, r0        mov     r3, r3, lsr #SECTION_SHIFT        mov     r3, r3, lsl #PMD_ORDER        add     r0, r4, r3        mov     r3, r7, lsr #SECTION_SHIFT        ldr     r7, [r10, #PROCINFO_IO_MMUFLAGS] @ io_mmuflags        orr     r3, r7, r3, lsl #SECTION_SHIFT............................................................................................................................#ifdef CONFIG_DEBUG_LL#if !defined(CONFIG_DEBUG_ICEDCC) && !defined(CONFIG_DEBUG_SEMIHOSTING)        /*         * Map in IO space for serial debugging.         * This allows debug messages to be output         * via a serial console before paging_init.         */        addruart r7, r3, r0        mov     r3, r3, lsr #SECTION_SHIFT        mov     r3, r3, lsl #PMD_ORDER        add     r0, r4, r3        mov     r3, r7, lsr #SECTION_SHIFT        ldr     r7, [r10, #PROCINFO_IO_MMUFLAGS] @ io_mmuflags        orr     r3, r7, r3, lsl #SECTION_SHIFT

发现它是通过addruart来获得uart的物理和虚拟地址,然后映射了的。也就是说,地址是映射了的,因为这个宏我们第一步的时候打开了的。
在检查虚拟地址:

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

在arch/arm/Kconfig.debug中找到了
default 0xfe100000 if DEBUG_IMX23_UART || DEBUG_IMX28_UART
但是怎样得到虚拟地址呢?我google很久,但是还是没有找到规则。最终取了个巧,从周立功的代码得到了正确的地址。
default 0xf0074000 if DEBUG_IMX23_UART || DEBUG_IMX28_UART

走到哪里了?

然后安装debug流程在lib/vsprintf.c里面加上了printascii贴出来的代码是我后来注释掉的:
int vscnprintf(char *buf, size_t size, const char *fmt, va_list args){        int i;        i = vsnprintf(buf, size, fmt, args);//#if defined(CONFIG_DEBUG_LL)//extern void printascii(const char *);//      printascii(buf);//#endif        if (likely(i < size))                return i;        if (size != 0)                return size - 1;         return 0;}EXPORT_SYMBOL(vscnprintf);
然后在init/main.c中把
bool initcall_debug = 1;
这样可以看在加载那个模块时失败了的。
最终确定了是加载application uart卡住了。为了尽快启动我直接去掉了这个驱动

打开串口


为了能够进入控制台,和打印输出。有把debug uart串口打开。也就是前面的pl011
arm,primecell-periphid = <0x00041011>;



0 0
原创粉丝点击