主要介绍imx28x的GPIO操作
- GPIO序号
gpio序号=BANK*32 + N
比如p2.4的GPIO序号就是:
2*32+4=68
imx283/287的四个GPIO的序号分别是:
描述 | 名称 | 序号 |
---|---|---|
LED1 | GPIO3_26 | 122 |
LED2 | GPIO3_22 | 118 |
LED3 | GPIO3_20 | 116 |
LED4 | GPIO2_7 | 71 |
GPIO的PIN定义可以查看bootloader/u-boot-2009.08/include/asm-arm/arch-mx28/pinctrl.h
- GPIO操作
- 导出GPIO
cd /sys/class/gpio/
echo 71 >export
- 设置方向
echo in > direction
echo out > direction
- 设置高低电平
echo 0 >value
echo 1 >value
- 应用示例
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <errno.h>
#define DEV_PATH "/sys/devices/virtual/gpio/gpio68/value"
int main(void)
{
int fd = 0;
char value;
fd = open(DEV_PATH, O_RDWR);
if (fd < 0) {
perror(DEV_PATH);
}
lseek(fd, 0, SEEK_SET);
read(fd, &value, 1);
printf("get value:%c \n", value);
close(fd);
return 0;
}
- beep驱动
无源蜂鸣器需要2K~5K的方波驱动,所以BEEP的驱动就是控制GPIO产生PWM方波
驱动源文件位于:
3.Linux\4.开发示例\6、驱动示例\beep\
- BEEP驱动源码:
/*
GPIO Driver driver for EasyARM-iMX283
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/ioctl.h>
#include <linux/delay.h>
#include <linux/bcd.h>
#include <linux/capability.h>
#include <linux/rtc.h>
#include <linux/cdev.h>
#include <linux/miscdevice.h>
#include <linux/gpio.h>
#include <../arch/arm/mach-mx28/mx28_pins.h>
#define DEVICE_NAME "imx283_beep"
/*--------------------------------------------------------------------------------------------------------
*/
static int gpio_open(struct inode *inode, struct file *filp);
static int gpio_release(struct inode *inode, struct file *filp);
ssize_t gpio_write(struct file *filp, const char __user *buf, size_t count,
loff_t *f_pos);
static int gpio_ioctl(struct inode *inode,struct file *flip,unsigned int command,unsigned long arg);
static int gpio_init(void);
static void gpio_exit(void);
/*--------------------------------------------------------------------------------------------------------
*/
static int gpio_open(struct inode *inode, struct file *filp)
{
gpio_request(MXS_PIN_TO_GPIO(PINID_LCD_D21), "beep");
return 0;
}
static int gpio_release(struct inode *inode, struct file *filp)
{
gpio_free(MXS_PIN_TO_GPIO(PINID_LCD_D21));
return 0;
}
ssize_t gpio_write(struct file *filp, const char __user *buf, size_t count,
loff_t *f_pos)
{
char data[2];
copy_from_user(data, buf, count);
gpio_direction_output(MXS_PIN_TO_GPIO(PINID_LCD_D21), data[0]);
return count;
}
static int gpio_ioctl(struct inode *inode,struct file *flip,unsigned int command,unsigned long arg)
{
int data;
switch (command) {
case 0:
gpio_direction_output(MXS_PIN_TO_GPIO(PINID_LCD_D21), 1);
break;
case 1:
gpio_direction_output(MXS_PIN_TO_GPIO(PINID_LCD_D21), 0);
break;
}
return 0;
}
static struct file_operations gpio_fops={
.owner = THIS_MODULE,
.open = gpio_open,
.write = gpio_write,
.release = gpio_release,
.ioctl = gpio_ioctl,
};
static struct miscdevice gpio_miscdev = {
.minor = MISC_DYNAMIC_MINOR,
.name = DEVICE_NAME,
.fops = &gpio_fops,
};
static int __init gpio_init(void)
{
misc_register(&gpio_miscdev);
printk(DEVICE_NAME" up. \n");
return 0;
}
static void __exit gpio_exit(void)
{
misc_deregister(&gpio_miscdev);
printk(DEVICE_NAME " down.\n");
}
module_init(gpio_init);
module_exit(gpio_exit);
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("zhuguojun, ZhiYuan Electronics Co, Ltd.");
MODULE_DESCRIPTION("GPIO DRIVER FOR MAGICARM270.");
- 测试程序
这个测试程序运行后BEEP不会响,原因是sleep()时间太长,产生的方波不满足BEEP的工作需求,将sleep()函数改为usleep()
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <errno.h>
#include <limits.h>
#include <asm/ioctls.h>
#include <time.h>
#include <pthread.h>
int main(void)
{
int fd;
char buf[1] = {0};
fd = open("/dev/imx283_beep", O_RDWR);
if (fd < 0) {
perror("open /dev/imx283_gpio");
}
printf("test write....\n");
buf[0] = 1;
write(fd, buf, 1);
sleep(2);
buf[0] = 0;
write(fd, buf, 1);
sleep(1);
printf("test ioctl..... \n");
ioctl(fd, 0);
sleep(2);
ioctl(fd, 1);
sleep(1);
}
修改后的程序:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <errno.h>
#include <limits.h>
#include <asm/ioctls.h>
#include <time.h>
#include <pthread.h>
int main(void)
{
int fd;
char buf[1] = {0};
fd = open("/dev/imx283_beep", O_RDWR);
if (fd < 0) {
perror("open /dev/imx283_gpio");
}
printf("test write....\n");
while(1){
buf[0] = 1;
write(fd, buf, 1);
usleep(50);
buf[0] = 0;
write(fd, buf, 1);
usleep(50);
}
printf("test ioctl..... \n");
ioctl(fd, 0);
sleep(2);
ioctl(fd, 1);
sleep(1);
}
- led驱动
根据pinctrl.h中的定义
#define PINID_SSP0_DATA7 PINID_ENCODE(2, 7)
修改驱动控制led4
#define LED_GPIO MXS_PIN_TO_GPIO(PINID_SSP0_DATA7)
- led驱动程序
/*
GPIO Driver driver for EasyARM-iMX283
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/ioctl.h>
#include <linux/delay.h>
#include <linux/bcd.h>
#include <linux/capability.h>
#include <linux/rtc.h>
#include <linux/cdev.h>
#include <linux/miscdevice.h>
#include <linux/gpio.h>
#include <../arch/arm/mach-mx28/mx28_pins.h>
#define DEVICE_NAME "imx28x_led"
#define LED_GPIO MXS_PIN_TO_GPIO(PINID_SSP0_DATA7) //for 283 287A/B
//#define LED_GPIO MXS_PIN_TO_GPIO(PINID_SAIF0_MCLK) //for 280
/*--------------------------------------------------------------------------------------------------------
*/
static int gpio_open(struct inode *inode, struct file *filp);
static int gpio_release(struct inode *inode, struct file *filp);
ssize_t gpio_write(struct file *filp, const char __user *buf, size_t count,
loff_t *f_pos);
static int gpio_ioctl(struct inode *inode,struct file *flip,unsigned int command,unsigned long arg);
static int gpio_init(void);
static void gpio_exit(void);
/*--------------------------------------------------------------------------------------------------------
*/
static int gpio_open(struct inode *inode, struct file *filp)
{
gpio_request(LED_GPIO, "led");
return 0;
}
static int gpio_release(struct inode *inode, struct file *filp)
{
gpio_free(LED_GPIO);
return 0;
}
ssize_t gpio_write(struct file *filp, const char __user *buf, size_t count,
loff_t *f_pos)
{
char data[2];
copy_from_user(data, buf, count);
gpio_direction_output(LED_GPIO, data[0]);
return count;
}
static int gpio_ioctl(struct inode *inode,struct file *flip,unsigned int command,unsigned long arg)
{
int data;
switch (command) {
case 0:
gpio_direction_output(LED_GPIO, 0);
break;
case 1:
gpio_direction_output(LED_GPIO, 1);
break;
}
return 0;
}
static struct file_operations gpio_fops={
.owner = THIS_MODULE,
.open = gpio_open,
.write = gpio_write,
.release = gpio_release,
.ioctl = gpio_ioctl,
};
static struct miscdevice gpio_miscdev = {
.minor = MISC_DYNAMIC_MINOR,
.name = DEVICE_NAME,
.fops = &gpio_fops,
};
static int __init gpio_init(void)
{
misc_register(&gpio_miscdev);
printk(DEVICE_NAME" up. \n");
return 0;
}
static void __exit gpio_exit(void)
{
misc_deregister(&gpio_miscdev);
printk(DEVICE_NAME " down.\n");
}
module_init(gpio_init);
module_exit(gpio_exit);
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("zhuguojun, ZhiYuan Electronics Co, Ltd.");
MODULE_DESCRIPTION("GPIO DRIVER FOR EasyARM-i.MX28xx");
- led测试程序
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <errno.h>
#include <limits.h>
#include <asm/ioctls.h>
#include <time.h>
#include <pthread.h>
int main(void)
{
int fd;
char buf[1] = {0};
fd = open("/dev/imx28x_led", O_RDWR);
if (fd < 0) {
perror("open /dev/imx283_led");
}
printf("test write....\n");
buf[0] = 0;
write(fd, buf, 1);
sleep(2);
buf[0] = 1;
write(fd, buf, 1);
sleep(1);
printf("test ioctl..... \n");
ioctl(fd, 0);
sleep(2);
ioctl(fd, 1);
}