- Navigation (`・ω・´)
- house主页
- 作品
- 暮光小猿图片管理器2
- av_timerSC 科学创造
- 记录
- videocam没事瞎折腾系列
- devices隔壁老王210
- devicesLinux嵌入式
- 关于
- archive更新日志
- restore历史版本
哔哩哔哩 - ( ゜- ゜)つロ 乾杯~
实验环境
- 硬件: Orange PI Zero 512M
- CPU: Allwiner H2+
- 内核版本: 3.4.113
- 操作系统: Armbian 版本忘了
相关资料
找到寄存器地址
上一页的用函数控制GPIO, 在GPIO已经被占用的情况下不能再用函数去控制.
那么可以通过直接改写内存中对应地址的数据对GPIO进行操作.
根据全志H3的芯片手册找到PIO寄存器地址为 0x01C20800.
再根据手册找到GPIOA数据寄存器的偏移为 0x10.
这是一个32位UINT型变量, 类似于STM32的ODR寄存器.
修改寄存器数据
虽然在上面找到了寄存器的地址...但是在Linux内核中是不能直接访问到这个地址的.
在Linux内核中, 这些寄存器地址都映射到了一个比较高的地址.
所以需要先找到这个虚拟地址, 通过修改这个虚拟地址的数据达到修改GPIO数据目的.
main.c
#include <linux/module.h>
#include <linux/delay.h>
#include <asm/io.h>
#define PIO_BASE ((uint32_t)0x01C20800) // PIO寄存器地址
#define PA_DATA_BASE ((uint32_t)PIO_BASE+0x10) // GPIOA寄存器地址
static volatile uint32_t *PA_DATA_VREG; // GPIOA虚拟寄存器指针变量
static __init int MapLed_Init(void)
{
// 映射虚拟寄存器地址 uint是4字节
PA_DATA_VREG = (uint32_t *)ioremap(PA_DATA_BASE, 4);
// PA17高电平
*PA_DATA_VREG |= 1 << 17;
// 延时500ms, 根据官方资料, 大于20ms的延时需要用msleep_interruptible
msleep_interruptible(500);
// PA17低电平
*PA_DATA_VREG &= ~((uint32_t)1 << 17);
// 延时500ms
msleep_interruptible(500);
// PA17高电平
*PA_DATA_VREG |= 1 << 17;
return 0;
}
static __exit void MapLed_Exit(void)
{
// PA17低电平
*PA_DATA_VREG &= ~((uint32_t)1 << 17);
// 释放映射
iounmap(PA_DATA_VREG);
}
module_init(MapLed_Init);
module_exit(MapLed_Exit);
MODULE_LICENSE("GPL");
编译测试
Makefile
NAME = MapLed
KDIR := /usr/src/linux-headers-3.4.113-sun8i
obj-m := MapLed.o
$(NAME)-objs := main.o
PWD := $(shell pwd)
all:
$(MAKE) -C $(KDIR) M=$(PWD) modules
clean:
-rm -rf *.ko *.o *.symvers modules.order $(NAME).*
load:
insmod $(NAME).ko
unload:
rmmod $(NAME)
加载运行
# 编译
root@orangepizero:~/mapLedTest# make
make -C /usr/src/linux-headers-3.4.113-sun8i M=/root/mapLedTest modules
make[1]: Entering directory '/usr/src/linux-headers-3.4.113-sun8i'
CC [M] /root/mapLedTest/main.o
LD [M] /root/mapLedTest/MapLed.o
Building modules, stage 2.
MODPOST 1 modules
CC /root/mapLedTest/MapLed.mod.o
LD [M] /root/mapLedTest/MapLed.ko
make[1]: Leaving directory '/usr/src/linux-headers-3.4.113-sun8i'
# 加载模块, 同时红色LED闪烁一次并加载成功
root@orangepizero:~/mapLedTest# make load
insmod MapLed.ko
# 卸载模块, 同时红色LED熄灭
root@orangepizero:~/mapLedTest# make unload
rmmod MapLed
LED到底被什么占用了
在Linux中有一种设备叫LED
在系统中已经有这两个LED的驱动了
ledTest.sh
# 红色亮
echo 255 > /sys/class/leds/red_led/brightness
sleep 0.5
#绿色灭
echo 0 > /sys/class/leds/green_led/brightness
sleep 0.5
# 红灭绿亮
echo 0 > /sys/class/leds/red_led/brightness
echo 255 > /sys/class/leds/green_led/brightness