I am creating a kernel module for controlling the GPIOs for learning purpose. I have written the code such that if anyone sends “4,1” to /proc/lll-gpio, pin 37 should turn on.
I am developing a kernel module to control GPIOs for educational purposes. My module is designed so that sending the string “4,1” to **/proc/lll-gpio**
should turn on GPIO pin 37. As I don’t have any previous experience writing kernel modules and accessing registers, I decided to read the values from the register first to verify that I am indeed accessing the correct the memory locations.
To do this, I used the Jetson.GPIO Python library to toggle pin 37 and then checked the register values using my kernel module. My goal was to ensure that my kernel module was correctly accessing the relevant registers by observing changes in register values corresponding to GPIO operation.
However, I am encountering an issue: toggling GPIO pin 37 using the Jetson.GPIO library does not seem to produce any change in the register values read by my kernel module. GPIO pin 37 is indeed toggling but the values read by my kernel module are having no change.
Could let me know what I am doing wrong here.
#include <asm/io.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#define LLL_MAX_USER_SIZE 1024
#define GPIO_ADDR 0x6000d000
#define GPIO_CONTROLLER_1_OFFSET 0x0
#define GPIO_CONTROLLER_2_OFFSET 0x100
#define GPIO_CONTROLLER_3_OFFSET 0x200
#define GPIO_CONTROLLER_4_OFFSET 0x300
#define GPIO_CONTROLLER_5_OFFSET 0x400
#define GPIO_CONTROLLER_6_OFFSET 0x500
#define GPIO_CONTROLLER_7_OFFSET 0x600
#define GPIO_PORT_1_OFFSET 0x00
#define GPIO_PORT_2_OFFSET 0x04
#define GPIO_PORT_3_OFFSET 0x08
#define GPIO_PORT_4_OFFSET 0x0C
#define GPIO_REG_GPIO_CNF 0x00
#define GPIO_REG_GPIO_OE 0x10
#define GPIO_REG_GPIO_OUT 0x20
#define GPIO_REG_GPIO_IN 0x30
#define GPIO_REG_GPIO_INT_STAT 0x40
#define GPIO_REG_GPIO_ENB 0x50
#define GPIO_REG_GPIO_LVL 0x60
#define GPIO_REG_GPIO_CLR 0x70
static unsigned int *gpio_registers = NULL;
static struct proc_dir_entry *lll_proc = NULL;
static char data_buffer[LLL_MAX_USER_SIZE];
ssize_t lll_read(struct file *file, char __user *user, size_t size, loff_t *off);
ssize_t lll_write(struct file *file, const char __user *user, size_t size, loff_t *off);
static void gpio_on(unsigned int pin) {
volatile unsigned int *GPIO_CNF_REG = gpio_registers + GPIO_CONTROLLER_1_OFFSET + GPIO_PORT_2_OFFSET +
GPIO_REG_GPIO_CNF;
volatile unsigned int *GPIO_OE_REG = gpio_registers + GPIO_CONTROLLER_1_OFFSET + GPIO_PORT_2_OFFSET +
GPIO_REG_GPIO_OE;
volatile unsigned int *GPIO_ENB_REG = gpio_registers + GPIO_CONTROLLER_1_OFFSET + GPIO_PORT_2_OFFSET +
GPIO_REG_GPIO_ENB;
volatile unsigned int *GPIO_IN_REG = gpio_registers + GPIO_CONTROLLER_1_OFFSET + GPIO_PORT_2_OFFSET +
GPIO_REG_GPIO_IN;
// *GPIO_CNF_REG = *GPIO_CNF_REG | 1 << 4;
// *GPIO_ENB_REG = *GPIO_ENB_REG | 1 << 4;
// *GPIO_OE_REG = *GPIO_OE_REG | 1 << 4;
printk("GPIO CNG addr : %X\n", *GPIO_CNF_REG);
printk("GPIO OE addr : %X\n", *GPIO_OE_REG);
printk("GPIO ENB addr : %X\n", *GPIO_ENB_REG);
printk("GPIO IN addr : %X\n", *GPIO_IN_REG );
}
static void gpio_off(unsigned int pin) {
}
ssize_t lll_read(struct file *file, char __user *user, size_t size, loff_t *off) {
int ret = 0;
ret = copy_to_user(user, "Hello!\n", 7);
return 7;
}
ssize_t lll_write(struct file *file, const char __user *user, size_t size, loff_t *off) {
int ret = 0;
unsigned int pin = UINT_MAX;
unsigned int value = UINT_MAX;
memset(data_buffer, 0x0, sizeof(data_buffer));
if (size > LLL_MAX_USER_SIZE)
size = LLL_MAX_USER_SIZE;
ret = copy_from_user(data_buffer, user, size);
printk("You said '%s' !", data_buffer);
if (sscanf(data_buffer, "%d,%d", &pin, &value) != 2) {
printk("Improper format\n");
}
printk("You said pin %d value %d!\n", pin, value);
if (pin > 0 && pin < 8) {
gpio_on(pin);
}
return size;
}
static const struct file_operations lll_proc_fops = {
.read = lll_read,
.write = lll_write,
};
static int __init gpio_driver_init(void) {
printk("Welcome to my driver!\n");
gpio_registers = (int *)ioremap(GPIO_ADDR, 1024);
if (gpio_registers == NULL) {
printk("Failed to initialize GPIO");
return -1;
}
printk("Successfully GPIO");
// Create proc file
lll_proc = proc_create("lll-gpio", 0666, NULL, &lll_proc_fops);
if (lll_proc == NULL)
return -1;
return 0;
}
static void __exit gpio_driver_exit(void) {
printk("Leaving to my driver!\n");
iounmap(gpio_registers);
proc_remove(lll_proc);
return;
}
module_init(gpio_driver_init);
module_exit(gpio_driver_exit);
MODULE_LICENSE("GPL");
Read value as seen in dmesg
[ +0.000007] GPIO CNG addr : 40
[ +0.000005] GPIO OE addr : 0
[ +0.000005] GPIO ENB addr : 0
[ +0.000004] GPIO IN addr : 0