├── deps.sh ├── .gitignore ├── user-mode-program ├── blink-led └── blink-led.c ├── Makefile └── lll-gpio-driver.c /deps.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | sudo apt-get install gcc raspberrypi-kernel-headers 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .*.cmd 2 | *.o 3 | *.ko 4 | *.mod 5 | *.mod.c 6 | *.order 7 | Module.symvers 8 | -------------------------------------------------------------------------------- /user-mode-program/blink-led: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lowleveltv/lll-gpio-driver/HEAD/user-mode-program/blink-led -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | obj-m += lll-gpio-driver.o 2 | 3 | KDIR = /lib/modules/$(shell uname -r)/build 4 | 5 | all: 6 | make -C $(KDIR) M=$(shell pwd) modules 7 | 8 | clean: 9 | make -C $(KDIR) M=$(shell pwd) clean 10 | -------------------------------------------------------------------------------- /user-mode-program/blink-led.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int main () 8 | { 9 | int f = open("/proc/lll-gpio", O_RDWR); 10 | 11 | while (1) 12 | { 13 | write(f, "21,1", 4); 14 | usleep(500000); 15 | write(f, "21,0", 4); 16 | usleep(500000); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /lll-gpio-driver.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | #define LLL_MAX_USER_SIZE 1024 11 | 12 | #define BCM2837_GPIO_ADDRESS 0x3F200000 13 | #define BCM2711_GPIO_ADDRESS 0xfe200000 14 | 15 | static struct proc_dir_entry *lll_proc = NULL; 16 | 17 | static char data_buffer[LLL_MAX_USER_SIZE+1] = {0}; 18 | 19 | static unsigned int *gpio_registers = NULL; 20 | 21 | static void gpio_pin_on(unsigned int pin) 22 | { 23 | unsigned int fsel_index = pin/10; 24 | unsigned int fsel_bitpos = pin%10; 25 | unsigned int* gpio_fsel = gpio_registers + fsel_index; 26 | unsigned int* gpio_on_register = (unsigned int*)((char*)gpio_registers + 0x1c); 27 | 28 | *gpio_fsel &= ~(7 << (fsel_bitpos*3)); 29 | *gpio_fsel |= (1 << (fsel_bitpos*3)); 30 | *gpio_on_register |= (1 << pin); 31 | 32 | return; 33 | } 34 | 35 | static void gpio_pin_off(unsigned int pin) 36 | { 37 | unsigned int *gpio_off_register = (unsigned int*)((char*)gpio_registers + 0x28); 38 | *gpio_off_register |= (1< LLL_MAX_USER_SIZE) 55 | { 56 | size = LLL_MAX_USER_SIZE; 57 | } 58 | 59 | if (copy_from_user(data_buffer, user, size)) 60 | return 0; 61 | 62 | printk("Data buffer: %s\n", data_buffer); 63 | 64 | if (sscanf(data_buffer, "%d,%d", &pin, &value) != 2) 65 | { 66 | printk("Inproper data format submitted\n"); 67 | return size; 68 | } 69 | 70 | if (pin > 21 || pin < 0) 71 | { 72 | printk("Invalid pin number submitted\n"); 73 | return size; 74 | } 75 | 76 | if (value != 0 && value != 1) 77 | { 78 | printk("Invalid on/off value\n"); 79 | return size; 80 | } 81 | 82 | printk("You said pin %d, value %d\n", pin, value); 83 | if (value == 1) 84 | { 85 | gpio_pin_on(pin); 86 | } else if (value == 0) 87 | { 88 | gpio_pin_off(pin); 89 | } 90 | 91 | return size; 92 | } 93 | 94 | static const struct proc_ops lll_proc_fops = 95 | { 96 | .proc_read = lll_read, 97 | .proc_write = lll_write, 98 | }; 99 | 100 | 101 | static int __init gpio_driver_init(void) 102 | { 103 | printk("Welcome to my driver!\n"); 104 | 105 | gpio_registers = (int*)ioremap(BCM2837_GPIO_ADDRESS, PAGE_SIZE); 106 | if (gpio_registers == NULL) 107 | { 108 | printk("Failed to map GPIO memory to driver\n"); 109 | return -1; 110 | } 111 | 112 | printk("Successfully mapped in GPIO memory\n"); 113 | 114 | // create an entry in the proc-fs 115 | lll_proc = proc_create("lll-gpio", 0666, NULL, &lll_proc_fops); 116 | if (lll_proc == NULL) 117 | { 118 | return -1; 119 | } 120 | 121 | return 0; 122 | } 123 | 124 | static void __exit gpio_driver_exit(void) 125 | { 126 | printk("Leaving my driver!\n"); 127 | iounmap(gpio_registers); 128 | proc_remove(lll_proc); 129 | return; 130 | } 131 | 132 | module_init(gpio_driver_init); 133 | module_exit(gpio_driver_exit); 134 | 135 | MODULE_LICENSE("GPL"); 136 | MODULE_AUTHOR("Low Level Learning"); 137 | MODULE_DESCRIPTION("Test of writing drivers for RASPI"); 138 | MODULE_VERSION("1.0"); 139 | --------------------------------------------------------------------------------