nanopi s2 驅動開發心得(二) s5p4418的GPIO函式
阿新 • • 發佈:2019-01-01
硬體環境
開發板:nanopi2 (cpu:A9 s5p4418 )
軟體環境
核心版本: linux3.4.39
交叉編譯器:arm-linux-gcc version 4.9.3 (ctng-1.21.0-229g-FA) 64位系統版本
Linux3.4核心GPIO驅動說明
Kernel 2.6.32版本以上提供了gpio口管理的庫檔案/kernel/drivers/gpio/gpiolib.c。
相關的介面:
1.int gpio_request(unsigned gpio, const char *label)
申請一個pin腳作為gpio口,命名為 * label,如果經過判斷空閒的 申請成功了做一些初始的bit位設定。
2. void gpio_free(unsigned gpio)
釋放這個gpio口
3.int gpio_direction_input(unsigned gpio)
設定gpio口為輸入模式
4.int gpio_direction_output(unsigned gpio, int value)
設定gpio口為輸出模式 value為初始值 0為高電平/1為低電平
5.void gpio_set_value(unsigned gpio, int value)
設定gpio口的值
6.int gpio_get_value(unsigned gpio)
獲取gpio口的值
底層晶片具體實現
在drivers/gpio下實現了通用的基於gpiolib的GPIO驅動,其中定義了一個通用的用於描述底層GPIO控制器的gpio_chip結構體,並要求具體的SoC實現gpio_chip結構體的成員函式,最後透過gpiochip_add()註冊gpio_chip
驅動程式原始碼
#include <linux/module.h> #include <linux/gpio.h> #include <linux/delay.h> #include <linux/kernel.h> #include <linux/moduleparam.h> #include <linux/init.h> #include <linux/hrtimer.h> #include <linux/ktime.h> #include <linux/device.h> #include <linux/kdev_t.h> #include <linux/interrupt.h> #include <linux/sched.h> #include <linux/miscdevice.h> #include <mach/platform.h> #include <mach/devices.h> #define DEVICE_NAME "4418_relay" //nanopi2 4418 unsigned int J1_GPIO = PAD_GPIO_C + 11;//模組GPIO腳 unsigned int J2_GPIO = PAD_GPIO_C + 12;//模組GPIO腳 #define J1_OFF 0x00 #define J1_ON 0x01 #define J2_OFF 0x10 #define J2_ON 0x11 char drv_buf[2]; static int update_relay(void) { switch(drv_buf[0]) { case J1_ON: gpio_set_value(J1_GPIO, 0); //輸出低電平 return 0; case J1_OFF: gpio_set_value(J1_GPIO, 1); //輸出高電平 return 0; case J2_ON: gpio_set_value(J2_GPIO, 0); //輸出低電平 return 0; case J2_OFF: gpio_set_value(J2_GPIO, 1); //輸出高電平 return 0; default: return -EINVAL; } } static int relay_write(struct file *file, const char * buffer, size_t count, loff_t * ppos) { unsigned long err; err = copy_from_user(drv_buf, buffer, 1); update_relay(); return 1; } static struct file_operations dev_fops={ write:relay_write, }; static struct miscdevice misc = { .minor = MISC_DYNAMIC_MINOR, .name = DEVICE_NAME, .fops = &dev_fops, }; static int __init my_relay_init(void) { int ret; gpio_direction_output(J1_GPIO, 1);//設定輸出 gpio_direction_output(J2_GPIO, 1);//設定輸出 ret = misc_register(&misc); printk (DEVICE_NAME"\t#NanoPi2 J1 J2 initialized\n"); return ret; } static void __exit my_relay_exit(void) { misc_deregister(&misc); } module_init(my_relay_init); module_exit(my_relay_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("TONY"); MODULE_DESCRIPTION("91arm.com Relay Driver");
核心模組不能載入問題
insmod 加載出現如下問題
root@nanopi2:/home/fa# insmod 4418_relay.ko
insmod: ERROR: could not insert module 4418_relay.ko: Invalid module format
檢視錯誤資訊,version magic驅動程式同開發板核心不匹配。
root@nanopi2:/home/fa# dmesg |tail
[ 2589.164000] 4418_relay: version magic '3.4.39-s5p4418 SMP preempt mod_unload ARMv7 p2v8 ' should be '3.4.39-FriendlyARM SMP preempt mod_unload ARMv7 p2v8 '
修改核心版本資訊,-s5p4418改成核心的FriendlyARM。
測試程式原始碼
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#define DEV_FILE "/dev/4418_relay"
#define J1_OFF 0x00
#define J1_ON 0x01
#define J2_OFF 0x10
#define J2_ON 0x11
int main()
{
int fd_dev=-1;
char dat[2];
int cmd;
printf("nanoPi driver Test\n");
fd_dev = open(DEV_FILE,O_RDWR);
if(fd_dev<0){
printf("open device err\n");
return 0;
}
while(1){
printf("1:J1 OFF 2:J1 ON 3:J2 OFF 4:J2 ON\n");
printf("Please input:");
scanf("%d",&cmd);
switch(cmd){
case 1:
dat[0] = J1_OFF;
break;
case 2:
dat[0] = J1_ON;
break;
case 3:
dat[0] = J2_OFF;
break;
case 4:
dat[0] = J2_ON;
break;
default:
break;
}
write(fd_dev,dat,1);
}
return 0;
}
自己的心得:#include<>尖括號中的標頭檔案去哪裡找,是makefile中定下來的,是linux原始碼中的,如上面的#include <mach/platform.h>,在我的nanopi 2s的配置情況下,對應linux原始檔目錄下arch\arm\plat-s5p4418\include\mach\platform.h,而這個檔案包含了arch\arm\plat-s5p4418\commom\cfg_type.h,而這個標頭檔案中對PAD_GPIO_A等進行了定義