ImageVerifierCode 换一换
格式:DOCX , 页数:13 ,大小:19.07KB ,
资源ID:4718613      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/4718613.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(Linux串口终端初始化.docx)为本站会员(b****6)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

Linux串口终端初始化.docx

1、Linux串口终端初始化1. 串口初始化过程 start_kernel() |- . |- setup_arch() |- . |- build_all_zonelists() |- page_alloc_init() |- . |- trap_init() |- . |- console_init() |- . |- mem_init() |- . - rest_init() - kernel_thread() - init() -do_basic_setup()1.1 console_init()drivers/char/tty_io.c/* 只作基本的初始化,详细的初始化在后面做 */v

2、oid _init console_init(void) initcall_t *call; /* Setup the default TTY line discipline. */ (void) tty_register_ldisc(N_TTY, &tty_ldisc_N_TTY); /* * set up the console device so that later boot sequences can * inform about problems etc. */#ifdef CONFIG_EARLY_PRINTK disable_early_printk();#endif call

3、 = _con_initcall_start; while (call _con_initcall_end) (*call)(); call+; 然后执行依次执行 .con_initcall.init 节中的函数,该节的每项为一个函数指针,使用宏 console_initcall(FUNC_NAME) 将函数指针填入,该宏定义于 include/linux/init.h:#define console_initcall(fn) static initcall_t _initcall_#fn _attribute_used_ _attribute_(_section_(.con_initcall

