原本以為將原本完全沒設定的 reset 按鈕註冊成 platform device 會是最困難的,
之前先試著改紅外線遙控喚醒卻不好找到問題。
找了些gpio key的資料後,
順利把 reset 按鈕設定成 platform device。
除了在 dmesg 中出現下面訊息外,
evbug.c: Event. Dev: input0, Type: 1, Code: 28, Value: 1
evbug.c: Event. Dev: input0, Type: 0, Code: 0, Value: 0
evbug.c: Event. Dev: input0, Type: 1, Code: 28, Value: 0
evbug.c: Event. Dev: input0, Type: 0, Code: 0, Value: 0
意外的順利用來喚醒 suspend to ram 的系統,
雖然沒有遙控器喚醒方便,
但已經比之前只能用 WoL 和 TTL 訊號實用多了。
修改已經更新到 https://github.com/rexct/kernel-pdk7105
kernel 對於板子的設定幾乎都在 arch/sh/boards/mach-pdk7105/setup.c 。
在 網樂通改機俱樂部Chia-Cheng Huang (suzuke) porting 2.6.32.59 時就存在下面的 structure 定義 LED。
static struct platform_device pdk7105_leds = {
.name = "leds-gpio",
.id = 0,
.dev.platform_data = &(struct gpio_led_platform_data) {
.num_leds = 2,
.leds = (struct gpio_led[]) {
{
.name = "LD5",
.default_trigger = "heartbeat",
.gpio = stm_gpio(2, 4), //stpio_to_gpio(2, 4),
},
{
.name = "LD6",
.gpio = stm_gpio(2, 3), //stpio_to_gpio(2, 3),
},
},
},
};
不過在336行 的註冊用structure 中卻是變成註解
static struct platform_device *pdk7105_devices[] __initdata = {
// &pdk7105_leds,
// &pdk7105_phy_device,
&spi_pio_device,
};
根據之前 控制網樂通LED 中在 user space 直接控制GPIO訊號用的針腳位置,
感覺 setup.c 中的怪怪的。
最近學會用的 cscope + vim 派上用場,
找到 include/linux/stm/gpio.h 中定義
#define stm_gpio(porst, pin) ((port) * STM_GPIO_PINS_PER_PORT + (pin))
以藍色LED port 值應該是0,pin 值是4,
以紅色LED port 值是0,pin 值是5,
reset按鈕 port值同樣是0,pin 是1。
為了解省編譯時間,
LED 和 reset 按鈕以起測試。
先在kernel 附的 Documentation/gpio.txt 文件中看到 gpio_keys ,
建議 LEDs 和 Buttons 用 kernel 內建的控制會比目前使用的 user space 方式還好。
以 gpio_keys 找到下面三個網頁:
1. arm板子使用GPIO-keys驱动方法及测试程序
2. Fred's blog: Add GPIO Keys support for Devkit8000
3. 使用Linux内核自带的GPIO 按键驱动 - [凌云嵌入式] - 嵌入式新手入门区 - 嵌入式开发联盟
從 1 和 3 可以得到要加入的 sturcture
#if defined(CONFIG_KEYBOARD_GPIO)
static struct gpio_keys_button pdk7105_keys[] = {
{
.gpio = stm_gpio(0, 1), /*rexct.131108: set gpio pin number(group number,sub-sequence number) */
.code = KEY_ENTER, /*rexct.131108:KEY_ENTER = 28 ref:include/linux/input.h */
.active_low = 1,
.wakeup = 1,
},
};
static struct gpio_keys_platform_data pdk7105_key_data = {
.buttons = pdk7105_keys,
.nbuttons = ARRAY_SIZE(pdk7105_keys),
};
static struct platform_device pdk7105_key_device = {
.name = "gpio-keys",
.id = -1,
.num_resources = 0,
.dev = {
.platform_data = &pdk7105_key_data,
}
};
#endif
以及將寫好的裝置定義 structure pdk7105_key_device 註冊成 platform device
static struct platform_device *pdk7105_devices[] __initdata = {
#if defined(CONFIG_KEYBOARD_GPIO)
&pdk7105_key_device,
#endif
};
其中為了避免在kernel .config 中沒定義第2個連結提到的 CONFIG_KEYBOARD_GPIO=y ,
加上
#if defined(CONFIG_KEYBOARD_GPIO)
#endif
避免沒選擇時出問題。
用structure 類型名稱 gpio_keys_button 可以找到定義在 include/linux/gpio_keys.h,
.code 值可以用 KEY_ENTER 找到定義在 include/linux/input.h 中,
因為沒有 reset 的定義,
暫時用 KEY_ENTER 代替,
在 dmesg 中會出現 Code:28
另外從 1 和 3 中也可以得到 menuconfig 所需項目:
Device Drivers
Input device support
Keyboards
GPIO Buttons
到這裡 reset 按鈕只要 把 kernel 編譯好就可以使用了。
另外參考了連結 1 後附的測試程式改成測試用程式含編譯完成執行檔:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <time.h>
#include <fcntl.h>
#include <linux/input.h>
int main(int argc, char **argv)
{
int key_state;
int fd;
int ret;
int code;
struct input_event buf;
int repeat_param[2];
fd = open("/dev/input/event0", O_RDONLY);
if (fd < 0)
{
printf("Open gpio-keys failed.\n");
return -1;
}
else
{
printf("Open gpio-keys success.\n");
}
repeat_param[0]=500;//ms重复按键第一次间隔
repeat_param[1]=66;//ms重复按键后续间隔
ret = ioctl(fd,EVIOCSREP,(int *)repeat_param);//设置重复按键参数
if(ret != 0)
{
printf("set repeat_param fail!\n");
}
else
{
printf("set repeat_param ok.\n");
}
while(1)
{
ret = read(fd,&buf,sizeof(struct input_event));
if(ret <= 0)
{
printf("read fail!\n");
return -1;
}
code = buf.code;
key_state = buf.value;
printf("Key_%c state= %d.\n",code,key_state);
}
close(fd);
printf("Key test finished.\n");
return 0;
}
沒有留言:
張貼留言