第一章 Android系统移植与驱动开发概述
一、Android系统架构
1)应用程序层
Android平台不仅仅是操作系统,也包含了许多应用程序,诸如SMS短信客户端程序、电话拨号程序、图片浏览器、Web浏览器等应用程序。这些应用程序都是 用Java语言编写的,并且这些应用程序都是可以被开发人员开发的其他应用程序所替换,这点不同于其他手机操作系统固化在系统内部的系统软件,更加灵活和个性化。
2)应用程序框架层
应用程序框架层是我们从事Android开发的基础,很多核心应用程序也是通过这一层来实现其核心功能的,该层简化了组件的重用,开发人员可以直接使用其提 供的组件来进行快速的应用程序开发,也可以通过继承而实现个性化的拓展。
3)系统运行库层
从图中可以看出,系统运行库层可以分成两部分,分别是系统库和Android运行时。
4)Linux内核层
Android是基于Linux2.6内核,其核心系统服务如安全性、内存管理、进程管理、网路协议以及驱动模型都依赖于Linux内核。
二、Android版本与Linux内核的关系
关于Android对应Linux内核版本,大家可以到自己手机中的设置---关于手机查看
查Linux 系统的内核版本方法:
①uname -a
1 uname -a
②cat /proc/version
1 cat /proc/version
注:/proc 不是普通的文件系统,而是系统内核的映像,也就是说,该目录中的文件是存放在系统内存之中的,它以文件系统的方式为访问系统内核数据的操作提供接
口。而uname 命令就是从/proc/version 文件中获取信息的,当然直接查看/proc/version文件的内容(方法2 )也可以获取同样的信息. uname 命令加上参数“-a” 可以获取更多的信息,否则只显示当前的系统名,也就是只会输出“Linux”.
三、Linux设备驱动
设备的分类:
字符设备
块设备
网络设备
例子(s3c6410小灯):
1 #include <linux/fs.h> 2 #include <linux/cdev.h> 3 #include <linux/pci.h> 4 #include <asm/uaccess.h> 5 #include <mach/map.h> 6 #include <mach/regs-gpio.h> 7 #include <mach/gpio-bank-m.h> 8 9 #define DEVICE_NAME "s3c6410_leds" 10 #define DEVICE_COUNT 1 // 设备数量 11 #define S3C6410_LEDS_MAJOR 0 12 #define S3C6410_LEDS_MINOR 234 13 #define PARAM_SIZE 3 14 static unsigned char mem[4]; // 保存4个Leds的设置状态 15 static int major = S3C6410_LEDS_MAJOR; 16 static int minor = S3C6410_LEDS_MINOR; 17 static dev_t dev_number; // 设备号 18 static int leds_state = 1; 19 static char *params[] = {"string1", "string2","string3"}; 20 static int param_size = PARAM_SIZE; 21 22 static struct class *leds_class = NULL; 23 24 static long s3c6410_leds_ioctl(struct file *filp, unsigned int cmd, 25 unsigned long arg) 26 { 27 28 switch (cmd) 29 { 30 unsigned tmp; 31 32 case 0: 33 case 1: 34 if (arg > 4) 35 { 36 return -EINVAL; 37 } 38 tmp = ioread32(S3C64XX_GPMDAT); 39 40 if (cmd == 1) 41 { 42 tmp &= (~(1 << arg)); 43 } 44 else 45 { 46 tmp |= (1 << arg); 47 } 48 49 iowrite32(tmp, S3C64XX_GPMDAT); 50 51 return 0; 52 default: 53 return -EINVAL; 54 } 55 } 56 static ssize_t s3c6410_leds_write(struct file *file, const char __user *buf, 57 size_t count, loff_t *ppos) 58 { 59 60 unsigned tmp = count; 61 unsigned long i = 0; 62 memset(mem, 0, 4); 63 64 if (count > 4) 65 { 66 tmp = 4; 67 } 68 69 if (copy_from_user(mem, buf, tmp)) 70 { 71 return -EFAULT; 72 } 73 else 74 { 75 for (i = 0; i < 4; i++) 76 { 77 tmp = ioread32(S3C64XX_GPMDAT); 78 if (mem[i] == '1') 79 { 80 tmp &= (~(1 << i)); 81 } 82 else 83 { 84 tmp |= (1 << i); 85 } 86 87 iowrite32(tmp, S3C64XX_GPMDAT); 88 89 } 90 return count; 91 } 92 93 94 } 95 96 static struct file_operations dev_fops = 97 { .owner = THIS_MODULE, .unlocked_ioctl = s3c6410_leds_ioctl, .write = 98 s3c6410_leds_write }; 99 static struct cdev leds_cdev; 100 101 //创建设备文件(/dev/s3c6410_leds) 102 static int leds_create_device(void) 103 { 104 int ret = 0; 105 int err = 0; 106 107 // 初始化cdev的成员,并建立cdev和file_operations之间的连接 108 cdev_init(&leds_cdev, &dev_fops); 109 leds_cdev.owner = THIS_MODULE; 110 if (major > 0) 111 { 112 // 获取设备号(主设备号和次设备号) 113 dev_number = MKDEV(major, minor); 114 err = register_chrdev_region(dev_number, DEVICE_COUNT, DEVICE_NAME); 115 if (err < 0) 116 { 117 printk(KERN_WARNING "register_chrdev_region() failed\n"); 118 return err; 119 } 120 } 121 else 122 { 123 err = alloc_chrdev_region(&leds_cdev.dev, 10, DEVICE_COUNT, 124 DEVICE_NAME); 125 if (err < 0) 126 { 127 printk(KERN_WARNING "alloc_chrdev_region() failed\n"); 128 return err; 129 } 130 131 major = MAJOR(leds_cdev.dev); 132 minor = MINOR(leds_cdev.dev); 133 //dev_number = MKDEV(major, minor); 134 dev_number = leds_cdev.dev; 135 136 } 137 ret = cdev_add(&leds_cdev, dev_number, DEVICE_COUNT); 138 leds_class = class_create(THIS_MODULE, DEVICE_NAME); 139 device_create(leds_class, NULL, dev_number, NULL, DEVICE_NAME); 140 141 return ret; 142 } 143 144 static void leds_init_gpm(int leds_default) 145 { 146 int tmp = 0; 147 // 初始化端口配置寄存器 148 tmp = ioread32(S3C64XX_GPMCON); 149 tmp &= (~0xFFFF); 150 tmp |= 0x1111; // 0001000100010001 151 iowrite32(tmp, S3C64XX_GPMCON); 152 153 // 初始化端口上拉电路寄存器 154 tmp = ioread32(S3C64XX_GPMPUD); 155 tmp &= (~0xFF); 156 tmp |= 0xAA; // 01010101 157 iowrite32(tmp, S3C64XX_GPMPUD); 158 159 // 初始化端口数据寄存器 160 tmp = ioread32(S3C64XX_GPMDAT); 161 tmp &= (~0xF); 162 tmp |= leds_default; 163 iowrite32(tmp, S3C64XX_GPMDAT); 164 } 165 166 // 初始化LED驱动 167 static int leds_init(void) 168 { 169 int ret; 170 ret = leds_create_device(); 171 leds_init_gpm(~leds_state); 172 printk(DEVICE_NAME"\tinitialized\n"); 173 174 printk("param0\t%s\n", params[0]); 175 printk("param1\t%s\n", params[1]); 176 printk("param2\t%s\n", params[2]); 177 178 return ret; 179 } 180 static void leds_destroy_device(void) 181 { 182 device_destroy(leds_class, dev_number); 183 184 if (leds_class) 185 class_destroy(leds_class); 186 unregister_chrdev_region(dev_number, DEVICE_COUNT); 187 188 return; 189 190 } 191 static void leds_exit(void) 192 { 193 leds_destroy_device(); 194 printk(DEVICE_NAME"\texit!\n"); 195 } 196 197 module_init(leds_init); 198 module_exit(leds_exit); 199 module_param(leds_state, int, S_IRUGO|S_IWUSR); 200 module_param_array(params, charp, ¶m_size, S_IRUGO|S_IWUSR); 201 MODULE_LICENSE("GPL"); 202 MODULE_AUTHOR("Lining");
总结一下学习Linux 驱动要做些什么:
1.准备一个自己熟悉的Linux 操作系统,用于开发和测试Linux 驱动,建议使用Ubuntu Linux14.04 及以上版本。
2.准备一块开发板(建议采用基于ARM11的开发板〉。
3.学习GNUC。
4.学习相关的硬件知识。
5.不断地实践。