资源描述
湖南科技学院二○ 一四 年 下 学期期末考试
电信、电科 专业 2011 年级 Linux平台驱动 试题
题 号
一
二
三
四
总分
统分人
得 分
阅卷人
复查人
考试类型:闭卷 试卷类型: A卷 考试时量: 120 分钟
一、选择题(每题3分,共30分)
1) 嵌入式系统,是以(B)为中心,以计算机为基础,并且软硬件可定制,适用于各种应用场合,对功能、可靠性、成本、体积、功耗有严格要求的专用计算机系统
A.Linux B.应用 C.数据处理 D.产品
2) 嵌入式系统的四大组成部分,分别是:嵌入式微处理器、外围硬件设备、( D)、用户应用程序
A.嵌入式底层驱动
B.嵌入式系统调用
C.嵌入式根文件系统
D.嵌入式操作系统
3) 目前人们所指的嵌入式微处理器一般是指( D)位
A.4bit B.8bit C.16bit D.32bit
4) Linux系统中,内核以(D)区分设备。
A.设备节点名 B:设备设备节点号 C.设备名称 D。设备号
5) 对交叉编译描述正确的是(B )
A. 在同一平台完成编译和运行
B. 在一种平台上能编译出不同平台上运行的程序
C. 使用同一交叉编译器编译出来的可执行文件是跨平台运行的
D. 动态库是跨平台的,不需要交叉编译
6) s5pv210上电首先执行的代码来自于那里 ( A)
A.iROM B.iRAM C.NAND flash D.SD卡
7) 将C源程序编译成目标文件(*.o),而不进行链接的编译选项是(D )
A.-o B.-E -o C.-S -o D.-c -o
8) 通常情况下,kmalloc函数能分配的最大内存是(C)
A.4K B.64K C.128K D.4M
9) Linux系统启动后,一般将设备文件放在以下那个目录 ( B)
A . /etc B . /dev C. /sys D. /var
10) 对于嵌入式C程序描述正确的是? (C )
A. 必须以_start作为程序入口
B. 必须以main函数作为程序入口
C. 必须设置堆栈
D. 裸机可执行程序是ELF格式的
二、填空题(本题共5小题,每空1分 共10分)
1)Linux系统驱动设备分为字符设备、块设备和网络设备三大类。
2)嵌入式BootLoader的开发建立,依赖CPU体系结构、微处理器芯片、开发板外设和内核镜像格式
3)u-boot传递给内核的参数“root=/dev/mtdblock4 rootfstype=yaffs2 init=/linuxrc console=ttySAC0”的意义是root指的是文件系统在内核中的位置、rootfstype指的是根文件系统的类型、init指的是内核启动后的第一个用户程序、console指定打印信息采用那一个串口作为控制台
三:问答题(本题共4小题,每题8分共32分)
1、 简述把一个驱动模块编译到Linux内核中基本步骤。
1)将该驱动源文件拷贝到driver的某个合适的目录下
2)修改Makefile文件
3)修改当前目录下的Kconfig文件以加入配置菜单
4)最后配置编译内核
2、导致内核并发的原因有哪些?有哪些机制能避免?
1)原因:中断,进程的抢占和多处理器。
2) 原子变量:共享资源恰巧是一个简单的整数值时使用
信号量:大部分情况都能使用,通过pv操作控制信号量。
互斥体:是对信号量的简化。
自旋锁:多用在单或多处理器抢占式内核,对于非抢占式内核退化为空操作
3、简述中断处理的两个部分,内核中实现中断底半部的机制有哪些?
1)中断顶半部:处理紧急的硬件操作(大家熟知的中断服务函数)。
中断底半部:处理不紧急的耗时操作,执行过程中中断是使能的,可被打断。
2)软中断、微线程和工作队列
4、简述bootloader的启动过程。
第一阶段完成任务:
1、禁用看门狗、初始化系统时钟
2、设置异常向量表(用到中断的情况下设置)
3、动态内存控制器初始化配置
4、初始化调试指示灯(可选)
5、初始化UART,用于开发调试(可选)
6、从NAND、NOR或SD卡中复制代码到SDRAM
7、跳转到start_armboot,进入Bootloader第二阶段
第二阶段完成任务:
1、初始化GPIO
2、初始化flash等存储设备
3、MMU初始化
4、堆初始化
5、MTD设备初始化
6、各类通信设备相关驱动初始化
7、环境变量和参数的加载及初始化
8、倒计时监听串口(进入命令模式或启动内核)
9、启动内核(拷贝内核镜像并跳转到内核入口)
四:编程题(共二小题,第一题12分,二题16分 共28分)
1、Linux系统中以模块方式组织设备驱动程序,请列举在一个模块程序中必不可少的组成部部分。
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
MODULE_LICENSE(“GPL”);
static int __init demo_init(void)
{
printk(“module init!\n”);
return 0;
}
static void __init demo_exit(void)
{
printk(“module exit\n”);
}
module_inti(demo_init);
module_exit(demo_exit);
2、 实现s5pv210的1*5键盘驱动中的file_operations.read和io口初始化。(已给出硬件连接图,部分接口信息)
file_operations成员(部分)
int (*open) (struct inode *, struct file *);
int (*release) (struct inode *, struct file *);
ssize_t (*read)(struct file *, char __user *, size_t, loff_t *);
ssize_t (*write)(struct file *, const char __user *, size_t, loff_t *);
字符设备注册
int register_chrdev( unsigned int major, const char *name,
const struct file_operations *fops);
字符设备注销
void unregister_chrdev(unsigned int major,const char *name)
从内核空间拷贝n字节数据到用户空间
copy_to_user(user_buffer, kernel_buffer, n)
从用户空间拷贝n字节数据到内核空间
copy_from_user(kernel_buffer, user_buffer, n)
static ssize_t demo_read (struct file *filp, char __user *buf, size_t count, loff_t *offp)
{
int key = -1;
unsigned long reg_val;
unsigned long len = min(count, sizeof(key)); //min是个宏,用来获取两个数中较小的值
int retval;
/*读取dat寄存器的值,反应了按键情况*/
reg_val = readl(S5PV210_GPH2_BASE);
//将dat寄存器中的值转换为逻辑键值
key = key_convert(reg_val & 0xf8);
if(copy_to_user(buf, &key, len) != 0){
retval = -EFAULT;
goto cp_err;
}
return len;
cp_err:
return retval;
}
/*@定义file_operations结构体变量*/
static struct file_operations fops = {
.owner = THIS_MODULE,
.read = demo_read,
};
/*设置按键的触发方式,通过配置行列引脚*/
static void key_ioport_setting(void __iomem *gph_base, int trigger)
{
unsigned long reg_val;
/*@配置gph3 的0、1端口为输出,且输出trigger对应高低电平
*
* 配置con寄存器,4位对应一个io端口: B0000为输入、
* B0001为输出、B0010~B1110为保留、B1111为外部中断
*
* 配置dat寄存器,1位对应一个io端口: B1 表示输入/
* 输出高电平、B0表示输入/输出低电平
*/
reg_val = readl(S5PV210_GPH3_BASE);
reg_val &= ~((0x0f<<4*0) | (0x0f<<4*1)); //清空GPH3_0,GPH3_1的控制寄存器(同时保存不需要修改的寄存器值)。
reg_val |= ((0x01<<0) | (0x01<<4) ); //讲GPH3_0,GPH3_1设置为输出
writel(reg_val, S5PV210_GPH3_BASE);
reg_val = readl(S5PV210_GPH3_BASE+0x04);
if(trigger == 0) //如果是低电平表示按键触发,行输出低电平
reg_val &= ~((0x01<<0) | (0x01<<1));
else //否则行输出高电平
reg_val |= (0x01<<0) | (0x01<<1);
writel(reg_val, S5PV210_GPH3_BASE+0x04);
/*@配置gph2的3 4 5 6 7端口为输入,且上拉或下拉使能(根据trigger),旨在
*外界没有输入时输入口获取到的电平为高电平
*
* 配置con寄存器,4位对应一个io端口: B0000为输入、
* B0001为输出、B0010~B1110为保留、B1111为外部中断
*
* 配置up寄存器,2位对应一个io端口: B00 表示禁止
* 上下拉、B01表示下拉使能、B10表示上拉使能、B11保留
*/
reg_val = readl(S5PV210_GPH2_BASE);
reg_val &= ~((0x0f<<4*3) | (0x0f<<4*4) | (0x0f<<4*5) | (0x0f<<4*6) |(0x0f<<4*7));
writel(reg_val,S5PV210_GPH2_BASE);
reg_val = readl(S5PV210_GPH2_BASE+0x08);
reg_val &= ~((0x03<<2*3) | (0x03<<2*4) | (0x03<<2*5) | (0x03<<2*6) |(0x03<<2*7));
if(trigger == 0)
reg_val |= ((0x02<<6) | (0x02<<8) | (0x02<<10) | (0x02<<12) |(0x02<<14));
else
reg_val |= ((0x01<<6) | (0x01<<8) | (0x01<<10) | (0x01<<12) |(0x01<<14));
writel(reg_val, S5PV210_GPH2_BASE+0x08);
}
6
展开阅读全文