首页 > 其他 > 详细

一、驱动基础

时间:2019-05-08 18:09:06      阅读:195      评论:0      收藏:0      [点我收藏+]

 


在读者看本文之前,最好已经有部分裸机程序基础(如点亮LED、arm-linux-gcc、中断等),初学者可以查看:ARM裸机加强版

本文使用的平台为TINY4412

移植等过程课查看之前的随笔:TINY4412:移植uboot、内核和挂接网络文件系统


 

Linux将存储器和外设分为3个基础大类:

1. 字符设备。

2. 块设备。

3. 网络设备。

 

对于用户而言,它们都需要使用文件系统的操作接口open()、read()、write()和close()进行访问。

对于驱动而言,我们需要完成的是操作接口函数对应的函数。

 

那么这两个的对应和调用关系是什么样的呢?

首先,接口函数会通过SWI实现从用户模式变换到管理模式。

SWI指令格式如下:

技术分享图片

cond:执行指令的条件

immed_24:24位整数,用于区分用户的不同操作,从而执行不同内核函数。

 

读者到这里可能会有一个疑问,为什么要通过SWI进入管理模式呢?

类比于Windows,有的时候我们会使用管理员身份运行程序,这样的程序就会有更高的权利。

操作系统之所以这么做,是为应用程序的运行创建良好的环境,保障每个程序都可以最大化利用硬件资源,防止非法程序破坏其它应用程序执行环境。

为达目的,操作系统会将硬件的操作权限交给内核程序来管理,用户程序不能随意使用硬件,使用硬件(对硬件寄存器进行读写)时要先向操作系统发出请求,操作系统内核帮助用户程序实现其操作,操作系统通过一组称为系统调用的(System Call)的接口呈现给用户,系统调用把应用程序的请求传给内核,调用相应的内核函数完成所需的处理,将处理结果返回给应用程序。

内核中的系统调用定义在arch/arm/kernel/calls.S

/* 0 */        CALL(sys_restart_syscall)
        CALL(sys_exit)
        CALL(sys_fork_wrapper)
        CALL(sys_read)
        CALL(sys_write)
/* 5 */        CALL(sys_open)
        CALL(sys_close)

...

/* 375 */    CALL(sys_setns)
        CALL(sys_process_vm_readv)
        CALL(sys_process_vm_writev)

其中CALL的定义如下,为代码段的偏移地址,可以看到sys_open()的偏移是5

#define CALL(x) .long x

 

那么内核是怎么知道调用哪个函数呢?

在EABI模式下,系统调用通过传入的寄存器r7的值来判断调用哪个函数。

mov r7, #num                  @ num对应系统调用的某个函数
swi 0x0                       @ 设置多少号软中断

原来的系统调用方式是这样:

swi (#num | 0x900000)         @ 0x900000是个magic值

 

这两个选择是由宏CONFIG_OABI_COMPAT(原来的调用方式)和CONFIG_AEABI(EABI)控制的

对于原来的调用方式,内核给出的处理是给它建立一个单独的system call table,叫sys_oabi_call_table,这样,兼容方式下就会有两个system call table,以原来的调用方式的系统调用会执行old_syscall_table表中的函数指针,EABI方式的系统调用会用sys_call_table中的函数指针。

总结起来就是,通过SWI指令和寄存器传入参数,以查表方式找到对应的系统调用函数。

 

下图为内核中设备驱动的层次关系:

技术分享图片

之后,如果我们想要控制LED的亮灭,由于LED属于字符驱设备驱动,因此程序就会依次通过应用程序open() -> SWI -> 系统调用sys_open() -> VFS -> 驱动程序open() -> 硬件操作

 

一、驱动基础

原文:https://www.cnblogs.com/Lioker/p/10832846.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!