分享一个香橙派PC2的C语言点亮LED程序
转发自http://blog.csdn.net/u013908686/article/details/62422799
首先要编写字符设备驱动,代码大同小异,随便复制粘贴就行了。
但是要注意了,一定要保护好寄存器,不要乱搞,要不然系统崩了,就等着你妈妈喊你回家吃饭吧。
led.c
#include <linux/module.h>
#include <linux/init.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <linux/io.h>
#include<linux/device.h>
#include "led.h"
#define LED_MAJOR 245 //主设备号
unsigned int *led_config;
unsigned int *led_data;
unsigned int *led_pull;
struct cdev cdev;
dev_t devno;
int led_open(struct inode *node, struct file *filp)
{
uint32_t register_dat;
//000:Input 001:Output
led_config = ioremap(PA_CFG1,4);//从datesheet里面查询你的寄存器 这里用的是PA10
register_dat = readl(led_config);//先读取寄存器值 只操作你需要操作的位段 不要干扰其他端口
register_dat &= ~(0x7<<8);//清空PA10的值
writel(register_dat|0x1<<8,led_config);//PA10 设置成输出
//00: Pull-up/down disable 01: Pull-up 10: Pull-down 11: Reserved
led_pull = ioremap(PA_PILL0,4);
register_dat = readl(led_pull);//读取寄存器值
register_dat &= ~(0x3<<2*10);//清空PA10设置
writel((register_dat|0x1<<2*10),led_pull);//PA10 上拉
led_data = ioremap(PA_DAT,4);
return 0;
}
long led_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
uint32_t reg_dat;
switch (cmd)
{
case LED_ON:
reg_dat = readl(led_data);
reg_dat &= ~(1<<10);
writel(reg_dat|0x0<<10,led_data);
return 0;
case LED_OFF:
reg_dat = readl(led_data);
reg_dat &= ~(1<<10);
writel(reg_dat|0x1<<10,led_data);
return 0;
default:
return -EINVAL;
}
}
static struct file_operations led_fops =
{
.owner= THIS_MODULE,
.open = led_open,
.unlocked_ioctl = led_ioctl,
};
#define DEVICE_NAME "myled"
static struct class*leds_class;
static int led_init(void)
{
int ret;
//注册LED设备为字符设备
ret = register_chrdev(LED_MAJOR, DEVICE_NAME, &led_fops);
if(ret< 0)
{
printk(DEVICE_NAME" major number register falid!\n");
return ret;
}
//注册一个类,使mdev可以在/dev/下面建立设备节点
leds_class= class_create(THIS_MODULE, DEVICE_NAME);
if(IS_ERR(leds_class) )
{
printk("creatleds_class failed!");
return-1;
}
//创建一个设备节点,节点名字为DEVICE_NAME
device_create(leds_class,NULL, MKDEV(LED_MAJOR, 0), NULL, DEVICE_NAME);
printk(DEVICE_NAME"initialized!");
return 0;
}
static void led_exit(void)
{
//注销设备
unregister_chrdev(LED_MAJOR,DEVICE_NAME);
//删除设备节点
device_destroy(leds_class,MKDEV(LED_MAJOR, 0));
//注销类
class_destroy(leds_class);
}
module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("leo_learning");
MODULE_DESCRIPTION("myled driver");
以下是led.h
这里把所有的GPIO都列出来了
#ifndef _LED_H
#define _LED_H
//GPIOA_10
#define GPIO_BASE 0x01C20800
#define PA_CFG0 GPIO_BASE+0x0000+0*0x24 //GPIOA0-7
#define PA_CFG1 GPIO_BASE+0x0004+0*0x24 //GPIOA8-15
#define PA_CFG2 GPIO_BASE+0x0008+0*0x24 //GPIOA17-21
#define PA_CFG3 GPIO_BASE+0x000C+0*0x24 //GPIOA
#define PA_DAT GPIO_BASE+0x0010+0*0x24 //GPIOA_DAT
#define PA_DRV0 GPIO_BASE+0x0014+0*0x24
#define PA_DRV1 GPIO_BASE+0x0018+0*0x24
#define PA_PILL0 GPIO_BASE+0x001C+0*0x24
#define PA_PILL1 GPIO_BASE+0x0020+0*0x24
#define PC_CFG0 GPIO_BASE+0x0000+1*0x24 //GPIOC0-7
#define PC_CFG1 GPIO_BASE+0x0004+1*0x24 //GPIOC8-15
#define PC_CFG2 GPIO_BASE+0x0008+1*0x24 //GPIOC17-21
#define PC_CFG3 GPIO_BASE+0x000C+1*0x24 //GPIOC
#define PC_DAT GPIO_BASE+0x0010+1*0x24 //GPIOC_DAT
#define PC_DRV0 GPIO_BASE+0x0014+1*0x24
#define PC_DRV1 GPIO_BASE+0x0018+1*0x24
#define PC_PILL0 GPIO_BASE+0x001C+1*0x24
#define PC_PILL1 GPIO_BASE+0x0020+1*0x24
#define PD_CFG0 GPIO_BASE+0x0000+2*0x24 //GPIOD0-7
#define PD_CFG1 GPIO_BASE+0x0004+2*0x24 //GPIOD8-15
#define PD_CFG2 GPIO_BASE+0x0008+2*0x24 //GPIOD17-21
#define PD_CFG3 GPIO_BASE+0x000C+2*0x24 //GPIOD
#define PD_DAT GPIO_BASE+0x0010+2*0x24 //GPIOD_DAT
#define PD_DRV0 GPIO_BASE+0x0014+2*0x24
#define PD_DRV1 GPIO_BASE+0x0018+2*0x24
#define PD_PILL0 GPIO_BASE+0x001C+2*0x24
#define PD_PILL1 GPIO_BASE+0x0020+2*0x24
#define PE_CFG0 GPIO_BASE+0x0000+3*0x24 //GPIOE0-7
#define PE_CFG1 GPIO_BASE+0x0004+3*0x24 //GPIOE8-15
#define PE_CFG2 GPIO_BASE+0x0008+3*0x24 //GPIOE17-21
#define PE_CFG3 GPIO_BASE+0x000C+3*0x24 //GPIOE
#define PE_DAT GPIO_BASE+0x0010+3*0x24 //GPIOE_DAT
#define PE_DRV0 GPIO_BASE+0x0014+3*0x24
#define PE_DRV1 GPIO_BASE+0x0018+3*0x24
#define PE_PILL0 GPIO_BASE+0x001C+3*0x24
#define PE_PILL1 GPIO_BASE+0x0020+3*0x24
#define PF_CFG0 GPIO_BASE+0x0000+4*0x24 //GPIOF0-7
#define PF_CFG1 GPIO_BASE+0x0004+4*0x24 //GPIOF8-15
#define PF_CFG2 GPIO_BASE+0x0008+4*0x24 //GPIOF17-21
#define PF_CFG3 GPIO_BASE+0x000C+4*0x24 //GPIOF
#define PF_DAT GPIO_BASE+0x0010+4*0x24 //GPIOF_DAT
#define PF_DRV0 GPIO_BASE+0x0014+4*0x24
#define PF_DRV1 GPIO_BASE+0x0018+4*0x24
#define PF_PILL0 GPIO_BASE+0x001C+4*0x24
#define PF_PILL1 GPIO_BASE+0x0020+4*0x24
#define PG_CFG0 GPIO_BASE+0x0000+5*0x24 //GPIOG0-7
#define PG_CFG1 GPIO_BASE+0x0004+5*0x24 //GPIOG8-15
#define PG_CFG2 GPIO_BASE+0x0008+5*0x24 //GPIOG17-21
#define PG_CFG3 GPIO_BASE+0x000C+5*0x24 //GPIOG
#define PG_DAT GPIO_BASE+0x0010+5*0x24 //GPIOG_DAT
#define PG_DRV0 GPIO_BASE+0x0014+5*0x24
#define PG_DRV1 GPIO_BASE+0x0018+5*0x24
#define PG_PILL0 GPIO_BASE+0x001C+5*0x24
#define PG_PILL1 GPIO_BASE+0x0020+5*0x24
#define PL_CFG0 GPIO_BASE+0x0000+6*0x24 //GPIOL0-7
#define PL_CFG1 GPIO_BASE+0x0004+6*0x24 //GPIOL8-15
#define PL_CFG2 GPIO_BASE+0x0008+6*0x24 //GPIOL17-21
#define PL_CFG3 GPIO_BASE+0x000C+6*0x24 //GPIOL
#define PL_DAT GPIO_BASE+0x0010+6*0x24 //GPIOL_DAT
#define PL_DRV0 GPIO_BASE+0x0014+6*0x24
#define PL_DRV1 GPIO_BASE+0x0018+6*0x24
#define PL_PILL0 GPIO_BASE+0x001C+6*0x24
#define PL_PILL1 GPIO_BASE+0x0020+6*0x24
#define PA_INT_CFG0 0x0200 + 0x00 + 0*0x20
#define PA_INT_CFG1 0x0200 + 0x04 + 0*0x20
#define PA_INT_CFG2 0x0200 + 0x08 + 0*0x20
#define PA_INT_CFG3 0x0200 + 0x0C + 0*0x20
#define PA_INT_CTL 0x0200 + 0x10 + 0*0x20
#define PA_INT_STA 0x0200 + 0x14 + 0*0x20
#define PA_INT_DEB 0x0200 + 0x18 + 0*0x20
#define PF_INT_CFG0 0x0200 + 0x00 + 1*0x20
#define PF_INT_CFG1 0x0200 + 0x04 + 1*0x20
#define PF_INT_CFG2 0x0200 + 0x08 + 1*0x20
#define PF_INT_CFG3 0x0200 + 0x0C + 1*0x20
#define PF_INT_CTL 0x0200 + 0x10 + 1*0x20
#define PF_INT_STA 0x0200 + 0x14 + 1*0x20
#define PF_INT_DEB 0x0200 + 0x18 + 1*0x20
#define PG_INT_CFG0 0x0200 + 0x00 + 2*0x20
#define PG_INT_CFG1 0x0200 + 0x04 + 2*0x20
#define PG_INT_CFG2 0x0200 + 0x08 + 2*0x20
#define PG_INT_CFG3 0x0200 + 0x0C + 2*0x20
#define PG_INT_CTL 0x0200 + 0x10 + 2*0x20
#define PG_INT_STA 0x0200 + 0x14 + 2*0x20
#define PG_INT_DEB 0x0200 + 0x18 + 2*0x20
#define LED_MAGIC 'L'
#define LED_ON _IO(LED_MAGIC,1)
#define LED_OFF _IO(LED_MAGIC,0)
#endif
Makefile,把这里的KDIR改成你开发板内核源码对应目录,指定交叉编译工具链,如果没有什么问题,make会编译出led.ko,只要insmod led.ko就行了, so easy
obj-m := led.o
KDIR := /home/share/OrangePi_H5SDK/kernel
all:
make -C $(KDIR) M=$(PWD) modules \
CROSS_COMPILE=/home/share/OrangePi_H5SDK/toolchain/gcc-linaro-aarch/bin/aarch64-linux-gnu- ARCH=arm64
clean:
rm -f *.ko *.o *.mod.o *.mod.c *.symvers *.bak *.order
上面是在PC上给板子交叉编译的,下面给出个在板子上编译的,需要内核头文件。
ifneq ($(KERNELRELEASE),)
obj-m:=led.o
else
CURRENT_PATH:=$(shell pwd)
LINUX_KERNEL_PATH:=/lib/modules/$(shell uname -r)/build
all:
make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) modules
clean:
make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) clean
endif
最后是应用软件,安装led.ko内核模块会产生一个/dev/myled的设备节点,现在我们需要打开它,并对其进行读写操作
led_app.c
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include "led.h"
int main(int argc, char *argv[])
{
int fd;
int cmd;
if (argc <2 )
{
printf("please enter the second para!\n");
return 0;
}
cmd = atoi(argv[1]);
fd = open("/dev/myled",O_RDWR);
if (cmd == 1)
ioctl(fd,LED_ON);
else
ioctl(fd,LED_OFF);
return 0;
}
PC上交叉编译
aarch64-Linux-gnu-gcc -o led_app led_app.c
板子上编译
gcc -o led_app led_app.c
通过
./led_app 0
熄灭LED
./led_app 1
点亮
然后随便浪吧