linuxカーネルにおけるGPIOの使用(二)--標準インタフェース関数

7043 ワード

linuxカーネルでは、GPIO、interrupt、clockなどの標準的なインタフェース関数を使用して操作できる基本モジュールがあります.標準的なインタフェース関数とは、ハードウェアプラットフォームに関係なく、linuxの下で駆動する一般的な関数を指し、よく使われています:gpio_request();gpio_free();gpio_direction_output();gpio_direction_input();gpio_set_value();gpio_get_value()など;

1)GPIO申請:
        int gpio_request(unsigned gpio, const char *label)
    :
    unsigned gpio:gpio   ;
    const char *label:  gpio      ;
   :
        0;          ;

異なるプラットフォームのgpioポート番号は異なる、例えばs 5 pv 210プラットフォームにおいて、カーネルソースコードのarch/arm/mach-s 5 pv 210/include/machの下にgpioがある.hのヘッダファイルには、次のものがあります.
/* S5PV210 GPIO number definitions */
#define S5PV210_GPA0(_nr)       (S5PV210_GPIO_A0_START + (_nr))
#define S5PV210_GPA1(_nr)       (S5PV210_GPIO_A1_START + (_nr))
#define S5PV210_GPB(_nr)        (S5PV210_GPIO_B_START + (_nr))
#define S5PV210_GPC0(_nr)       (S5PV210_GPIO_C0_START + (_nr))
#define S5PV210_GPC1(_nr)       (S5PV210_GPIO_C1_START + (_nr))
#define S5PV210_GPD0(_nr)       (S5PV210_GPIO_D0_START + (_nr))
#define S5PV210_GPD1(_nr)       (S5PV210_GPIO_D1_START + (_nr))
…..

例えばポートGPJD 0_1マクロ定義に対応するS 5 PV 210_GPD0(1).
2)GPIOの初期化
              ,       :
        int gpio_direction_output(unsigned gpio, int value);
              :
        int gpio_direction_input(unsigned gpio);

3)GPIOの出力レベル設定:
        void gpio_set_value(unsigned gpio, int value);

4)GPIOレベルを得る
        int gpio_get_value(unsigned gpio);

5)GPIOのリリース
        void gpio_free(unsigned gpio);

以下に簡単なled駆動を行い、S 5 PV 210プラットフォームに基づく4つのLEDランプ制御を実現し、対応するGPIOポートはGPJ 2_である.0、GPJ2_0、GPJ2_0、GPJ2_0.
static int __init leddev_init(void)
{   
    int ret;
/*************led gpio request and initial**************/
    int i;
    for( i = 0; i < 4; i++)
    {
        ret = gpio_request(S5PV210_GPJ2(i), "led_gpio");
        if(ret < 0)
        {
            printk("S5PV210_GPJ2(%d)_request error!
"
, i); goto err_gpio_request; } gpio_direction_output(S5PV210_GPJ2(i), 1); } printk("led initial success!
"
); if(cdev_Major) // 0, { cdev_num = MKDEV(cdev_Major, cdev_Minor); ret= register_chrdev_region(cdev_num, 1, cdev_name); } else { ret = alloc_chrdev_region(&cdev_num, cdev_Minor, 1, cdev_name); // cdev_Major = MAJOR(cdev_num); } if(ret < 0) { printk(KERN_WARNING"can not get major %d
"
, cdev_Major); goto err_leddev_region; } cdev_init(&leddev, &leddev_fops);// gpiodev.owner = THIS_MODULE; ret = cdev_add(&leddev, cdev_num, 1); if(ret) { printk("error while register device!
"
); goto err_gpiodev_add; } /******************auto create device file****************/ class_ret = class_create(THIS_MODULE, "ledclass"); if(class_ret == NULL) { printk("class_create error!
"
); goto err_class_creat; } device_ret = device_create(class_ret, NULL, cdev_num, NULL, "leddev"); if(device_ret == NULL) { printk("device_create error!
"
); goto err_device_create; } return 0; err_device_create: class_destroy(class_ret); err_class_creat: err_leddev_add: unregister_chrdev_region(MKDEV(cdev_Major, cdev_Minor), 1); err_leddev_region: err_gpio_request: for( ; i > 0; i--) { gpio_free(S5PV210_GPJ2(i - 1)); } return ret; } static void __exit leddev_exit(void) { int i; printk("exit from leddev!
"
); for(i = 0 ; i < 4; i++) { gpio_free(S5PV210_GPJ2(i)); } class_destroy(class_ret); device_destroy(class_ret, cdev_num); unregister_chrdev_region(MKDEV(cdev_Major, cdev_Minor), 1); cdev_del(&leddev); } module_init(leddev_init); module_exit(leddev_exit); MODULE_AUTHOR("Mr.Huang"); MODULE_DESCRIPTION("This is a leddev for testing!"); MODULE_LICENSE("GPL");