今天看了一下达克洛德的裸奔程序,突发奇想,既然能引导自己的程序,那也可以引导linux内核吧,这样bootloader可以小到几k吧
离线
怎么做到的?
离线
直接启动?引导程序肯定打包进linux内核了,zlg的i.mx287开发板也有这样的方式。总之引导过程避免不了,从裸奔程序提炼出引导程序肯定比uboot小很多,这样引导程序的启动时间基本可以忽略。
离线
把基本外设初始化好,再向内核传参就行,可以做到很小,启动时间主要是从flash加载内核到内存耗时比较长
离线
把基本外设初始化好,再向内核传参就行,可以做到很小,启动时间主要是从flash加载内核到内存耗时比较长
需要传参吗?如何传参,不是有设备树吗?
离线
需要传递一个tag列表或设备树地址给内核,简化的bootloader做到4kb以内都很正常
需要传参吗?如何传参,不是有设备树吗?
离线
需要传递一个tag列表或设备树地址给内核,简化的bootloader做到4kb以内都很正常
感谢回复,很有帮助。做一个简单的boot,从start.s文件中找到一段关键代码:
/* Initial system clock, ddr add uart */
bl sys_clock_init
bl sys_dram_init
bl sys_uart_init
/* Copyself to link address */
adr r0, _start
ldr r1, =_start
cmp r0, r1
beq 1f
bl sys_copyself
这段代码几乎是核心引导了,加上copy linux内核代码应该就可以了,然后跳转到linux内核地址
最近编辑记录 kekemuyu (2020-01-05 23:15:40)
离线
这里就是主程序入口,很简单嘛,怀念8051汇编的日子。有时候挺喜欢汇编的,让我有一种全局掌控的感觉,了解所有寄存的状况,内存,堆栈,中断都在自己的掌控之中
/* Call _main */
ldr r1, =_main
mov pc, r1
_main:
mov r0, #1;
mov r1, #0;
bl boot_main
b _main
最近编辑记录 kekemuyu (2020-01-05 23:28:06)
离线
和楼主有同样的想法,加油!我可能会试试uboot裁剪这条路。我这个裸机有点问题好像200s的高32MB内存用不起来
离线
和楼主有同样的想法,加油!我可能会试试uboot裁剪这条路。我这个裸机有点问题好像200s的高32MB内存用不起来
感谢@达克罗德 大神对f1c100s裸奔的所做的大量工作,我等菜鸟才可以一探f1c100s内部的工作原理。uboot裁剪有点难搞,开始也是想看一下uboot源码,可不知道从哪里下手,本来想看一下makefile,可是makefile文件太多了,不知道从哪一个看起。有时间还邀请大神普及一下uboot和linux内核的编译过程。
离线
和楼主有同样的想法,加油!我可能会试试uboot裁剪这条路。我这个裸机有点问题好像200s的高32MB内存用不起来
heap中的len改成48M,应该就支持了吧
MEMORY
{
ram : org = 0x80000000, len = 8M
dma : org = 0x80800000, len = 8M
heap : org = 0x81000000, len = 16M
}
最近编辑记录 kekemuyu (2020-01-06 15:09:44)
离线
需要明确一件事,把设备树和linux内核加载到ram后,只要把设备树地址赋值给r2寄存器,然后跳转到linux地址就可以了吗?linux就会自动解析设备树了吗?
内核对设备树的处理也是分这三部分的。
1. 对于32bit的arm处理器,bootloader启动内核时,会设置r0,r1,r2三个寄存器,
r0一般设置为0;
r1一般设置为machine id (在使用设备树时该参数没有被使用);
r2一般设置ATAGS(使用设备树之前)或DTB的开始地址(使用设备树之后)
bootloader给内核传递的参数时有2种方法:ATAGS 或 DTB
a. __lookup_processor_type : 使用汇编指令读取CPU ID, 根据该ID找到对应的proc_info_list结构体(里面含有这类CPU的初始化函数、信息)
b. __vet_atags : 判断是否存在可用的ATAGS或DTB
c. __create_page_tables : 创建页表, 即创建虚拟地址和物理地址的映射关系
d. __enable_mmu : 使能MMU, 以后就要使用虚拟地址了
e. __mmap_switched : 上述函数里将会调用__mmap_switched
f. 把bootloader传入的r2参数, 保存到变量__atags_pointer中
g. 调用C函数start_kernel
head.S/head-common.S :
把bootloader传来的r1值, 赋给了C变量: __machine_arch_type
把bootloader传来的r2值, 赋给了C变量: __atags_pointer // dtb首地址
对于32bit的arm处理器,machine_desc 使用 MACHINE_START 初始化,其 dt_compat 存储的是 compatible 属性数组,用于表示支持的单板。
u-boot 中也提供的对dtb文件进行操作的命令,为 fdt, uboot 中所有的命令都是使用U_BOOT_CMD()来定义的,对应文件中有命令的使用注释。
离线
现在的模式, linux 和 dtb 是单独打包的, 我记得 openwrt 是打包到一起的, 不知道f1c100s能不能这样操作?
离线
现在的模式, linux 和 dtb 是单独打包的, 我记得 openwrt 是打包到一起的, 不知道f1c100s能不能这样操作?
可以的
离线
顺便说一下,start.s不是必要的。可以通过设置代码段的方式强行把数组放到一个段里面,然后让LD把这个段放到代码的最开始。这样SPL header和向量表就可以都用C写了。纯C是完全可以实现bootloader的,反正性能不是那么重要,真正引导之后各种核心函数比如memcpy都在内核里面重新写了。bootloader有很多懒人写法,比如把堆放到栈上面,LD脚本和sbrk的实现都会简单很多。
基本上能把时钟和内存初始化了,能读闪存,能加载内核和参数(DTB等),就可以引导。F1C 32KB的SPL的空间应该够了,不需要第三阶段引导器。XBoot的SPL包含上述全部外加一些其他驱动,也就是16KB。如果不用既有框架而是从头开始为F1C手写的话,应该能再小。之前我闲的玩F1C的时候写的纯C向量表+时钟+内存+SPI+NOR+UART+hello world也就是几KB。后来没时间了,要不然准备练手写个最简RTOS的。
离线
想要实现简单的裸奔挺容易的,但要实现较全功能的裸奔就比较复杂了!
离线
aodzip大佬patch过的uboot不香么,USB OTG 也支持了,直接那上面修改就好了。
离线