2015/4/23

【樹莓派】寫Driver控制GPIO

  控制RPi的GPIO方法很多,在User Space下可以透過讀寫/dev/mem或是/sys/class/gpio來控制輸出與讀取狀態;在Kernel Space下就要自己寫一個Driver(或稱為核心模組)來實現了!另外有高手寫了WiringPi讓大家可以簡單透過python來實現IO控制(包括I2C與SPI),也提供API讓C語言之類的程式進行調用。
  這篇文章提供一個簡單的範例,示範如何寫一個驅動程式控制RPi的GPIO。
  首先查看電路圖(Schematic),挑選GPIO_GEN0來連接LED燈正極,並將LED負極接到旁邊的地(Ground,Pin9),如此一來把Pin11設為1就會點亮LED燈,設為0就會讓LED熄滅。

  上圖的GPIO_GEN0是Pin11,但這個Pin11指的是P1這個連接頭(Header)的編號,實際上我們要控制的是BCM2835(RPi的ARM核心)接腳,所以得在電路圖上找尋GPIO_GEN0在核心上對應的GPIO編號,查看下圖得知是GPIO17
確定好要控制的GPIO編號後,就可以來撰寫驅動程式了,直接看Code
rpi.c
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/gpio.h>

#define DRIVER_AUTHOR    "YS Wang <yaushung AT gmail.com>"
#define DRIVER_DESC    "RPi GPIO Output Demo"
#define GPIO0_PIN    17
#define GPIO0_DESC    "GPIO0"
#define GPIO0_DEVICE_DESC   "GPIO17Output"

MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);

int rpi_init(void) {
 printk(KERN_NOTICE "Hello, RPi !\n");
 
 if (gpio_request(GPIO0_PIN, GPIO0_DESC)) {
  printk("[%s] Request fail\n", GPIO0_DESC);
  return -EIO;
 }

 printk(KERN_ALERT "[%s] Request Pin%d ... Success.\n",
  GPIO0_DESC, GPIO0_PIN);

 gpio_direction_output(GPIO0_PIN, 1);

 return 0;
}

void rpi_exit(void) {
 printk(KERN_ALERT "Goodbye, RPi\n");
 gpio_direction_output(GPIO0_PIN, 0);
 gpio_free(GPIO0_PIN);
 return;
}

module_init(rpi_init);
module_exit(rpi_exit);
Makefile
# make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-

CFILES  = rpi.c

obj-m += rpi.o
sample-objs := $(CFILES:.c=.o)

all:
 make -C /home/acos/rpi/linux M=$(PWD) modules

clean:
 make -C /home/acos/rpi/linux M=$(PWD) clean

直接下make(make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-)指令就會產生rpi.ko模組檔案,接著把檔案複製到RPi上執行
sudo insmod rpi.ko      # 模組載入,這時會看到LED點亮
sudo rmmod rpi      # 模組卸除,這時會看到LED熄滅

編譯環境設置可以參考這篇文章

沒有留言:

張貼留言