diff --git a/Makefile b/Makefile index fd86c49..418d29a 100644 --- a/Makefile +++ b/Makefile @@ -2,10 +2,10 @@ #CROSS_COMPILE=arm-linux-gnueabi-gcc TARGET = cc2520 -OBJS = radio.o interface.o +OBJS = radio.o interface.o module.o platform.o obj-m += $(TARGET).o -cc2520-objs = radio.o interface.o +cc2520-objs = radio.o interface.o module.o platform.o # Set this is your linux kernel checkout. KDIR := /home/androbin/linux-rpi-3.2.27 diff --git a/cc2520.h b/cc2520.h index edc64c5..37a585a 100644 --- a/cc2520.h +++ b/cc2520.h @@ -1,3 +1,6 @@ +#ifndef CC2520_H +#define CC2520_H + ////////////////////////////// // Configuration for driver ///////////////////////////// @@ -52,9 +55,18 @@ struct cc2520_gpioState { }; struct cc2520_state { + // Hardware struct cc2520_gpioState gpios; + + // Character Device + unsigned int major; + }; int cc2520_setupGpioPins(void); -void cc2520_freeGpioPins(void); \ No newline at end of file +void cc2520_freeGpioPins(void); + +extern struct cc2520_state state; + +#endif \ No newline at end of file diff --git a/cc2520_load b/cc2520_load new file mode 100644 index 0000000..5e5d031 --- /dev/null +++ b/cc2520_load @@ -0,0 +1,24 @@ +#!/bin/sh + +module="cc2520" +device="radio" +mode="664" + +# invoke insmod with all arguments we were passed +# and use a pathname, as newer modutils don't look in . by default +/sbin/insmod -f ./$module.o $* || exit 1 + +# remove stale nodes +rm -f /dev/${device}[0-3] + +major=`awk "\\$2==\"$module\" {print \\$1}" /proc/devices` + +mknod /dev/${device}0 c $major 0 + +# give appropriate group/permissions, and change the group. +# Not all distributions have staff; some have "wheel" instead. +group="staff" +grep '^staff:' /etc/group > /dev/null || group="wheel" + +chgrp $group /dev/${device}0 +chmod $mode /dev/${device}0 \ No newline at end of file diff --git a/interface.c b/interface.c index c03c57c..7a7d569 100644 --- a/interface.c +++ b/interface.c @@ -1,2 +1,6 @@ #include "cc2520.h" +#include +#include +#include +#include "cc2520.h" diff --git a/module.c b/module.c new file mode 100644 index 0000000..19d7390 --- /dev/null +++ b/module.c @@ -0,0 +1,96 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cc2520.h" + +#define DRIVER_AUTHOR "Andrew Robinson " +#define DRIVER_DESC "A driver for the CC2520 radio. Be afraid." + +struct cc2520_state state; + +struct hrtimer utimer; +int irqNumber = 0; +int pinValue = 0; + +static enum hrtimer_restart callbackFunc(struct hrtimer *timer) +{ + ktime_t kt; + + gpio_set_value(23, pinValue == 1); + pinValue = !pinValue; + + // Create a 100uS time period. + kt=ktime_set(0,100000); + hrtimer_forward_now(&utimer, kt); + + return HRTIMER_RESTART; +} + + +int init_module() +{ + ktime_t kt; + int err = 0; + + printk(KERN_INFO "Loading CC2520 Kernel Module v0.01...\n"); + + err = cc2520_setupGpioPins(); + if (err) { + printk(KERN_INFO "[CC2520] - Error setting up GPIO pins. Aborting."); + return 1; + } + + ////////////////////////// + // GPIO Interrupt Init + //err = gpio_request_one(22, GPIOF_DIR_IN, NULL); + //err = gpio_request_one(23, GPIOF_DIR_OUT, NULL); + //printk(KERN_INFO "Requesting GPIO Pin 22: %d\n", err); + + //irqNumber = gpio_to_irq(22); + //printk(KERN_INFO "Requesting IRQ: %d\n", irqNumber); + + //if (irqNumber < 0) { + // printk("Unable to get irq number."); + // return 1; + //} + + //request_irq(irqNumber, handler, IRQF_TRIGGER_FALLING, "theInterrupt", NULL); + + //////////////////////// + // HFTimer Test + // Create a 100uS time period. + + kt=ktime_set(10,100000); + + //printk(KERN_ALERT "HRTTIMER inserted\n"); + + //utimer = (struct hrtimer *)kmalloc(sizeof(struct hrtimer),GFP_KERNEL); + + + hrtimer_init(&utimer,CLOCK_MONOTONIC, HRTIMER_MODE_REL); + + utimer.function = &callbackFunc; // callback + + hrtimer_start(&utimer, kt, HRTIMER_MODE_REL); + + //printk(KERN_ALERT "HRTTIMER STARTED\n"); + + return 0; +} + +void cleanup_module() +{ + cc2520_freeGpioPins(); + hrtimer_cancel(&utimer); // + printk(KERN_INFO "Unloading CC2520 Kernel Module...\n"); +} + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); \ No newline at end of file diff --git a/platform.c b/platform.c new file mode 100644 index 0000000..91e4f09 --- /dev/null +++ b/platform.c @@ -0,0 +1,129 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cc2520.h" + +////////////////////////// +// Interrupt Handles +///////////////////////// + +static irqreturn_t cc2520_sfdHandler(int irq, void *dev_id) +{ + printk(KERN_INFO "[CC2520] - sfd interrupt occurred"); + return IRQ_HANDLED; +} + +static irqreturn_t cc2520_fifopHandler(int irq, void *dev_id) +{ + printk(KERN_INFO "[CC2520] - fifop interrupt occurred"); + return IRQ_HANDLED; +} + +////////////////////////////// +// Interface Initialization +////////////////////////////// + +// Sets up the GPIO pins needed for the CC2520 +// and initializes any interrupt handlers needed. +int cc2520_setupGpioPins() +{ + int err = 0; + int irq = 0; + + // Setup GPIO In/Out + err = gpio_request_one(CC2520_FIFO, GPIOF_DIR_IN, NULL); + if (err) + goto fail; + + err = gpio_request_one(CC2520_FIFOP, GPIOF_DIR_IN, NULL); + if (err) + goto fail; + + err = gpio_request_one(CC2520_CCA, GPIOF_DIR_IN, NULL); + if (err) + goto fail; + + err = gpio_request_one(CC2520_SFD, GPIOF_DIR_IN, NULL); + if (err) + goto fail; + + err = gpio_request_one(CC2520_RESET, GPIOF_DIR_IN, NULL); + if (err) + goto fail; + + err = gpio_request_one(CC2520_DEBUG_0, GPIOF_DIR_OUT, NULL); + if (err) + goto fail; + + err = gpio_request_one(CC2520_DEBUG_1, GPIOF_DIR_OUT, NULL); + if (err) + goto fail; + + gpio_set_value(CC2520_DEBUG_0, 0); + gpio_set_value(CC2520_DEBUG_1, 0); + + // Setup FIFOP Interrupt + irq = gpio_to_irq(CC2520_FIFOP); + if (irq < 0) { + err = irq; + goto fail; + } + + err = request_irq( + irq, + cc2520_fifopHandler, + IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, + "fifopHandler", + NULL + ); + if (err) + goto fail; + state.gpios.fifopIrq = irq; + + // Setup SFD Interrupt + irq = gpio_to_irq(CC2520_SFD); + if (irq < 0) { + err = irq; + goto fail; + } + + err = request_irq( + irq, + cc2520_sfdHandler, + IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, + "sfdHandler", + NULL + ); + if (err) + goto fail; + state.gpios.sfdIrq = irq; + + return err; + + fail: + printk(KERN_INFO "Failed to init GPIOs\n"); + cc2520_freeGpioPins(); + return err; +} + +void cc2520_freeGpioPins() +{ + gpio_free(CC2520_CLOCK); + gpio_free(CC2520_FIFO); + gpio_free(CC2520_FIFOP); + gpio_free(CC2520_CCA); + gpio_free(CC2520_SFD); + gpio_free(CC2520_RESET); + + gpio_free(CC2520_DEBUG_0); + gpio_free(CC2520_DEBUG_1); + + free_irq(state.gpios.fifopIrq, NULL); + free_irq(state.gpios.sfdIrq, NULL); +} \ No newline at end of file diff --git a/radio.c b/radio.c index 613894c..b99f3d9 100644 --- a/radio.c +++ b/radio.c @@ -7,208 +7,4 @@ #include #include -#include "cc2520.h" - -#define DRIVER_AUTHOR "Andrew Robinson " -#define DRIVER_DESC "A driver for the CC2520 radio. Be afraid." - -struct cc2520_state state; - -int irqNumber = 0; -int pinValue = 0; - -struct hrtimer utimer; - -////////////////////////// -// Interrupt Handles -///////////////////////// - -static irqreturn_t cc2520_sfdHandler(int irq, void *dev_id) -{ - printk(KERN_INFO "[CC2520] - sfd interrupt occurred"); - return IRQ_HANDLED; -} - -static irqreturn_t cc2520_fifopHandler(int irq, void *dev_id) -{ - printk(KERN_INFO "[CC2520] - fifop interrupt occurred"); - return IRQ_HANDLED; -} - -static enum hrtimer_restart callbackFunc(struct hrtimer *timer) -{ - ktime_t kt; - - gpio_set_value(23, pinValue == 1); - pinValue = !pinValue; - - // Create a 100uS time period. - kt=ktime_set(0,100000); - hrtimer_forward_now(&utimer, kt); - - return HRTIMER_RESTART; -} - -////////////////////////////// -// Interface Initialization -////////////////////////////// - -// Sets up the GPIO pins needed for the CC2520 -// and initializes any interrupt handlers needed. -int cc2520_setupGpioPins() -{ - int err = 0; - int irq = 0; - - // Setup GPIO In/Out - err = gpio_request_one(CC2520_FIFO, GPIOF_DIR_IN, NULL); - if (err) - goto fail; - - err = gpio_request_one(CC2520_FIFOP, GPIOF_DIR_IN, NULL); - if (err) - goto fail; - - err = gpio_request_one(CC2520_CCA, GPIOF_DIR_IN, NULL); - if (err) - goto fail; - - err = gpio_request_one(CC2520_SFD, GPIOF_DIR_IN, NULL); - if (err) - goto fail; - - err = gpio_request_one(CC2520_DEBUG_0, GPIOF_DIR_OUT, NULL); - if (err) - goto fail; - - err = gpio_request_one(CC2520_DEBUG_1, GPIOF_DIR_OUT, NULL); - if (err) - goto fail; - - gpio_set_value(CC2520_DEBUG_0, 0); - gpio_set_value(CC2520_DEBUG_1, 0); - - // Setup FIFOP Interrupt - irq = gpio_to_irq(CC2520_FIFOP); - if (irq < 0) { - err = irq; - goto fail; - } - - err = request_irq( - irq, - cc2520_fifopHandler, - IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, - "fifopHandler", - NULL - ); - if (err) - goto fail; - state.gpios.fifopIrq = irq; - - // Setup SFD Interrupt - irq = gpio_to_irq(CC2520_SFD); - if (irq < 0) { - err = irq; - goto fail; - } - - err = request_irq( - irq, - cc2520_sfdHandler, - IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, - "sfdHandler", - NULL - ); - if (err) - goto fail; - state.gpios.sfdIrq = irq; - - return err; - - fail: - printk(KERN_INFO "Failed to init GPIOs\n"); - cc2520_freeGpioPins(); - return err; -} - -void cc2520_freeGpioPins() -{ - gpio_free(CC2520_CLOCK); - gpio_free(CC2520_FIFO); - gpio_free(CC2520_FIFOP); - gpio_free(CC2520_CCA); - gpio_free(CC2520_SFD); - - gpio_free(CC2520_DEBUG_0); - gpio_free(CC2520_DEBUG_1); - - free_irq(state.gpios.fifopIrq, NULL); - free_irq(state.gpios.sfdIrq, NULL); -} - -////////////////////////////// -// Module Init/Cleanup -////////////////////////////// - -int init_module() -{ - ktime_t kt; - int err = 0; - - printk(KERN_INFO "Loading CC2520 Kernel Module v0.01...\n"); - - err = cc2520_setupGpioPins(); - if (err) { - printk(KERN_INFO "[CC2520] - Error setting up GPIO pins. Aborting."); - return 1; - } - - ////////////////////////// - // GPIO Interrupt Init - //err = gpio_request_one(22, GPIOF_DIR_IN, NULL); - //err = gpio_request_one(23, GPIOF_DIR_OUT, NULL); - //printk(KERN_INFO "Requesting GPIO Pin 22: %d\n", err); - - //irqNumber = gpio_to_irq(22); - //printk(KERN_INFO "Requesting IRQ: %d\n", irqNumber); - - //if (irqNumber < 0) { - // printk("Unable to get irq number."); - // return 1; - //} - - //request_irq(irqNumber, handler, IRQF_TRIGGER_FALLING, "theInterrupt", NULL); - - //////////////////////// - // HFTimer Test - // Create a 100uS time period. - - kt=ktime_set(10,100000); - - //printk(KERN_ALERT "HRTTIMER inserted\n"); - - //utimer = (struct hrtimer *)kmalloc(sizeof(struct hrtimer),GFP_KERNEL); - - - hrtimer_init(&utimer,CLOCK_MONOTONIC, HRTIMER_MODE_REL); - - utimer.function = &callbackFunc; // callback - - hrtimer_start(&utimer, kt, HRTIMER_MODE_REL); - - //printk(KERN_ALERT "HRTTIMER STARTED\n"); - - return 0; -} - -void cleanup_module() -{ - cc2520_freeGpioPins(); - hrtimer_cancel(&utimer); // - printk(KERN_INFO "Unloading CC2520 Kernel Module...\n"); -} - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); +#include "cc2520.h" \ No newline at end of file