通过sysfs控制gpio来驱动LED
文章参考了https://sysprogs.com/VisualKernel/tutorials/raspberry/leddriver/ Creating a Basic LED Driver for Raspberry Pi
gpio操作在硬件调试中经常被硬件工程师用到。经常搜到的方法是 这种 https://docs.linuxkernel.org.cn/userspace-api/gpio/sysfs.html 。用户空间可以通过将 GPIO 号写入 对 /sys/class/gpio/export来请求内核将 GPIO 的控制权导出到用户空间。例如:“echo 19 > export”将为 GPIO #19 创建一个“gpio19”节点。然后对 /sys/class/gpio/gpio19/目录下的direction,value进行控制。
下面的程序还是省略了头文件和出错处理。加载模块后,可以直接通过echo 写sysfs下的节点来控制gpio的状态。
static struct class *led_class;
static struct device *my_led;
/* registers */
// IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3 地址:0x02290000 + 0x14
static volatile unsigned int *IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3;
// GPIO5_GDIR 地址:0x020AC004
static volatile unsigned int *GPIO5_GDIR;
//GPIO5_DR 地址:0x020AC000
static volatile unsigned int *GPIO5_DR;
static ssize_t led_control(struct device* dev,
struct device_attribute* attr,
const char* buf,
size_t count)
{
int value = 0;
if (kstrtoint(buf, 10, &value) < 0)
return -EINVAL;
if (value)
{
/* set gpio to let led on */
*GPIO5_DR &= ~(1<<3);
}
else
{
/* set gpio to let led off */
*GPIO5_DR |= (1<<3);
}
return count;
}
static DEVICE_ATTR(myled, S_IWUSR | S_IWGRP, NULL, led_control);//定义属性
/* 入口函数 */
static int __init led_init(void)
{
int result ;
printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
/* ioremap */
// IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3 地址:0x02290000 + 0x14
IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3 = ioremap(0x02290000 + 0x14, 4);
// GPIO5_GDIR 地址:0x020AC004
GPIO5_GDIR = ioremap(0x020AC004, 4);
//GPIO5_DR 地址:0x020AC000
GPIO5_DR = ioremap(0x020AC000, 4);
/* enable gpio5
* configure gpio5_io3 as gpio
* configure gpio5_io3 as output
*/
*IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3 &= ~0xf;
*IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3 |= 0x5;
*GPIO5_GDIR |= (1<<3);
led_class = class_create(THIS_MODULE, "myled");
my_led = device_create(led_class, NULL, 0, NULL, "myled");
result = device_create_file( my_led, &dev_attr_myled); //创建文件
return 0;
}
static void __exit led_exit(void)
{
iounmap(IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3);
iounmap(GPIO5_GDIR);
iounmap(GPIO5_DR);
device_remove_file(my_led, &dev_attr_myled);
device_destroy(led_class, 0);
class_destroy(led_class);
}
module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE("GPL");
浙公网安备 33010602011771号