歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

Android系統移植與驅動開發概述

一、Android系統架構

1)應用程序層

        Android平台不僅僅是操作系統,也包含了許多應用程序,諸如SMS短信客戶端程序、電話撥號程序、圖片浏覽器、Web浏覽器等應用程序。這些應用程序都是  用Java語言編寫的,並且這些應用程序都是可以被開發人員開發的其他應用程序所替換,這點不同於其他手機操作系統固化在系統內部的系統軟件,更加靈活和個性化。

2)應用程序框架層

        應用程序框架層是我們從事Android開發的基礎,很多核心應用程序也是通過這一層來實現其核心功能的,該層簡化了組件的重用,開發人員可以直接使用其提    供的組件來進行快速的應用程序開發,也可以通過繼承而實現個性化的拓展。

3)系統運行庫層         

   從圖中可以看出,系統運行庫層可以分成兩部分,分別是系統庫和Android運行時。

4)Linux內核層

        Android是基於Linux2.6內核,其核心系統服務如安全性、內存管理、進程管理、網路協議以及驅動模型都依賴於Linux內核。

二、Android版本與Linux內核的關系

關於Android對應Linux內核版本,大家可以到自己手機中的設置---關於手機查看

查Linux 系統的內核版本方法:

①uname -a     

 uname -a

②cat /proc/version

cat /proc/version

 

注:/proc 不是普通的文件系統,而是系統內核的映像,也就是說,該目錄中的文件是存放在系統內存之中的,它以文件系統的方式為訪問系統內核數據的操作提供接
口。而uname 命令就是從/proc/version 文件中獲取信息的,當然直接查看/proc/version文件的內容(方法2 )也可以獲取同樣的信息. uname 命令加上參數“-a” 可以獲取更多的信息,否則只顯示當前的系統名,也就是只會輸出“Linux”.

三、Linux設備驅動

設備的分類:

字符設備

塊設備

網絡設備

例子(s3c6410小燈):

#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/pci.h>
#include <asm/uaccess.h>
#include <mach/map.h>
#include <mach/regs-gpio.h>
#include <mach/gpio-bank-m.h>

#define DEVICE_NAME "s3c6410_leds"
#define DEVICE_COUNT 1              //  設備數量
#define S3C6410_LEDS_MAJOR 0 
#define S3C6410_LEDS_MINOR 234
#define PARAM_SIZE  3
static unsigned char mem[4]; // 保存4個Leds的設置狀態
static int major = S3C6410_LEDS_MAJOR;
static int minor = S3C6410_LEDS_MINOR;
static dev_t dev_number; //  設備號
static int leds_state = 1;
static char *params[] = {"string1", "string2","string3"};
static int param_size = PARAM_SIZE;

static struct class *leds_class = NULL;

static long s3c6410_leds_ioctl(struct file *filp, unsigned int cmd,
        unsigned long arg)
{

    switch (cmd)
    {
        unsigned tmp;

        case 0:
        case 1:
        if (arg > 4)
        {
            return -EINVAL;
        }
        tmp = ioread32(S3C64XX_GPMDAT);

        if (cmd == 1)
        {
            tmp &= (~(1 << arg));
        }
        else
        {
            tmp |= (1 << arg);
        }

        iowrite32(tmp, S3C64XX_GPMDAT);

        return 0;
        default:
        return -EINVAL;
    }
}
static ssize_t s3c6410_leds_write(struct file *file, const char __user *buf,
        size_t count, loff_t *ppos)
{

    unsigned tmp = count;
    unsigned long i = 0;
    memset(mem, 0, 4);

    if (count > 4)
    {
        tmp = 4;
    }

    if (copy_from_user(mem, buf, tmp))
    {
        return -EFAULT;
    }
    else
    {
        for (i = 0; i < 4; i++)
        {
            tmp = ioread32(S3C64XX_GPMDAT);
            if (mem[i] == '1')
            {
                tmp &= (~(1 << i));
            }
            else
            {
                tmp |= (1 << i);
            }

            iowrite32(tmp, S3C64XX_GPMDAT);

        }
        return count;
    }


}

