Linux内核(Day19)

零 补充:
    vim 中跳转到函数的开头的位置:{{
    跳转到函数的开头的位置 }}
    
    
    

一 回忆昨天的内容
    
    qemu 的安装  gdb调试工具的使用
    模拟arm核执行的状态
    
    ARM 汇编
    位运算指令
    and orr eor ...
    
    比较测试指令
    cmp cmp不加s,也会影响NZCV位
    tst
    ...
    
    加载存储指令
    ldr r0, [r1]
    内存中load到寄存器 (只能是通用寄存器)
    
    str r0, [r1] 
    将寄存器中的内容写入到内存中 (只能是通用寄存器)
    
    ldmxx 
        fd   满栈指的是栈指针指向的内存中有数据,先改变sp的位置,在放数据
        fa
        ed     增栈和减栈指的是从低地址到高地址还是相反的
        ea
    stmxx
                 将数据从寄存器store进内存
                 
    局部变量的栈空间中的分布 重点掌握!

二 移植uboot,阅读uboot的源码

     面试题:谈谈对uboot的理解
     问:ubootpak.bin 从哪里来?
     
     2.1 首先聊聊uboot的特点
     a) uboot 属于bootloader的一种,还有armboot, vivi, redboot...
     b) uboot 是著名的开源软件,相当于PC机上的bios, 德国的denx小组开发维护
             http://www.denx.de 
     c) uboot本质上是一个裸板程序,跟咱们的shell裸板程序一样
     d) uboot支持多种架构,arm,ppc, mips, dsp, fpga... 支持的开发板达上万种
     e) uboot和硬件是息息相关,所以移植性较差
     
     找开发板厂商提供源码,修改之后,匹配平台。
     
     2.2 然后谈谈uboot的三大功能:
     a) 初始化硬件的功能:
             初始化硬件的目的?本质目的就是为了运行linux内核,提前准备运行环境
             例如: mmc read 0x48000000 0x800 0x3000 初始化emmc  mmc read 
             初始化cpu, 内存 .....
             
             需要将开发板上的所有硬件都初始化么?
             答:不需要,因为uboot是引导linux内核并且生命周期极短,
             如果做大量的硬件的初始化,浪费时间
             linux内核一旦接管,uboot做的初始化工作就无效了。
             
             问:哪些硬件做初始化是必要的?
             8大硬件
             1.初始化cpu, 主要是在初始化cache缓存, 将cache中的数据指令进行
             清除, 为了防止cpu一上电就去cache中拿数据,造成各种异常。
             2.初始化系统时钟 sys tick  IIC控制器的时钟, uart的时钟....
             3.初始化内存
             4.初始化闪存 EMMC 
                 将来一旦引导起来linux内核, 中断报给linux内核。
             7.初始化串口 研发阶段  发布阶段 
             5.初始化网卡 OTG_USB 
             6.关闭中断(Event), 加快系统的启动速度,
                 缩短启动时间,提高用户体验。
             8.关闭看门狗:加快系统启动的速度,防止系统发生复位
             
     b)    从emmc中加载linux内核到内存,并且启动linux内核
             setenv bootcmd mmc read 0x48000000 0x800 0x3000 \; bootm 0x48000000
             
     c) 给linux内核传参,告诉linux内核根文件系统在emmc的哪个分区上
           setenv bootargs root=/dev/mmcblk0p2 init=/linuxrc console=ttySAC0,115200
           lcd=wy070ml tp=gslx680-linux loglevel=2
           
     2.3 谈谈uboot的源码操作
         实施步骤:
             a) 建议从厂商获取源码  
             b) 交叉编译工具
             注意此代码仅仅支持芯片厂家的参考版,不一定能在你的开发板上运行起来
             将来势必要根据硬件的差异修改uboot源码
             c) 拷贝uboot.tar.gz 到虚拟机的porting目录下
                tar xf uboot.tar.gz 
                cd uboot
                make distclean ---> 获取做干净的源码
                make x6818_config 
                //配置uboot源码, 配置成能够匹配abc这个参考版,只做一次
                make 
             d) 一旦编译通过,会生成ubootpak.bin 
                接下来根据硬件的差异,修改uboot的源码
                硬件差异怎么确定?
                答:管硬件工程师要 (这是他的义务)
             e) 直接上来修改uboot源码中跟硬件相关的文件
                 vi uboot/include/configs/x6818.h 
                 其中包含了大量外设的硬件信息。只需要根据宏进行修改。
                 
     2.4 uboot的源码组织结构:
             1. 问如何知道Uboot源码运行的入口地址?
                 只要知道了入口地址,然后顺藤摸瓜理清代码的执行流程, 
                 有针对性的修改代码。
                 通过链接脚本,找到入口地址:
                 make V=1
                 从末尾往前找,找到连接器的链接信息。
                 arm-cortex_a9-linux-gnueabi-ld.bfd   -pie  
                 --gc-sections -Bstatic -Ttext 0x43C00000 -o u-boot 
                 -T u-boot.lds arch/arm/cpu/slsiap/start.o 
                 
                 -Ttext 0x43C00000 :指定了uboot代码段的起始地址
                 -T u-boot.lds: 指定了链接时链接脚本
                 
                 找到了入口点文件:
                 arch/arm/cpu/slsiap/s5p6818/start.S
                 
                 结论:uboot代码段的第一个文件为:
                 arch/arm/cpu/slsiap/s5p6818/start.S 
                 
                 研究uboot的目录结构:
                 利用ctags 工具阅读分析uboot的源码:
                 理清uboot代码的执行流程:
                 1. 只关注流程,不要关注细节 
                 2. 看注释和参数返回值等信息
                 
                 怎么确定函数是否被调用:
                 在函数中添加打印信息
                 
                 uboot代码的执行流程:
                 上电-> uboot -> _stext --> b reset---> bl board_init_f 
                 --> ldr pc, =board_init_r ---> run_main_loop --> main_loop
                 --> cli_loop ---> cli_simple_loop ---> for(;;) //读秒,探测热键
                 
                 board_init_f: 
                     if (initcall_run_list(init_sequence_f))
                      发现 init_sequence_f 是一个函数指针数组
                      将数组中的每一个函数都调用了一遍
                              board_early_init_f:
                                      db_gpio_init
                                      nxp_rtc_init
                                      ....
                      hang();//如果硬件初始化异常,
                      直接让uboot进入死循环,不允许继续执行
                      
                      
                 board_init_r:
                     init_fnc_t init_sequence_r[] = {
                         board_init,
                         initr_serial,
                         .....
                         arch_early_init_r,
                         .....
                     };
                     
                 uboot的代码组织结构:
                 见图 
             
             mmu_turn_on
                 物理地址,直接出现在地址总线上的值
                 虚拟地址,开启mmu后,由ARM核发出没有经过mmu翻译的地址
                 
             终极结论:
             1. uboot中如果将来某个硬件初始化的时候发生异常,只需要在数组中找
             到对应的硬件初始化函数,然后跟踪这个函数,找到问题所在
             2. 如果将来在Uboot中添加一个新的硬件初始化的函数
             直接在数组中添加,在可以编译到的文件中实现。
             例如:
             int led_init (void)
             {
                 return 0;//成功
                 ....
                 return -1;//失败
             }

三 在uboot中添加logo显示

    问:为何要添加logo?
    商业化的行为,提升用户体验
    
    logo本质上是一个图片
    ARM处理器如何在LCD屏上显示logo图像呢?
    答:首先在内存中开辟一段空间用来存储logo,
    这块内存简称显存,将来内存控制器自动从显存中获取图像。
    然后处理器将图像放到lcd控制器的地址总线上,LCD控制器会
    自动的将图像显示到屏幕上。
    
    logo图像在显存中如何存储?
    答:图像是由一堆的像素点组成的,并且每一个像素点具有一种颜色。
    每种颜色又是由RGB三种颜色组成。
    
    X6818开发板分辨率 1024*600
    颜色值在内存中的存储格式:
    32位
        31-------23------15----7-----0
             透明度         R       G    B
    24位
        23------15-----7----0
                R                G            B
    
    实战演练:
    向X6818开发板的LCD屏上添加LOGO显示功能
    具体的实施步骤:参见《LOGO显示》
    
    
    
    

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值