am335x UART驱动
am335x UART驱动
(2014-02-13 13:03:36)
UART 驱动框架图
Application
-----------------------------------------------------------------------------
tty_io.c
-----------------------------------------------------------------------------
serial_core.c
-----------------------------------------------------------------------------
omap_serial.c
-----------------------------------------------------------------------------
mux33xx.c
-----------------------------------------------------------------------------
board-am335xevm.c
Linux包含三种终端设备:
1.串口终端(/dev/ttySn)
linux把每个串口都看成是字符设备,通过设备节点就可以传输数据
2.伪终端(/dev/pty)
成对出现的逻辑终端设备。Ptyp2 ttyp2
3.控制台(/dev/ttyn /dev/console)
tty0是当前所使用的虚拟终端的一个别名。
Linux终端设备驱动结构
tty核心(tty_io.c 定义了file_operations实现了接口函数
tty_register_driver用于注册tty设备)
----------
tty线路规划 (n_tty.c)
----------
tty驱动
----------
硬件
//分配tty驱动
struct tty_driver *alloc_tty_driver(int lines);
返回tty_driver指针,参数为要分配的设备数量
//注册tty驱动
int tty_register_driver(struct tty_driver *driver);
注册tty驱动成功时返回0,参数为alloc_tty_driver()分配的tty_driver结构体指针。
//注销tty驱动
int tty_unregister_driver(struct tty_driver *driver);
//注册tty设备
struct device *tty_register_device(struct tty_driver *driver,unsigned index,
strcut device *device);
仅有tty_driver是不够的,驱动必须依附于设备,用于注册关联于tty_driver的设备,index为
设备的索引(范围0~driver->num)
Linux终端设备驱动初始化和释放
static int __init xxx_init(void)
{
//分配tty_driver结构体
xxx_tty_driver = alloc_tty_driver(xxx_prots);
//初始化tty_driver结构体
xxx_tty_driver->xxx = …...
ret = tty_register_driver(xxx_tty_driver);
//硬件资源申请
ret = request_irq();
}
UART设备驱动
linux在文件serial_core.c中实现了UART设备的通用tty驱动层。接口是一组uart_xxx而不是tty_xxx了。
uart_driver,uart驱动结构,它封装了tty_driver.
//uart驱动的注册/注销为
int uart_register_driver(struct uart_driver *uart);
void uart_unregister_driver(strcut uart_driver *uart);
uart_port用于描述一个UART端口(直接对应一个串口)的I/O端口或者I/O内存地址 FIFO大小 端口类型
在模块初始化时调用 uart_register_driver()和uart_add_one_port()以注册UART驱动并添加端口,在卸载模块时,相反。
系统通过调用设备文件的主设备号找到相应的设备驱动程序,然后读取这个数据结构的相应函数指针。
am335x模块启动流程
在/init/main.c中start_kernel()函数调用
-->rest_init() 它会创建一个内核线程kernel_thread(kernel_init,...)和一个管理内核的线程kthreadd
-->kernel_thread(kernel_init,...) 会调用它的处理函数kernel_init()
-->kernel_init_freeable()
-->do_basic_setup()
-->do_initcalls()
-->do_inicall_level()
它来调用.initcalln.init段中的代码。
这些段定义在中
arch_initcall位于.initcall3.init段中。
arch_initcall加载了定位设备程序customize_machine在中定义了一个结构体
strcut machine_desc{
void (*init_early)(void);
void (*init_irq)(void);
void (*init_time)(void);
void (*init_machine)(void);//会初始化机器的地址
void (*init_late)(void);
};
struct machine_desc描述了目标板对内核初始阶段资源分配至关重要的一些参数,
有一个宏
最后会调用具体的设备 如:.init_machine = am335x_evm_init.
MACHINE_START(AM335XEVM,"am335xevm");
.init_machine = am335x_evm_init
分享: