历史上的今天
今天是:2025年11月17日(星期一)
2022年11月17日 | S3C2440移植linux3.4.2内核之内核框架介绍及简单修改
2022-11-17 来源:zhihu
uboot启动内核分析
进入cmd_bootm.c,找到对应的bootm命令对应的do_bootm():
int do_bootm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
boot_os_fn *boot_fn; //boot_fn是个数组函数
... ..
boot_fn(0, argc, argv, &images); //调用数组函数
... ...
}
boot_os_fn是个typedef型,如下图所示:

由于定义了宏CONFIG_BOOTM_LINUX,最终会跳转到do_bootm ->do_bootm_linux() 代码如下所示:
int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images)
{
/* No need for those on ARM */
if (flag & BOOTM_STATE_OS_BD_T || flag & BOOTM_STATE_OS_CMDLINE)
return -1;
if (flag & BOOTM_STATE_OS_PREP) {
boot_prep_linux(images);
return 0;
}
if (flag & BOOTM_STATE_OS_GO) {
boot_jump_linux(images);
return 0;
}
boot_prep_linux(images); //该函数会将各个tag参数保存在指定位置,比如:内存tag、bootargs环境变量tag、串口tag等
boot_jump_linux(images); //该函数会跳转到内核起始地址
return 0;
}
最终跳转到do_bootm ->do_bootm_linux-> boot_jump_linux()
static void boot_jump_linux(bootm_headers_t *images)
{
unsigned long machid = gd->bd->bi_arch_number; //获取机器ID
char *s;
void (*kernel_entry)(int zero, int arch, uint params);
unsigned long r2;
kernel_entry = (void (*)(int, int, uint))images->ep; //设置kernel_entry()的地址为0x30000000
s = getenv("machid"); //判断环境变量machid是否设置,若设置则使用环境变量里的值
if (s) {
strict_strtoul(s, 16, &machid); //重新获取机器ID
printf("Using machid 0x%lx from environmentn", machid); //使用环境变量的machid
}
... ...
r2 = gd->bd->bi_boot_params; //获取tag参数地址, gd->bd->bi_boot_params在setup_start_tag()函数里被设置
kernel_entry(0, machid, r2); //跳转到0x30000000,r0=0,r1=机器ID,r2=tag参数地址
}
上面的machid默认值为MACH_TYPE_SMDK2410(也就是193),我们也可以在环境变量里设置machid变量 最终,便跳到内核执行代码,步骤如下所示: 1)根据R1(机器ID),来判断内核是否支持该机器,若支持则初始化机器相关函数 2)解析TAG参数,初始化串口,设置内存等 3)挂载根文件系统,并执行应用程序
简单配置内核
修改Makefile,修改配置
tar xjf linux-3.4.2.tar.bz2
cd linux-3.4.2/
vi Makefile

改为
ARCH ?= arm
CROSS_COMPILE ?= arm-linux-
配置编译
cd arch/arm/configs //由于我们板子是arm板,进入该目录
ls *2440* //找到有mini2440_defconfig、
ls *2410* //找到有s3c2410_defconfig
cd ../../..
make s3c2410_defconfig //配置2410, 更新.config配置文件
make uImage //编译,生成uImage
cp arch/arm/boot/uImage /work/nfs_root/ //拷贝
cd /work/nfs_root/
mv uImage uImage_new

进入.config查看支持的CPU
vi .config

如上图所示,有我们的2440
编译内核
make uImage
报错如下
Can't use 'defined(@array)'(Maybe you should just omit the defined? )at kernel/timeconst pl line 373
/root/working/Hi3520D SDK V2.0.3.0/osdrv/kernel/linux-30y/kernel/Makefile:140
recipe for target kernel/timeconst h failed make【1】:*** 【kernel/timeconst h】 Error 255
Makefile:945:recipe for target kernel ' failed
【kernel】 Error 2
解决办法: 将 kernel/timeconst.pl中第373行的 defined0去掉只留下@val就可以了
vim kernel/timeconst.pl +373
进入uboot烧写
nfs 32000000 192.168.2.106:/work/nfs_root/uImage_new
bootm 32000000
如下图所示,发现串口输出乱码:

