通过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");
posted @ 2026-03-09 22:59  michael2025  阅读(1)  评论(0)    收藏  举报