121 lines
2.7 KiB
C
121 lines
2.7 KiB
C
|
||
#include <linux/kernel.h>
|
||
#include <linux/module.h>
|
||
#include <linux/slab.h>
|
||
#include <linux/init.h>
|
||
#include <linux/fs.h>
|
||
#include <linux/delay.h>
|
||
#include <linux/poll.h>
|
||
#include <linux/mutex.h>
|
||
#include <linux/wait.h>
|
||
#include <linux/uaccess.h>
|
||
#include <asm/io.h>
|
||
#include <linux/device.h>
|
||
|
||
static int major;
|
||
static struct class *led_class;
|
||
|
||
/* registers */
|
||
// RCC_PLL4CR地址:0x50000000 + 0x894
|
||
static volatile unsigned int *RCC_PLL4CR;
|
||
|
||
// RCC_MP_AHB4ENSETR 地址:0x50000000 + 0xA28
|
||
static volatile unsigned int *RCC_MP_AHB4ENSETR;
|
||
|
||
// GPIOA_MODER 地址:0x50002000 + 0x00
|
||
static volatile unsigned int *GPIOA_MODER;
|
||
|
||
// GPIOA_BSRR 地址: 0x50002000 + 0x18
|
||
static volatile unsigned int *GPIOA_BSRR;
|
||
|
||
static ssize_t led_write(struct file *filp, const char __user *buf,
|
||
size_t count, loff_t *ppos)
|
||
{
|
||
char val;
|
||
/* copy_from_user : get data from app */
|
||
copy_from_user(&val, buf, 1);
|
||
|
||
/* to set gpio register: out 1/0 */
|
||
if (val)
|
||
{
|
||
/* set gpa10 to let led on */
|
||
*GPIOA_BSRR = (1<<26);
|
||
}
|
||
else
|
||
{
|
||
|
||
/* set gpa10 to let led off */
|
||
*GPIOA_BSRR = (1<<10);
|
||
}
|
||
return 1;
|
||
}
|
||
|
||
static int led_open(struct inode *inode, struct file *filp)
|
||
{
|
||
/* enalbe PLL4, it is clock source for all gpio */
|
||
*RCC_PLL4CR |= (1<<0);
|
||
while ((*RCC_PLL4CR & (1<<1)) == 0);
|
||
|
||
/* enable gpioA */
|
||
*RCC_MP_AHB4ENSETR |= (1<<0);
|
||
|
||
/*
|
||
* configure gpa10 as gpio
|
||
* configure gpio as output
|
||
*/
|
||
*GPIOA_MODER &= ~(3<<20);
|
||
*GPIOA_MODER |= (1<<20);
|
||
|
||
return 0;
|
||
}
|
||
|
||
static struct file_operations led_fops = {
|
||
.owner = THIS_MODULE,
|
||
.write = led_write,
|
||
.open = led_open,
|
||
};
|
||
|
||
/* 入口函数 */
|
||
static int __init led_init(void)
|
||
{
|
||
printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
|
||
|
||
major = register_chrdev(0, "100ask_led", &led_fops);
|
||
|
||
/* ioremap(base_phy, size); */
|
||
// RCC_PLL4CR地址:0x50000000 + 0x894
|
||
RCC_PLL4CR = ioremap(0x50000000 + 0x894, 4);
|
||
|
||
// RCC_MP_AHB4ENSETR 地址:0x50000000 + 0xA28
|
||
RCC_MP_AHB4ENSETR = ioremap(0x50000000 + 0xA28, 4);
|
||
|
||
// GPIOA_MODER 地址:0x50002000 + 0x00
|
||
GPIOA_MODER = ioremap(0x50002000 + 0x00, 4);
|
||
|
||
// GPIOA_BSRR 地址: 0x50002000 + 0x18
|
||
GPIOA_BSRR = ioremap(0x50002000 + 0x18, 4);
|
||
|
||
led_class = class_create(THIS_MODULE, "myled");
|
||
device_create(led_class, NULL, MKDEV(major, 0), NULL, "myled"); /* /dev/myled */
|
||
|
||
return 0;
|
||
}
|
||
|
||
static void __exit led_exit(void)
|
||
{
|
||
iounmap(RCC_PLL4CR);
|
||
iounmap(RCC_MP_AHB4ENSETR);
|
||
iounmap(GPIOA_MODER);
|
||
iounmap(GPIOA_BSRR);
|
||
|
||
device_destroy(led_class, MKDEV(major, 0));
|
||
class_destroy(led_class);
|
||
|
||
unregister_chrdev(major, "100ask_led");
|
||
}
|
||
|
||
module_init(led_init);
|
||
module_exit(led_exit);
|
||
MODULE_LICENSE("GPL");
|
||
|
||
|