static struct file_operations dev_fops =
{ .owner = THIS_MODULE, .unlocked_ioctl = s3c6410_leds_ioctl, .write =
        s3c6410_leds_write };
static struct cdev leds_cdev;

//創建設備文件(/dev/s3c6410_leds)
static int leds_create_device(void)
{
    int ret = 0;
    int err = 0;

    //  初始化cdev的成員,並建立cdev和file_operations之間的連接
    cdev_init(&leds_cdev, &dev_fops);
    leds_cdev.owner = THIS_MODULE;
    if (major > 0)
    {
        //  獲取設備號(主設備號和次設備號)
        dev_number = MKDEV(major, minor);
        err = register_chrdev_region(dev_number, DEVICE_COUNT, DEVICE_NAME);
        if (err < 0)
        {
            printk(KERN_WARNING "register_chrdev_region() failed\n");
            return err;
        }
    }
    else
    {
        err = alloc_chrdev_region(&leds_cdev.dev, 10, DEVICE_COUNT,
                DEVICE_NAME);
        if (err < 0)
        {
            printk(KERN_WARNING "alloc_chrdev_region() failed\n");
            return err;
        }

        major = MAJOR(leds_cdev.dev);
        minor = MINOR(leds_cdev.dev);
        //dev_number = MKDEV(major, minor);
        dev_number = leds_cdev.dev;

    }
    ret = cdev_add(&leds_cdev, dev_number, DEVICE_COUNT);
    leds_class = class_create(THIS_MODULE, DEVICE_NAME);
    device_create(leds_class, NULL, dev_number, NULL, DEVICE_NAME);

    return ret;
}

static void leds_init_gpm(int leds_default)
{
    int tmp = 0;
    //  初始化端口配置寄存器
    tmp = ioread32(S3C64XX_GPMCON);
    tmp &= (~0xFFFF);
    tmp |= 0x1111; // 0001000100010001
    iowrite32(tmp, S3C64XX_GPMCON);

    //  初始化端口上拉電路寄存器
    tmp = ioread32(S3C64XX_GPMPUD);
    tmp &= (~0xFF);
    tmp |= 0xAA; // 01010101
    iowrite32(tmp, S3C64XX_GPMPUD);

    //  初始化端口數據寄存器
    tmp = ioread32(S3C64XX_GPMDAT);
    tmp &= (~0xF);
    tmp |= leds_default;
    iowrite32(tmp, S3C64XX_GPMDAT);
}

//  初始化LED驅動
static int leds_init(void)
{
    int ret;
    ret = leds_create_device();
    leds_init_gpm(~leds_state);
    printk(DEVICE_NAME"\tinitialized\n");

    printk("param0\t%s\n", params[0]);
    printk("param1\t%s\n", params[1]);
    printk("param2\t%s\n", params[2]);

    return ret;
}
static void leds_destroy_device(void)
{
    device_destroy(leds_class, dev_number);

    if (leds_class)
        class_destroy(leds_class);
    unregister_chrdev_region(dev_number, DEVICE_COUNT);

    return;

}
static void leds_exit(void)
{
    leds_destroy_device();
    printk(DEVICE_NAME"\texit!\n");
}

module_init(leds_init);
module_exit(leds_exit);
module_param(leds_state, int, S_IRUGO|S_IWUSR);
module_param_array(params, charp, &param_size, S_IRUGO|S_IWUSR);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Lining");

總結一下學習Linux 驅動要做些什麼:

1.准備一個自己熟悉的Linux 操作系統,用於開發和測試Linux 驅動,建議使用Ubuntu Linux14.04 及以上版本。

2.准備一塊開發板(建議采用基於ARM11的開發板〉。

3.學習GNUC。

4.學習相關的硬件知識。

5.不斷地實踐。

更多Ubuntu相關信息見Ubuntu 專題頁面 http://www.linuxidc.com/topicnews.aspx?tid=2

更多Android相關信息見Android 專題頁面 http://www.linuxidc.com/topicnews.aspx?tid=11

Copyright © Linux教程網 All Rights Reserved