zz-am335x-LinuxKernel启动流程初始化141221c
来源:互联网 发布:电子海洛因 知乎 编辑:程序博客网 时间:2024/06/03 18:00
//zz//#######################################################################
zz-am335x-LinuxKernel启动流程初始化141221c
zz-Write:
@2014-12-21 22:40:25
@2014-12-21 23:57:29
@2014-12-22 00:01:41
Tab 转4空格,方便 csdn_blog 上传
@
REF:
linux-3.2.0-psp04.06ti-zz141219b.zip
ti-sdk-am335x-evm-06.00.00.00-Linux-x86-Install.bin
linux内核启动流程(上)
http://blog.csdn.net/williamwang2013/article/details/8691883
linux内核启动流程(下)
http://blog.csdn.net/williamwang2013/article/details/8695618
KeyWord:
ECC 校验 => BCH 8/12/16 bits => 2K: 13*4/??/14*?? Bytes
arch/arm/mach-omap2/board-am335xevm.c
MACHINE_START(AM335XIAEVM, "am335xiaevm")
am335x_evm_init();
struct evm_dev_cfg gen_purp_evm_dev_cfg[] = {...};
struct mtd_partition am335x_nand_partitions[] = {...};
arch/arm/boot/compress/head.S
start:
bl decompress_kernel
ARM( mov pc, r4 ) @ call kernel
arch/arm/kernel/head-common.S
b start_kernel
init/main.c
start_kernel()
setup_arch(&command_line);
mdesc = setup_machine_tags(machine_arch_type);
machine_name = mdesc->name;
mdesc->init_early();
setup_machine_tags()
arch/arm/include/asm/mach/arch.h
#define for_each_machine_desc(p) \
for (p = __arch_info_begin; p < __arch_info_end; p++)
//zz//#######################################################################
1.
从汇编代码跳入C入口函数
start: => start_kernel()
arch/arm/boot/compress/head.S
start:
bl decompress_kernel
ARM( mov pc, r4 ) @ call kernel
arch/arm/kernel/head-common.S
b start_kernel
2.
从C入口函数调用板子相关的初始化函数指针列表
1)
根据 machine_arch_type 即板子的 id 在表中查找,匹配 machine_desc
init/main.c
start_kernel()
//zz// MACHINE_START() define struct machine_desc
// init cpu-board __mach_desc_AM335XIAEVM
setup_arch(&command_line);
//zz// machine_desc am335x cpu-board init
// sequence func array[]
struct machine_desc *mdesc;
mdesc = setup_machine_tags(machine_arch_type);
machine_name = mdesc->name;
mdesc->init_early();
setup_machine_tags()
从链表中根据 arch id 查找本板子的 machine_desc 初始化结构体
arch/arm/include/asm/mach/arch.h
#define for_each_machine_desc(p) \
for (p = __arch_info_begin; p < __arch_info_end; p++)
2)
MACHINE_START 宏定义一个板子的 machine_desc 结构体
arch/arm/mach-omap2/board-am335xevm.c
MACHINE_START(AM335XIAEVM, "am335xiaevm")
am335x_evm_init();
struct evm_dev_cfg gen_purp_evm_dev_cfg[] = {...};
struct mtd_partition am335x_nand_partitions[] = {...};
3)
板子相关 machine_desc 结构体的定义 __mach_desc_AM335XIAEVM
arch/arm/mach-omap2/board-am335xevm.c
//zz// MACH_TYPE_##_type => MACH_TYPE_AM335XIAEVM
// __mach_desc_##_type => __mach_desc_AM335XIAEVM
//
// struct machine_desc __mach_desc_AM335XIAEVM
// .nr = MACH_TYPE_AM335XIAEVM;
// .name = am335xiaevm;
MACHINE_START(AM335XIAEVM, "am335xiaevm")
/* Maintainer: Texas Instruments */
.atag_offset = 0x100,
.map_io = am335x_evm_map_io,
.init_irq = ti81xx_init_irq,
.init_early = am33xx_init_early,
.timer = &omap3_am33xx_timer,
.init_machine = am335x_evm_init,
MACHINE_END
//zz//#######################################################################
3.
machine_desc 结构体中函数做了什么
1)
其中重要的初始化函数
am335x_evm_init()
//zz// 1. evm_dev_cfg[] ;init sequence func array are called
am335x_evm_i2c_init();
//zz// 2. am335x_i2c0_boardinfo => .. => evm_dev_cfg[]
omap_register_i2c_bus(1, 100, am335x_i2c0_boardinfo,
ARRAY_SIZE(am335x_i2c0_boardinfo));
//zz// 3. am335x_baseboard_eeprom_info => .. => evm_dev_cfg[]
/* Baseboard board EEPROM */
I2C_BOARD_INFO("24c256", BASEBOARD_I2C_ADDR),
.platform_data = &am335x_baseboard_eeprom_info,
//zz// 4. am335x_evm_setup => .. => evm_dev_cfg[]
.setup = am335x_evm_setup,
.context = (void *)NULL,
//zz// 5. setup_general_purpose_evm() => .. => evm_dev_cfg[]
if (!strncmp("SKU#01", config.opt, 6))
setup_general_purpose_evm();
//zz// 6. gen_purp_evm_dev_cfg[] is evm_dev_cfg array.
_configure_device(boardid, gen_purp_evm_dev_cfg, (1L << prof_sel));
2)
am335x_evm 板子的初始化函数指针数组,这些函数会逐个被调用
这些就是内核启动时候初始化各硬件配置寄存器的函数,可以添加自己自定义的
/* General Purpose EVM */
//zz// 7. gen_purp_evm_dev_cfg[] is sequence func array[]
static struct evm_dev_cfg gen_purp_evm_dev_cfg[] = {
{am335x_rtc_init, DEV_ON_BASEBOARD, PROFILE_ALL},
{clkout2_enable, DEV_ON_BASEBOARD, PROFILE_ALL},
{enable_ecap0, DEV_ON_DGHTR_BRD, (PROFILE_0 | PROFILE_1 |
PROFILE_2 | PROFILE_7) },
{lcdc_init, DEV_ON_DGHTR_BRD, (PROFILE_0 | PROFILE_1 |
PROFILE_2 | PROFILE_7) },
{mfd_tscadc_init, DEV_ON_DGHTR_BRD, (PROFILE_0 | PROFILE_1 |
PROFILE_2 | PROFILE_7) },
{rgmii1_init, DEV_ON_BASEBOARD, PROFILE_ALL},
{rgmii2_init, DEV_ON_DGHTR_BRD, (PROFILE_1 | PROFILE_2 |
... ...
//zz//#######################################################################
4.
start_kernel() 除了完成 arch 初始化,还有其他许多东西需要配置执行
例如
time_init();
console_init();
最后会执行 文件系统的 init 程序等等操作,以后再分析
#########################
1)
arch/arm/mach-omap2/board-am335xevm.c
此文件是移植到一个板子的基础,再增加一点其他的说明
static struct mtd_partition am335x_nand_partitions[] = {
/* All the partition sizes are listed in terms of NAND block size */
{
.name = "SPL",
.offset = 0, /* Offset = 0x0 */
.size = SZ_128K,
},
...
文件系统若使用 nand flash , 则此文件 mtd_partition 类型结构指定了分区信息
必须和 u-boot 写入 nand flash 的位置一样
才可能正确启动 Linux-Kernel
#########################
2)
Nand Ecc 简单说明
am335x 使用的是 ubi 格式的镜像格式烧写文件系统 rootfs
ECC 算法主要有 汉明码 伯明翰(BCH) RS 三种
汉明码:
s3c24x0-ARM9-yaffs-512byte 小页的 nand 使用的多,只能纠正1位错误
BCH伯明翰码:
SLC(2K等较大页) MLC(页很大,4K,8K..) 现在用的多,可以纠正多位 8/12/16 位错误
算法复杂,各家都有自己的算法..
我所知道的两种 BCH 方式所需要的 ECC 码:
2K page 的 OOB 有64Bytes ,其中页开头 2 Bytes 保留用作 Block 坏块标记(虽然只有 该 Block 中Page0 用到)
512 Byte(数据) - 8 bit(t 最大纠错位数) - 13 Bytes(OOB中ECC码) => 2K的页需要 13*4 = 52 字节 ECC 码
512 Byte(数据) - 16 bit(t 最大纠错位数) - 14 Bytes(OOB中ECC码) => 2K的页需要 14*4 = 56 字节 ECC 码
ECC 有硬件和软件实现
设置为 NAND_ECC_NONE 并不是不做 ECC 校验的意思;而是内核Kernel不做,交给 yaffs2 或 ubifs代码来做
include/linux/mtd/nand.h
typedef enum {
NAND_ECC_NONE,
//zz// 内核常用项; 如此 ECC 由文件系统 yaffs2 或者 ubifs 代码中实现 ECC
// 至于是 HW 还是 SOFT 就要看文件系统镜像格式代码中怎么做了
NAND_ECC_SOFT,
//zz// ECC 校验由内核完成,内核采用 SOFT 软件C代码实现
NAND_ECC_HW,
//zz// ECC 校验由内核完成,内核采用 HW 模块实现(操作寄存器?)
NAND_ECC_HW_SYNDROME,
NAND_ECC_HW_OOB_FIRST,
NAND_ECC_SOFT_BCH,
//zz// 可以校验多位(8/12/16)错误的 ECC 校验算法,SLC大页/MLC 现在多用这种
// 但一般也是 yaffs2 或 ubifs 代码来做,不会在内核做吧?
} nand_ecc_modes_t;
zz-am335x-LinuxKernel启动流程初始化141221c
zz-Write:
@2014-12-21 22:40:25
@2014-12-21 23:57:29
@2014-12-22 00:01:41
Tab 转4空格,方便 csdn_blog 上传
@
REF:
linux-3.2.0-psp04.06ti-zz141219b.zip
ti-sdk-am335x-evm-06.00.00.00-Linux-x86-Install.bin
linux内核启动流程(上)
http://blog.csdn.net/williamwang2013/article/details/8691883
linux内核启动流程(下)
http://blog.csdn.net/williamwang2013/article/details/8695618
KeyWord:
ECC 校验 => BCH 8/12/16 bits => 2K: 13*4/??/14*?? Bytes
arch/arm/mach-omap2/board-am335xevm.c
MACHINE_START(AM335XIAEVM, "am335xiaevm")
am335x_evm_init();
struct evm_dev_cfg gen_purp_evm_dev_cfg[] = {...};
struct mtd_partition am335x_nand_partitions[] = {...};
arch/arm/boot/compress/head.S
start:
bl decompress_kernel
ARM( mov pc, r4 ) @ call kernel
arch/arm/kernel/head-common.S
b start_kernel
init/main.c
start_kernel()
setup_arch(&command_line);
mdesc = setup_machine_tags(machine_arch_type);
machine_name = mdesc->name;
mdesc->init_early();
setup_machine_tags()
arch/arm/include/asm/mach/arch.h
#define for_each_machine_desc(p) \
for (p = __arch_info_begin; p < __arch_info_end; p++)
//zz//#######################################################################
1.
从汇编代码跳入C入口函数
start: => start_kernel()
arch/arm/boot/compress/head.S
start:
bl decompress_kernel
ARM( mov pc, r4 ) @ call kernel
arch/arm/kernel/head-common.S
b start_kernel
2.
从C入口函数调用板子相关的初始化函数指针列表
1)
根据 machine_arch_type 即板子的 id 在表中查找,匹配 machine_desc
init/main.c
start_kernel()
//zz// MACHINE_START() define struct machine_desc
// init cpu-board __mach_desc_AM335XIAEVM
setup_arch(&command_line);
//zz// machine_desc am335x cpu-board init
// sequence func array[]
struct machine_desc *mdesc;
mdesc = setup_machine_tags(machine_arch_type);
machine_name = mdesc->name;
mdesc->init_early();
setup_machine_tags()
从链表中根据 arch id 查找本板子的 machine_desc 初始化结构体
arch/arm/include/asm/mach/arch.h
#define for_each_machine_desc(p) \
for (p = __arch_info_begin; p < __arch_info_end; p++)
2)
MACHINE_START 宏定义一个板子的 machine_desc 结构体
arch/arm/mach-omap2/board-am335xevm.c
MACHINE_START(AM335XIAEVM, "am335xiaevm")
am335x_evm_init();
struct evm_dev_cfg gen_purp_evm_dev_cfg[] = {...};
struct mtd_partition am335x_nand_partitions[] = {...};
3)
板子相关 machine_desc 结构体的定义 __mach_desc_AM335XIAEVM
arch/arm/mach-omap2/board-am335xevm.c
//zz// MACH_TYPE_##_type => MACH_TYPE_AM335XIAEVM
// __mach_desc_##_type => __mach_desc_AM335XIAEVM
//
// struct machine_desc __mach_desc_AM335XIAEVM
// .nr = MACH_TYPE_AM335XIAEVM;
// .name = am335xiaevm;
MACHINE_START(AM335XIAEVM, "am335xiaevm")
/* Maintainer: Texas Instruments */
.atag_offset = 0x100,
.map_io = am335x_evm_map_io,
.init_irq = ti81xx_init_irq,
.init_early = am33xx_init_early,
.timer = &omap3_am33xx_timer,
.init_machine = am335x_evm_init,
MACHINE_END
//zz//#######################################################################
3.
machine_desc 结构体中函数做了什么
1)
其中重要的初始化函数
am335x_evm_init()
//zz// 1. evm_dev_cfg[] ;init sequence func array are called
am335x_evm_i2c_init();
//zz// 2. am335x_i2c0_boardinfo => .. => evm_dev_cfg[]
omap_register_i2c_bus(1, 100, am335x_i2c0_boardinfo,
ARRAY_SIZE(am335x_i2c0_boardinfo));
//zz// 3. am335x_baseboard_eeprom_info => .. => evm_dev_cfg[]
/* Baseboard board EEPROM */
I2C_BOARD_INFO("24c256", BASEBOARD_I2C_ADDR),
.platform_data = &am335x_baseboard_eeprom_info,
//zz// 4. am335x_evm_setup => .. => evm_dev_cfg[]
.setup = am335x_evm_setup,
.context = (void *)NULL,
//zz// 5. setup_general_purpose_evm() => .. => evm_dev_cfg[]
if (!strncmp("SKU#01", config.opt, 6))
setup_general_purpose_evm();
//zz// 6. gen_purp_evm_dev_cfg[] is evm_dev_cfg array.
_configure_device(boardid, gen_purp_evm_dev_cfg, (1L << prof_sel));
2)
am335x_evm 板子的初始化函数指针数组,这些函数会逐个被调用
这些就是内核启动时候初始化各硬件配置寄存器的函数,可以添加自己自定义的
/* General Purpose EVM */
//zz// 7. gen_purp_evm_dev_cfg[] is sequence func array[]
static struct evm_dev_cfg gen_purp_evm_dev_cfg[] = {
{am335x_rtc_init, DEV_ON_BASEBOARD, PROFILE_ALL},
{clkout2_enable, DEV_ON_BASEBOARD, PROFILE_ALL},
{enable_ecap0, DEV_ON_DGHTR_BRD, (PROFILE_0 | PROFILE_1 |
PROFILE_2 | PROFILE_7) },
{lcdc_init, DEV_ON_DGHTR_BRD, (PROFILE_0 | PROFILE_1 |
PROFILE_2 | PROFILE_7) },
{mfd_tscadc_init, DEV_ON_DGHTR_BRD, (PROFILE_0 | PROFILE_1 |
PROFILE_2 | PROFILE_7) },
{rgmii1_init, DEV_ON_BASEBOARD, PROFILE_ALL},
{rgmii2_init, DEV_ON_DGHTR_BRD, (PROFILE_1 | PROFILE_2 |
... ...
//zz//#######################################################################
4.
start_kernel() 除了完成 arch 初始化,还有其他许多东西需要配置执行
例如
time_init();
console_init();
最后会执行 文件系统的 init 程序等等操作,以后再分析
#########################
1)
arch/arm/mach-omap2/board-am335xevm.c
此文件是移植到一个板子的基础,再增加一点其他的说明
static struct mtd_partition am335x_nand_partitions[] = {
/* All the partition sizes are listed in terms of NAND block size */
{
.name = "SPL",
.offset = 0, /* Offset = 0x0 */
.size = SZ_128K,
},
...
文件系统若使用 nand flash , 则此文件 mtd_partition 类型结构指定了分区信息
必须和 u-boot 写入 nand flash 的位置一样
才可能正确启动 Linux-Kernel
#########################
2)
Nand Ecc 简单说明
am335x 使用的是 ubi 格式的镜像格式烧写文件系统 rootfs
ECC 算法主要有 汉明码 伯明翰(BCH) RS 三种
汉明码:
s3c24x0-ARM9-yaffs-512byte 小页的 nand 使用的多,只能纠正1位错误
BCH伯明翰码:
SLC(2K等较大页) MLC(页很大,4K,8K..) 现在用的多,可以纠正多位 8/12/16 位错误
算法复杂,各家都有自己的算法..
我所知道的两种 BCH 方式所需要的 ECC 码:
2K page 的 OOB 有64Bytes ,其中页开头 2 Bytes 保留用作 Block 坏块标记(虽然只有 该 Block 中Page0 用到)
512 Byte(数据) - 8 bit(t 最大纠错位数) - 13 Bytes(OOB中ECC码) => 2K的页需要 13*4 = 52 字节 ECC 码
512 Byte(数据) - 16 bit(t 最大纠错位数) - 14 Bytes(OOB中ECC码) => 2K的页需要 14*4 = 56 字节 ECC 码
ECC 有硬件和软件实现
设置为 NAND_ECC_NONE 并不是不做 ECC 校验的意思;而是内核Kernel不做,交给 yaffs2 或 ubifs代码来做
include/linux/mtd/nand.h
typedef enum {
NAND_ECC_NONE,
//zz// 内核常用项; 如此 ECC 由文件系统 yaffs2 或者 ubifs 代码中实现 ECC
// 至于是 HW 还是 SOFT 就要看文件系统镜像格式代码中怎么做了
NAND_ECC_SOFT,
//zz// ECC 校验由内核完成,内核采用 SOFT 软件C代码实现
NAND_ECC_HW,
//zz// ECC 校验由内核完成,内核采用 HW 模块实现(操作寄存器?)
NAND_ECC_HW_SYNDROME,
NAND_ECC_HW_OOB_FIRST,
NAND_ECC_SOFT_BCH,
//zz// 可以校验多位(8/12/16)错误的 ECC 校验算法,SLC大页/MLC 现在多用这种
// 但一般也是 yaffs2 或 ubifs 代码来做,不会在内核做吧?
} nand_ecc_modes_t;
0 0
- zz-am335x-LinuxKernel启动流程初始化141221c
- AM335x u-boot启动流程问题
- AM335x启动流程(BootRom->MLO->Uboot)
- AM335x启动流程(BootRom->MLO->Uboot)
- am335x嵌入式开发-bootloader启动流程
- AM335x启动流程(BootRom->MLO->Uboot)
- AM335x启动流程(BootRom->MLO->Uboot)
- AM335x启动流程(BootRom->MLO->Uboot)
- AM335x启动流程(BootRom->MLO->Uboot)
- Nginx启动初始化流程
- BeagleBone Black——AM335X——启动流程
- [UBOOT] AM335x 启动流程(u-boot-2011.09)
- AM335x启动流程(BootRom-> MLO->的Uboot)
- 【转】wpa_supplicant 初始化流程分析(zz)
- Windows CE初始化启动流程
- PackageManagerService启动及初始化流程
- PackageManagerService启动及初始化流程
- PackageManagerService启动及初始化流程
- You must restart adb and Eclipse
- Codeforces 490F Treeland Tour 树上的最长上升子序列
- Android推送通知指南
- 自定义控件(2.3):SurfaceView和SurfaceHolder
- java网络通信
- zz-am335x-LinuxKernel启动流程初始化141221c
- android 静默安装
- Android应用自动更新功能的代码实现
- 虚函数相关的知识
- 自定义控件(3):view的绘制原理
- dos 命令查找进程pid pid_find.bat
- 最简单的视频编码器:编译(libx264,libx265,libvpx)
- JNI/NDK开发指南(2)
- Android中JNI调用过程简述