设置机器ID
uboot传递进来的机器ID可以通过环境变量machid来设置 所以任意设置一个ID,这样再次启动内核时,内核识别不出来,就会打印出所有设备对应的机器ID。下面开始测试机器ID是否正确,进入uboot,输入:
set machid 33333
tftp 32000000 uImage
bootm 32000000
如下图所示,由于内核不支持这个机器ID,所以打印出内核能支持的ID表:

ID所对应的文件为arch/arm/mach-s3c24xx/Mach-smdk2440.c
MACHINE_START为一个结构体,根据不同的机器ID找到对应的MACHINE_START,调用初始化函数。 由于我们板子是2440,所以测试7cf(mini2440)以及16a(smdk2440)这两个机器ID,是否支持我们开发板。 但是依旧乱码,可能是波特率设置不正确。重新设置下环境变量的波特率
set bootargs root=/dev/mtdblock3 console=ttySAC0,115200
再次烧写启动,发现7cf(mini2440)这个ID,有串口输出正常。下面看下16a(smdk2440)为什么串口乱码,进入mach-smdk2440.c( 位arch/arm/mach-s3c24xx)找到问题出在smdk2440_map_io():
static void __init smdk2440_map_io(void)
{
s3c24xx_init_io(smdk2440_iodesc, ARRAY_SIZE(smdk2440_iodesc));
s3c24xx_init_clocks(16934400); //初始化时钟clock
s3c24xx_init_uarts(smdk2440_uartcfgs, ARRAY_SIZE(smdk2440_uartcfgs));
}
修改晶振
由于我们板子上的晶振是12Mhz,而mdk2440_map_io()里,初始化的时钟是基于16934400hz的晶振。所以将:
s3c24xx_init_clocks(16934400); //初始化时钟clock
改为:
s3c24xx_init_clocks(12000000); //初始化时钟clock
然后重新编译uImage:
make s3c2410_defconfig //将mach-s3c2440.c配置进内核
make uImage
cp uImage /work/nfs_root/ uImage_new
进入uboot,输入:
set machid 16a
nfs 32000000 192.168.1.30:/work/nfs_root/uImage_new
bootm 32000000
启动内核打印正常。
史海拾趣
|
ginny 14:50:25 一个有趣的问题:几乎所有的cpu都晶振,人脑也相当于cpu,大家猜猜,人脑有类似于晶振的组织吗? O□(291888386) 14:50:51 心脏 ginny 14:51:04 那也太慢的吧 O□(291888386) 14 ...… 查看全部问答> |
|
armsys2410 大容量sd卡驱动开发我的pb5.0更新了微软的《Windows CE 5.0 支持仅 SD 1.1 兼容的内存卡所小于 2 GB 》中提到的更新, 工程里也将 IMGSDBUS2 变量的值设置为 1。 直接加载了CataLog里的sd memory以及samsung 2410 sdio host. 但是ar ...… 查看全部问答> |
|
我的屏幕是宽屏。想转90度当竖屏使用。 就是这种效果 11111111111111111111111 11111111111111111111111 现在安装的时候竖起来了。 11 11 11 11 11 11 11 11 11 怎样在竖起来的屏幕上面正确显示呢?… 查看全部问答> |
|
CString c_sTime(\"010904\"); CString hour =c_sTime.Left(2); int num=atoi((char*)(LPCTSTR)hour); 转换后得到的num为0为什么;那一步出错了… 查看全部问答> |
|
应用LM3S8962的网络功能,将ZigBee网络融合,实现上位机远程监控。目前是用LM3S3739做的ZigBee协调器,如果组网成功,改用LM3S8962应该比较简单。… 查看全部问答> |
|
想清除ST10F269Z2Q6的Flash,结果用ST Flasher Tools 2.4B - Erase Flash时,出错,信息如下:* ERASE BANKS -->ERRORDescription: EraseFlash failed.Flash: block erase:&n ...… 查看全部问答> |
|
CCSv5.4.0 Beta 1来啦!希望能够支持ubuntu下调试430LaunchPad 在http://e2e.ti.com/support/development_tools/code_composer_studio/f/81/t/251388.aspx一帖子中unfortunately the mps430 launchpad and eZ sticks are not yet supported under linux.Sorry for the inconvenience. http://www.deyisupport.c ...… 查看全部问答> |




