Compare commits
5 Commits
738d2ffa8e
...
main
Author | SHA1 | Date | |
---|---|---|---|
9595b72bc1 | |||
8145e1c790 | |||
49d5847980 | |||
34ea87ded0 | |||
48e9f86d33 |
@ -1,31 +1,31 @@
|
||||
NAME = counter
|
||||
OBJS = init.o leds.o ls7366r.o trigger.o io.o
|
||||
KDIR := /lib/modules/$(shell uname -r)/build
|
||||
DTC_FLAGS := -@ -I dts -O dtb
|
||||
|
||||
obj-m += $(NAME).o
|
||||
$(NAME)-objs := init.o leds.o ls7366r.o trigger.o
|
||||
$(NAME)-objs := $(OBJS)
|
||||
|
||||
all: $(NAME).ko $(NAME).dtbo
|
||||
echo Builded Device Tree Overlay and kernel module
|
||||
|
||||
$(NAME).ko: init.c leds.c ls7366r.c trigger.c
|
||||
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
|
||||
$(NAME).ko:
|
||||
make -C $(KDIR) M=$(PWD) modules
|
||||
|
||||
$(NAME).dtbo: $(NAME).dts
|
||||
dtc -@ -I dts -O dtb -o $@ $<
|
||||
dtc $(DTC_FLAGS) -o $@ $<
|
||||
|
||||
clean:
|
||||
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
|
||||
make -C $(KDIR) M=$(PWD) clean
|
||||
rm -rf $(NAME).dtbo
|
||||
|
||||
load:
|
||||
sudo dtoverlay -d . $(NAME).dtbo
|
||||
@echo "Overlay loaded"
|
||||
sudo insmod ./$(NAME).ko
|
||||
@echo "LKM loaded"
|
||||
sudo dtoverlay -d . $(NAME).dtbo && echo "Overlay loaded"
|
||||
sudo insmod ./$(NAME).ko && echo "LKM loaded"
|
||||
|
||||
unload:
|
||||
sudo rmmod ./$(NAME).ko
|
||||
@echo "LKM unloaded"
|
||||
sudo dtoverlay -R $(NAME)
|
||||
@echo "Overlay unloaded"
|
||||
sudo rmmod ./$(NAME).ko && echo "LKM unloaded"
|
||||
sudo dtoverlay -R $(NAME) && echo "Overlay unloaded"
|
||||
|
||||
list:
|
||||
sudo dtoverlay -l
|
||||
|
26
driver/counter_io_calls.h
Normal file
26
driver/counter_io_calls.h
Normal file
@ -0,0 +1,26 @@
|
||||
#ifndef _COUNTER_IO_CALLS_H_
|
||||
#define _COUNTER_IO_CALLS_H_
|
||||
|
||||
#ifndef __KERNEL__
|
||||
#include <stdint.h>
|
||||
#define u64 uint64_t
|
||||
#define u32 uint32_t
|
||||
#endif
|
||||
|
||||
#include "leds_codes.h"
|
||||
|
||||
struct observation {
|
||||
u64 ts_sec;
|
||||
u64 ts_nsec;
|
||||
u32 value;
|
||||
};
|
||||
|
||||
struct led_cmd {
|
||||
enum led_color_e color;
|
||||
enum led_state_e state;
|
||||
};
|
||||
|
||||
#define LED_CMD _IOW('l', 'c', struct led_cmd *);
|
||||
|
||||
|
||||
#endif /* _COUNTER_IO_CALLS_H_ */
|
@ -6,6 +6,8 @@
|
||||
#include "ls7366r.h"
|
||||
#include "trigger.h"
|
||||
#include "leds.h"
|
||||
#include "io.h"
|
||||
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Wolfgang Hottgenroth");
|
||||
@ -15,6 +17,12 @@ MODULE_DESCRIPTION("Driver for the MainsCnt measurement hat");
|
||||
|
||||
/* module loading and unloading */
|
||||
static int __init my_init(void) {
|
||||
printk("counter - Loading IO subsystem...\n");
|
||||
if (io_init()) {
|
||||
printk("counter - Error! Could not load IO subsystem\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
printk("counter - Loading the leds driver...\n");
|
||||
if(platform_driver_register(&leds_driver)) {
|
||||
printk("counter - Error! Could not load leds driver\n");
|
||||
@ -45,6 +53,9 @@ static void __exit my_exit(void) {
|
||||
|
||||
printk("counter - Unloading the interrupt driver...\n");
|
||||
platform_driver_unregister(&interrupt_driver);
|
||||
|
||||
printk("counter - Unloading IO subsystem...\n");
|
||||
io_exit();
|
||||
}
|
||||
|
||||
module_init(my_init);
|
||||
|
53
driver/io.c
Normal file
53
driver/io.c
Normal file
@ -0,0 +1,53 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/ioctl.h>
|
||||
|
||||
#include "io.h"
|
||||
#include "counter_io_calls.h"
|
||||
|
||||
|
||||
static dev_t io_device_no;
|
||||
static struct class *io_device_class;
|
||||
static struct cdev io_device;
|
||||
|
||||
#define DRIVER_NAME "cntiodev"
|
||||
#define DRIVER_CLASS "CounterClass"
|
||||
|
||||
|
||||
|
||||
static int io_open(struct inode *device_file, struct file *instance) {
|
||||
printk("counter - Info! io open was called\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int io_close(struct inode *device_file, struct file *instance) {
|
||||
printk("counter - Info! io close was called\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static struct file_operations fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = io_open,
|
||||
.release = io_close,
|
||||
};
|
||||
|
||||
int io_init(void) {
|
||||
printk("counter - Info! io init\n");
|
||||
|
||||
if (alloc_chrdev_region(&io_device_no, 0, 1, DRIVER_NAME) < 0) {
|
||||
printk("counter - ERROR! Device No. could not be allocated\n");
|
||||
return -1;
|
||||
}
|
||||
printk("counter - Info! Device No. Major: %d, Minor: %d was registered!\n", my_device_nr >> 20, my_device_nr & 0xfffff);
|
||||
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void io_exit(void) {
|
||||
}
|
||||
|
8
driver/io.h
Normal file
8
driver/io.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef _IO_H_
|
||||
#define _IO_H_
|
||||
|
||||
|
||||
int io_init(void);
|
||||
void io_exit(void);
|
||||
|
||||
#endif /* _IO_H_ */
|
@ -6,6 +6,8 @@
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
|
||||
#include "leds.h"
|
||||
|
||||
|
||||
/* leds stuff */
|
||||
static int dt_leds_probe(struct platform_device *pdev);
|
||||
@ -72,3 +74,26 @@ static void dt_leds_remove(struct platform_device *pdev) {
|
||||
gpiod_put(red_led);
|
||||
gpiod_put(blue_led);
|
||||
}
|
||||
|
||||
void led_ctrl(enum led_color_e color, enum led_state_e state) {
|
||||
struct gpio_desc *led;
|
||||
switch (color) {
|
||||
case e_RED:
|
||||
led = red_led;
|
||||
break;
|
||||
case e_BLUE:
|
||||
led = blue_led;
|
||||
break;
|
||||
}
|
||||
int st;
|
||||
switch (state) {
|
||||
case e_ON:
|
||||
st = 1;
|
||||
break;
|
||||
case e_OFF:
|
||||
st = 0;
|
||||
break;
|
||||
}
|
||||
gpiod_set_value(led, st);
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,11 @@
|
||||
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include "leds_codes.h"
|
||||
|
||||
|
||||
extern struct platform_driver leds_driver;
|
||||
|
||||
void led_ctrl(enum led_color_e color, enum led_state_e state);
|
||||
|
||||
#endif /* _LEDS_H_ */
|
||||
|
7
driver/leds_codes.h
Normal file
7
driver/leds_codes.h
Normal file
@ -0,0 +1,7 @@
|
||||
#ifndef _LEDS_CODES_H_
|
||||
#define _LEDS_CODES_H_
|
||||
|
||||
enum led_color_e { e_RED, e_BLUE };
|
||||
enum led_state_e { e_ON, e_OFF };
|
||||
|
||||
#endif /* _LEDS_CODES_H_ */
|
@ -9,8 +9,10 @@
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/timekeeping.h>
|
||||
|
||||
#include "ls7366r.h"
|
||||
#include "leds.h"
|
||||
|
||||
|
||||
|
||||
@ -45,14 +47,14 @@ struct counter_irq_data {
|
||||
struct work_struct work;
|
||||
u64 timestamp;
|
||||
struct spi_device *client;
|
||||
u64 last_timestamp;
|
||||
struct timespec64 current_timestamp;
|
||||
struct timespec64 last_timestamp;
|
||||
u32 last_value;
|
||||
};
|
||||
static struct counter_irq_data counter_irq_wq_data;
|
||||
|
||||
static void counter_worker(struct work_struct *work) {
|
||||
struct counter_irq_data *data = container_of(work, struct counter_irq_data, work);
|
||||
u64 ts = data->timestamp;
|
||||
|
||||
u32 counter_value;
|
||||
int ret = read_otr(data->client, &counter_value);
|
||||
@ -64,16 +66,20 @@ static void counter_worker(struct work_struct *work) {
|
||||
|
||||
if (data->last_value) {
|
||||
u32 period = counter_value - data->last_value;
|
||||
u64 duration = ts - data->last_timestamp;
|
||||
printk("counter - Info! ts = %llu, duration = %llu, period = %u\n", ts, duration, period);
|
||||
printk("counter %lld.%09lu %u\n",
|
||||
(s64)((data->current_timestamp).tv_sec),
|
||||
((data->current_timestamp).tv_nsec),
|
||||
period);
|
||||
|
||||
|
||||
}
|
||||
data->last_value = counter_value;
|
||||
data->last_timestamp = ts;
|
||||
data->last_timestamp = data->current_timestamp;
|
||||
}
|
||||
|
||||
// ISR
|
||||
static irqreturn_t counter_isr(int irq, void *dev_id) {
|
||||
counter_irq_wq_data.timestamp = ktime_get();
|
||||
ktime_get_real_ts64(&counter_irq_wq_data.current_timestamp);
|
||||
schedule_work(&counter_irq_wq_data.work);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
@ -86,7 +92,6 @@ static int dt_interrupt_probe(struct platform_device *pdev) {
|
||||
INIT_WORK(&counter_irq_wq_data.work, counter_worker);
|
||||
counter_irq_wq_data.client = ls7366r_spi_client;
|
||||
counter_irq_wq_data.last_value = 0;
|
||||
counter_irq_wq_data.last_timestamp = 0;
|
||||
|
||||
counter_interrupt = gpiod_get(dev, "intr", GPIOD_IN);
|
||||
if (IS_ERR(counter_interrupt)) {
|
||||
|
Reference in New Issue
Block a user