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申請:
異なるプラットフォームのgpioポート番号は異なる、例えばs 5 pv 210プラットフォームにおいて、カーネルソースコードのarch/arm/mach-s 5 pv 210/include/machの下にgpioがある.hのヘッダファイルには、次のものがあります.
例えばポートGPJD 0_1マクロ定義に対応するS 5 PV 210_GPD0(1).
2)GPIOの初期化
3)GPIOの出力レベル設定:
4)GPIOレベルを得る
5)GPIOのリリース
以下に簡単なled駆動を行い、S 5 PV 210プラットフォームに基づく4つのLEDランプ制御を実現し、対応するGPIOポートはGPJ 2_である.0、GPJ2_0、GPJ2_0、GPJ2_0.
:
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");