diff --git a/17_platform/.vscode/c_cpp_properties.json b/17_platform/.vscode/c_cpp_properties.json new file mode 100644 index 0000000000000000000000000000000000000000..cb10f14b6b40f342741561de7075f245b6d38527 --- /dev/null +++ b/17_platform/.vscode/c_cpp_properties.json @@ -0,0 +1,40 @@ +{ + "configurations": [ + { + "name": "Linux", + "includePath": [ + "../../../linux-imx-rel_imx_4.1.15_2.1.0_ga/include", + "../../../linux-imx-rel_imx_4.1.15_2.1.0_ga/arch/arm/include", + "../../../linux-imx-rel_imx_4.1.15_2.1.0_ga/arch/arm/include/generated", + "../../../linux-imx-rel_imx_4.1.15_2.1.0_ga/arch/arm/include/asm", + "../../../linux-imx-rel_imx_4.1.15_2.1.0_ga/drivers", + "${workspaceFolder}/**", + "${default}" + ], + "defines": ["__KERNEL__","__linux__"], + "compilerPath": "/usr/bin/clang", + "cStandard": "c11", + "cppStandard": "c++17", + "intelliSenseMode": "clang-x64" + }, + { + "name": "Win32", + "includePath": [ + "../../../linux-imx-rel_imx_4.1.15_2.1.0_ga/include", + "../../../linux-imx-rel_imx_4.1.15_2.1.0_ga/arch/arm/include", + "../../../linux-imx-rel_imx_4.1.15_2.1.0_ga/arch/arm/include/generated", + "../../../linux-imx-rel_imx_4.1.15_2.1.0_ga/arch/arm/include/asm", + "../../../linux-imx-rel_imx_4.1.15_2.1.0_ga/drivers", + "${workspaceFolder}/**", + "${default}" + ], + "defines": ["__KERNEL__","__linux__"], + "compilerPath": "C:/Qt/Qt5.12.9/Tools/mingw730_64/bin/gcc.exe", + "cStandard": "c11", + "cppStandard": "c++17", + "intelliSenseMode": "gcc-x64" + } + ], + "version": 4 +} + diff --git a/17_platform/.vscode/settings.json b/17_platform/.vscode/settings.json new file mode 100644 index 0000000000000000000000000000000000000000..1a2a04ac7a2d6b080404235adcd34b94bc581cb4 --- /dev/null +++ b/17_platform/.vscode/settings.json @@ -0,0 +1,21 @@ +{ + "search.exclude": { + "**/node_modules": true, + "**/bower_components": true, + "**/*.o":true, + "**/*.su":true, + "**/*.cmd":true, + "Documentation":true, + }, + "files.exclude": { + "**/.git": true, + "**/.svn": true, + "**/.hg": true, + "**/CVS": true, + "**/.DS_Store": true, + "**/*.o":true, + "**/*.su":true, + "**/*.cmd":true, + "Documentation":true, + } +} \ No newline at end of file diff --git a/17_platform/Makefile b/17_platform/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..e51d710cc014e12c2cd4bd8e5e495a96cc42ee51 --- /dev/null +++ b/17_platform/Makefile @@ -0,0 +1,13 @@ +KERNELDIR := ../../../linux-imx-rel_imx_4.1.15_2.1.0_ga +CURRENT_PATH := $(shell pwd) +obj-m := leddevice.o + +build: kernel_modules + +kernel_modules: + $(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) modules + +clean: + $(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) clean + + diff --git a/17_platform/ledApp.c b/17_platform/ledApp.c new file mode 100644 index 0000000000000000000000000000000000000000..05b1adcc81378cf278a2a8161ba082a9f986b5c6 --- /dev/null +++ b/17_platform/ledApp.c @@ -0,0 +1,46 @@ +#include "stdio.h" +#include "unistd.h" +#include "sys/types.h" +#include "fcntl.h" +#include "stdlib.h" +#include "string.h" + +#define LEDOFF 0 +#define LEDOON 0 + +int main(int argc,char *argv[]) +{ + int fd, retvalue; + char *filename; + unsigned char databuf[3]; + if (argc != 3) + { + printf("Error Usage!\r\n"); + return -1; + } + + filename = argv[1]; + + /* 打开led驱动 */ + fd = open(filename, O_RDWR); + if(fd < 0){ + printf("file %s open failed!\r\n", argv[1]); + return -1; + } + + databuf[0] = atoi(argv[2]); + retvalue = write(fd, databuf, sizeof(databuf)); + if(retvalue < 0 ){ + printf("LED Control Failed!\r\n"); + close(fd); + return -1; + } + + retvalue = close(fd); + if(retvalue < 0){ + printf("file %s close failed!\r\n", argv[1]); + return -1; + } + + return 0; +} diff --git a/17_platform/leddevice.c b/17_platform/leddevice.c new file mode 100644 index 0000000000000000000000000000000000000000..9e3091fd862e4c35959be5e8f5af911e434793e0 --- /dev/null +++ b/17_platform/leddevice.c @@ -0,0 +1,112 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* +* 寄存器地址定义 +*/ +#define CCM_CCGR1_BASE (0X020C406C) +#define SW_MUX_GPIO1_IO03_BASE (0X020E0068) +#define SW_PAD_GPIO1_IO03_BASE (0X020E02F4) +#define GPIO1_DR_BASE (0X0209C000) +#define GPIO1_GDIR_BASE (0X0209C004) +#define REGISTER_LENGTH 4 + +/* + @description : 释放 flatform 设备模块的时候此函数会执行 +* @param - dev : 要释放的设备 + +* @return 无 +*/ +static void led_release(struct device *dev) +{ + printk("led device released!\r\n"); +} + +static struct resource led_resources[] = { + [0] = { + .start = CCM_CCGR1_BASE, + .end = (CCM_CCGR1_BASE + REGISTER_LENGTH - 1), + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = SW_MUX_GPIO1_IO03_BASE, + .end = (SW_MUX_GPIO1_IO03_BASE + REGISTER_LENGTH - 1), + .flags = IORESOURCE_MEM, + }, + [2] = { + .start = SW_PAD_GPIO1_IO03_BASE, + .end = (SW_PAD_GPIO1_IO03_BASE + REGISTER_LENGTH - 1), + .flags = IORESOURCE_MEM, + }, + [3] = { + .start = GPIO1_DR_BASE, + .end = (GPIO1_DR_BASE + REGISTER_LENGTH - 1), + .flags = IORESOURCE_MEM, + }, + [4] = { + .start = GPIO1_GDIR_BASE, + .end = (GPIO1_GDIR_BASE + REGISTER_LENGTH - 1), + .flags = IORESOURCE_MEM, + }, +}; + + + +/* +* platform 设备结构体 +*/ + static struct platform_device leddevice = { + .name = "imx6ul-led", + .id = -1, + .dev = { + .release = &led_release, + }, + .num_resources = ARRAY_SIZE(led_resources), + .resource = led_resources, +}; + + +/* +* @description: 设备模块加载 +* @param : 无 +* @return : 无 +*/ +static int __init leddevice_init(void) +{ + return platform_device_register(&leddevice); +} + +/* +* @description : 设备模块注销 +* @param : 无 +* @return : 无 +*/ +static void __exit leddevice_exit(void) +{ + platform_device_unregister(&leddevice); +} + +module_init(leddevice_init); +module_exit(leddevice_exit); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("chaoliang"); \ No newline at end of file diff --git a/17_platform/leddriver.c b/17_platform/leddriver.c new file mode 100644 index 0000000000000000000000000000000000000000..509adf288f93513cbff612780c62615591ee68a0 --- /dev/null +++ b/17_platform/leddriver.c @@ -0,0 +1,220 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define LEDDEV_CNT 1 /* 设备号长度 */ +#define LEDDEV_NAME "platled" /* 设备名字 */ +#define LEDOFF 0 +#define LEDON 1 + + +/* 寄存器名 */ +static void __iomem *IMX6U_CCM_CCGR1; +static void __iomem *SW_MUX_GPIO1_IO03; +static void __iomem *SW_PAD_GPIO1_IO03; +static void __iomem *GPIO1_DR; +static void __iomem *GPIO1_GDIR; + + +/* leddev 设备结构体*/ +struct leddev_dev{ + dev_t devid; + struct cdev cdev; + struct class *class; + struct device *device; + int major; +}; + +struct leddev_dev leddev; /* led设备 */ + +void led0_switch(u8 sta) +{ + u32 val = 0; + if(sta == LEDON){ + val = readl(GPIO1_DR); + val &= ~(1 << 3); + writel(val, GPIO1_DR); + }else if(sta == LEDOFF){ + val = readl(GPIO1_DR); + val |= (1 << 3); + writel(val, GPIO1_DR); + } +} + + +static int led_open(struct inode *inode, struct file *filp) +{ + filp->private_data = &leddev; /* 设置私有数据 */ + return 0; +} + +static ssize_t led_write(struct file *filp, const char __user *buf, + size_t cnt, loff_t *offt) +{ + int retvalue; + unsigned char databuf[1]; + unsigned char ledstat; + retvalue = copy_from_user(databuf, buf, cnt); + if (retvalue < 0) + { + return -EFAULT; + } + + ledstat = databuf[0]; /* 获取状态 */ + if(ledstat == LEDON){ + led0_switch(LEDON); + } + else if(ledstat == LEDOFF){ + led0_switch(LEDOFF); + } + return 0; +} + +static struct file_operations led_fops = { + .owner = THIS_MODULE, + .open = led_open, + .write = led_write, +}; + +static int led_probe(struct platform_device *dev) +{ + int i = 0; + int ressize[5]; + u32 val = 0; + struct resource *ledsource[5]; + + printk("led driver and device has matched!\r\n"); + + /* 1、获取资源 */ + for (i = 0; i < 5;i++){ + ledsource[i] = platform_get_resource(dev, IORESOURCE_MEM, i); + if(!ledsource[i]){ + dev_err(&dev->dev, "No MEM resource for always on\r\n"); + printk("No MEM resource[%d] \r\n", i); + return -ENXIO; + } + ressize[i] = resource_size(ledsource[i]); + } + + /* 2、初始化LED */ + /* 寄存器地址映射 */ + IMX6U_CCM_CCGR1 = ioremap(ledsource[0]->start, ressize[0]); + SW_MUX_GPIO1_IO03 = ioremap(ledsource[1]->start, ressize[1]); + SW_PAD_GPIO1_IO03 = ioremap(ledsource[2]->start, ressize[2]); + GPIO1_DR = ioremap(ledsource[3]->start, ressize[3]); + GPIO1_GDIR = ioremap(ledsource[4]->start, ressize[4]); + + val = readl(IMX6U_CCM_CCGR1); + val &= ~(3 << 26); /* 清除以前的设置 */ + val |= (3 << 26); /* 设置新值 */ + writel(val, IMX6U_CCM_CCGR1); + + /* 设置 GPIO1_IO03 复用功能,将起复用为GPIO_IO03 */ + writel(5, SW_MUX_GPIO1_IO03); + writel(0x10B0, SW_PAD_GPIO1_IO03); + + /* 设置 GPIO1_IO03 为输出功能 */ + val = readl(GPIO1_GDIR); + val &= ~(1 << 3); /* 清除以前的设置 */ + val |= (1 << 3); + writel(val, GPIO1_GDIR); /* 设置为输出 */ + + + /* 默认关闭 LED1 */ + val = readl(GPIO1_DR); + val |= (1 << 3) ; + writel(val, GPIO1_DR); + + /* 注册字符设备驱动 */ + /*1、创建设备号 */ + + if (leddev.major) { + /* 定义了设备号*/ + leddev.devid = MKDEV(leddev.major, 0); + register_chrdev_region(leddev.devid, LEDDEV_CNT,LEDDEV_NAME); + } else { + /* 没有定义设备号*/ + alloc_chrdev_region(&leddev.devid, 0, LEDDEV_CNT,LEDDEV_NAME); + leddev.major = MAJOR(leddev.devid); + } + + /* 2、初始化 cdev */ + leddev.cdev.owner = THIS_MODULE; + cdev_init(&leddev.cdev, &led_fops); + + /* 3、添加一个 cdev */ + cdev_add(&leddev.cdev, leddev.devid, LEDDEV_CNT); + + /* 4、创建类 */ + leddev.class = class_create(THIS_MODULE, LEDDEV_NAME); + if (IS_ERR(leddev.class)) { + return PTR_ERR(leddev.class); + } + /* 5、创建设备 */ + leddev.device = device_create(leddev.class, NULL, leddev.devid,NULL, LEDDEV_NAME); + if (IS_ERR(leddev.device)) { + return PTR_ERR(leddev.device); + } + + return 0; +} + +static int led_remove(struct platform_device *dev) +{ + iounmap(IMX6U_CCM_CCGR1); + iounmap(SW_MUX_GPIO1_IO03); + iounmap(SW_PAD_GPIO1_IO03); + iounmap(GPIO1_DR); + iounmap(GPIO1_GDIR); + + cdev_del(&leddev.cdev); + unregister_chrdev_region(leddev.devid, LEDDEV_CNT); + device_destroy(leddev.class, leddev.devid); + class_destroy(leddev.class); + printk("led driver rmmove!\r\n"); + return 0; +} + +static struct platform_driver led_driver = +{ + .driver = { + .name = "imx6ul-led", + }, + .probe = led_probe, + .remove = led_remove, +}; + + + +static int __init leddriver_init(void) +{ + return platform_driver_register(&led_driver); +} + +static __exit leddriver_exit(void) +{ + platform_driver_unregister(&led_driver); +} + +module_init(leddriver_init); +module_exit(leddriver_exit); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("chaoliang"); \ No newline at end of file diff --git a/17_platform/platform.code-workspace b/17_platform/platform.code-workspace new file mode 100644 index 0000000000000000000000000000000000000000..a563c858bedf0385cd9bbd6d0395651af865f705 --- /dev/null +++ b/17_platform/platform.code-workspace @@ -0,0 +1,41 @@ +{ + "folders": [ + { + "path": "." + } + ], + "settings": { + "files.associations": { + "gpio.h": "c", + "*.tcc": "c", + "ioctl.h": "c", + "fstream": "c", + "types.h": "c", + "kernel.h": "c", + "ide.h": "c", + "uaccess.h": "c", + "atomic.h": "c", + "interrupt.h": "c", + "hardirq.h": "c", + "irq.h": "c", + "delay.h": "c", + "init.h": "c", + "module.h": "c", + "cdev.h": "c", + "of_address.h": "c", + "of_gpio.h": "c", + "errno.h": "c", + "device.h": "c", + "of.h": "c", + "of_irq.h": "c", + "timer.h": "c", + "stdlib.h": "c", + "stdio.h": "c", + "driver.h": "c", + "select.h": "c", + "fcntl.h": "c", + "signal.h": "c" + } + + } +} \ No newline at end of file