4、.init)=fninitcall_t 为一函数指针: typedef int (*initcall_t)(void);如: console_initcall(serial8250_console_init) 则展开为:static initcall_t _initcall_serial8250_console_init = _attribute_used_ _attribute_(_section_(.con_initcall.init) = serial8250_console_init;即定义一个函数指针,使其指向 serial8250_console_init,并使用gcc的 _att

5、ribute_ 扩展,将其链接入.con_initcall.init 节,方便管理。一个典型的 .con_initcall.init 节的内容为:.Disassembly of section .con_initcall.init:80234f90 :80234f90: 802328e4 lb v1,10468(at) # 这是一个函数指针,指向serial8250_console_init80234f94 : 80234f94: 80232ce4 lb v1,11492(at).因此 console_init() 所做的,就是: console_init() |- tty_register_

6、ldisc() /* Install a line discipline, drivers/char/tty_io.c */ |- serial8250_console_init() - early_uart_console_init()1.1.1 serial8250_console_initserial8250_console_init() 定义于 drivers/serial/8250.cstatic int _init serial8250_console_init(void) serial8250_isa_init_ports(); register_console(&serial8

7、250_console); return 0;console_initcall(serial8250_console_init);static struct uart_8250_port serial8250_portsUART_NR;static void _init serial8250_isa_init_ports(void) struct uart_8250_port *up; static int first = 1; int i; if (!first) return; first = 0; for (i = 0; i port.line = i; spin_lock_init(&

8、up-port.lock); init_timer(&up-timer); up-timer.function = serial8250_timeout; /* * ALPHA_KLUDGE_MCR needs to be killed. */ up-mcr_mask = ALPHA_KLUDGE_MCR; up-mcr_force = ALPHA_KLUDGE_MCR; up-port.ops = &serial8250_pops; for (i = 0, up = serial8250_ports; i ARRAY_SIZE(old_serial_port) & i port.iobase

9、 = old_serial_porti.port; up-port.irq = irq_canonicalize(old_serial_porti.irq); up-port.uartclk = old_serial_porti.baud_base * 16; up-port.flags = old_serial_porti.flags; up-port.hub6 = old_serial_porti.hub6; up-port.membase = old_serial_porti.iomem_base; up-port.iotype = old_serial_porti.io_type; u

10、p-port.regshift = old_serial_porti.iomem_reg_shift; if (share_irqs) up-port.flags |= UPF_SHARE_IRQ; serial8250_isa_init_ports() 所做的事即使用 old_serial_port 来初始化 struct uart_8250_port 结构数组 serial8250_ports. 这个 old_serial_port 定义为:static const struct old_serial_port old_serial_port = SERIAL_PORT_DFNS /* d

11、efined in asm/serial.h */;include/asm-mips/serial.h#define SERIAL_PORT_DFNS DDB5477_SERIAL_PORT_DEFNS EV64120_SERIAL_PORT_DEFNS IP32_SERIAL_PORT_DEFNS JAZZ_SERIAL_PORT_DEFNS STD_SERIAL_PORT_DEFNS MOMENCO_OCELOT_G_SERIAL_PORT_DEFNS MOMENCO_OCELOT_C_SERIAL_PORT_DEFNS MOMENCO_OCELOT_SERIAL_PORT_DEFNS M

12、OMENCO_OCELOT_3_SERIAL_PORT_DEFNS BCM947XX_SERIAL_PORT_DEFNS BCM56218_SERIAL_PORT_DEFNS这个根据具体的平台配置,使用相应的宏定义. 如当 CONFIG_HAVE_STD_PC_SERIAL_PORT 时:#ifdef CONFIG_HAVE_STD_PC_SERIAL_PORT#define STD_SERIAL_PORT_DEFNS /* UART CLK PORT IRQ FLAGS */ 0, BASE_BAUD, 0x3F8, 4, STD_COM_FLAGS , /* ttyS0 */ 0, BAS

13、E_BAUD, 0x2F8, 3, STD_COM_FLAGS , /* ttyS1 */ 0, BASE_BAUD, 0x3E8, 4, STD_COM_FLAGS , /* ttyS2 */ 0, BASE_BAUD, 0x2E8, 3, STD_COM4_FLAGS , /* ttyS3 */#else /* CONFIG_HAVE_STD_PC_SERIAL_PORTS */#define STD_SERIAL_PORT_DEFNS#endif /* CONFIG_HAVE_STD_PC_SERIAL_PORTS */否则为空宏serial8250_isa_init_ports() 后

14、, serial8250_console_init() 调用 register_console(&serial8250_console) 注册一个struct console 结构:static struct uart_driver serial8250_reg;static struct console serial8250_console = .name = ttyS, .write = serial8250_console_write, .device = uart_console_device, .setup = serial8250_console_setup, .flags = C

15、ON_PRINTBUFFER, .index = -1, .data = &serial8250_reg,;其用来描述一个 serial8250 的 console.这个register_console() 定义于 kernel/printk.c1.1.2 early_uart_console_init()drivers/serial/8250_early.cstatic struct console early_uart_console _initdata = .name = uart, .write = early_uart_write, .setup = early_uart_setup

16、, .flags = CON_PRINTBUFFER, .index = -1,;static int _init early_uart_console_init(void) if (!early_uart_registered) register_console(&early_uart_console); early_uart_registered = 1; return 0;console_initcall(early_uart_console_init);和 serial8250_console_init() 类似,也是注册一个 console 结构,表示一个 uart console1

17、.2 rest_init() rest_init() |- . |- smp_prepare_cpus(max_cpus) |- do_pre_smp_initcalls() |- smp_init() |- sched_init_smp() |- cpuset_init_smp() |- do_basic_setup() |- . - init_post()1.2.1 do_basic_setup()到 do_basic_setup() 时,与体系结构相关的部分已经初始化完了,现在开始初始化设备了:init/main.cstatic void _init do_basic_setup(voi

18、d) /* drivers will send hotplug events */ init_workqueues(); usermodehelper_init(); driver_init(); /* initialize driver model */ init_irq_proc(); do_initcalls(); /* 顺序执行 .initcall.init 节中的所有函数 */1.2.1 driver_init()driver_init() 定义于 drivers/base/init.c 主要完成 driver subsystem 的初始化:void _init driver_ini

19、t(void) /* These are the core pieces */ devices_init(); buses_init(); classes_init(); firmware_init(); hypervisor_init(); /* These are also core pieces, but must come after the * core core pieces. */ platform_bus_init(); system_bus_init(); cpu_dev_init(); memory_dev_init(); attribute_container_init(

20、);这些函数主要调用 subsystem_register() 注册一个struct subsystem 结构,进入kobjects.1.2.2 do_initcall()这个于上面 console_init() 类似,其是顺序执行 .initcall.init 节中的所有函数:init/main.cextern initcall_t _initcall_start, _initcall_end;static void _init do_initcalls(void) initcall_t *call; int count = preempt_count(); for (call = _ini

21、tcall_start; call _initcall_end; call+) char *msg = NULL; char msgbuf40; int result; if (initcall_debug) printk(Calling initcall 0x%p, *call); print_fn_descriptor_symbol(: %s(), (unsigned long) *call); printk(n); result = (*call)(); if (result & result != -ENODEV & initcall_debug) sprintf(msgbuf, er

22、ror code %d, result); msg = msgbuf; if (preempt_count() != count) msg = preemption imbalance; preempt_count() = count; if (irqs_disabled() msg = disabled interrupts; local_irq_enable(); if (msg) printk(KERN_WARNING initcall at 0x%p, *call); print_fn_descriptor_symbol(: %s(), (unsigned long) *call);

23、printk(: returned with %sn, msg); /* Make sure there is no pending stuff from the initcall sequence */ flush_scheduled_work();关于符号地址 _initcall_start, _initcall_end 的来源,则是由编译系统写在 arch/mips/kernel/vmlinux.lds中:._initcall_start = .;.initcall.init : *(.initcall0.init) *(.initcall0s.init) *(.initcall1.in

24、it) *(.initcall1s.init) *(.initcall2.init) *(.initcall2s.init) *(.initcall3.init) *(.initcall3s.init) *(.initcall4.init) *(.initcall4s.init) *(.initcall5.init) *(.initcall5s.init) *(.initcallrootfs.init) *(.initcall6.init) *(.initcall6s.init) *(.initcall7.init) *(.initcall7s.init)_initcall_end = .;.

25、链接时,会被替换为实际的地址矣.写入 .initcall.init 节的函数指针,有一组辅助的宏定义于include/linux/init.h:#define pure_initcall(fn) _define_initcall(0,fn,1)#define core_initcall(fn) _define_initcall(1,fn,1)#define core_initcall_sync(fn) _define_initcall(1s,fn,1s)#define postcore_initcall(fn) _define_initcall(2,fn,2)#define postcore_initcall_sync(fn) _define_initcall(2s,fn,2s)#define arch_initcall(fn) _define_init

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1