1、类似MCU通过直接控制寄存器的方式去控制,好处是实时性
该方式通过iomap方式把寄存器映射到内存方式来进行控制,需要依据芯片datasheet的寄存器去控制。
#define GPIOB_CFG0 (0x02000030)
#define GPIOB_CFG1 (0x02000034)
#define GPIOB_DATA (0x02000040)
#define GPIOB_PUL0 (0x02000054)
//寄存器物理地址到虚拟地址的映射
gpiob_cfg0 = ioremap(GPIOB_CFG0,4);
gpiob_cfg1 = ioremap(GPIOB_CFG1,4);
gpiob_data = ioremap(GPIOB_DATA,4);
gpiob_pul0 = ioremap(GPIOB_PUL0,4);
//io初始化以及设定
*((volatile size_t*)gpiob_cfg0) &= ~(15<<16);
*((volatile size_t*)gpiob_cfg0) |= (1<<16);
*((volatile size_t*)gpiob_pul0) &= ~(3<<8);
*((volatile size_t*)gpiob_pul0) |= (1<<8);
//io控制
*((volatile size_t*)gpiob_data) &= ~(1<<4) ;
if(status)
*((volatile size_t*)gpiob_data) |= (1<<4);
2、通过设备树方式
设备树文件添加一个节点,通过of系统函数获取到设备树节点以及实际io号,通过gpio requet等系统函数直接控制,不需要去关心芯片底层控制器
设备树根节点下加节点
mqrled {
led-gpios = <&pio PD 22 GPIO_ACTIVE_HIGH>;
};
//从设备树找出设备节点并提取到gpio号
struct device_node *led_node;
led_node = of_find_node_by_path("/mqrled");
if(led_node == NULL)
{
printk(KERN_DEBUG"no led dts!!!\n");
}
LED_IO = of_get_named_gpio(led_node, "led-gpios", 0);
printk(KERN_DEBUG"LED_IO is:%d\n",LED_IO);
//依据拿到的io号去申请io 设置io输出以及实际的io高低控制
ret = gpio_request(LED_IO, "led_0");
if (ret < 0)
{
return ret;
}
else
{
gpio_direction_output(LED_IO, 0);
return 0;
}
if(status)
{
gpio_set_value(LED_IO, 0);
}
else
{
gpio_set_value(LED_IO, 1);
}
3、通过GPIO子系统 sys层面直接控制
内核开启gpio子系统支持
GPIO Support以及[*] /sys/class/gpio/... (sysfs interface)
依据io号直接export导出控制,不需要自己写额外驱动代码
echo 118> /sys/class/gpio/export
cd /sys/class/gpio/gpio118
echo out > direction
echo 0 > value
echo 1 > value
4、通过设备树加LED子系统方式
添加led设备树,通过led子系统控制,不需要额外自己写驱动代码
leds {
compatible = "gpio-leds";//必须固定gpio-leds让系统能probe到有这个设备
led0 {
gpios = <&pio PD 22 GPIO_ACTIVE_HIGH>;
};
};
控制
root@TinaLinux:/sys/devices/platform/leds/leds/led0# echo 255 > brightness
root@TinaLinux:/sys/devices/platform/leds/leds/led0# echo 0 > brightness
root@TinaLinux:/sys/devices/platform/leds/leds/led0# echo 255 > brightness