From ed8c28d0e9815bf7df44a6c75c49de3f6b5bced3 Mon Sep 17 00:00:00 2001 From: Andrew Robinson Date: Sun, 23 Dec 2012 17:10:04 -0500 Subject: [PATCH] checkpoint on implementation of better layer implementation --- Makefile | 2 +- cc2520.h | 70 ++++++------------------------- interface.c | 116 ++++++++++++++++++++++++++++++++++------------------ interface.h | 10 +++++ lpl.c | 39 ++++++++++++++++++ lpl.h | 12 ++++++ module.c | 5 +++ platform.c | 2 + platform.h | 10 +++++ radio.c | 13 +++--- radio.h | 33 +++++++++++++++ sack.c | 35 ++++++++++------ sack.h | 12 ++++++ 13 files changed, 241 insertions(+), 118 deletions(-) create mode 100644 interface.h create mode 100644 lpl.h create mode 100644 platform.h create mode 100644 radio.h create mode 100644 sack.h diff --git a/Makefile b/Makefile index 43fda06..a511f5b 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ DRIVER = spike TARGET = cc2520 -OBJS = radio.o interface.o module.o platform.o sack.o +OBJS = radio.o interface.o module.o platform.o sack.o lpl.o obj-m += $(TARGET).o cc2520-objs = radio.o interface.o module.o platform.o sack.o diff --git a/cc2520.h b/cc2520.h index dd5c3bb..87639d1 100644 --- a/cc2520.h +++ b/cc2520.h @@ -6,8 +6,6 @@ #include #include -#include "radio.h" - ////////////////////////////// // Configuration for driver ///////////////////////////// @@ -55,6 +53,7 @@ #define SPI_BUS_CS0 0 #define SPI_BUS_SPEED 500000 #define SPI_BUFF_SIZE 256 +#define PKT_BUFF_SIZE 127 // Defaults for Radio Operation #define CC2520_DEF_CHANNEL 26 @@ -64,84 +63,39 @@ #define CC2520_DEF_EXT_ADDR 0x01 +// XOSC Period in nanoseconds. +#define CC2520_XOSC_PERIOD 31 + ////////////////////////////// // Structs and definitions ///////////////////////////// -// XOSC Period in nanoseconds. -#define CC2520_XOSC_PERIOD 31 +struct cc2520_interface { + int (*tx)(u8 *buf, u8 len); + void (*tx_done)(u8 status); + void (*rx_done)(u8 *buf, u8 len); +}; -#define PKT_BUFF_SIZE 127 +/// +// KEEP THESE AROUND FOR LEGACY REASONS: +// struct cc2520_gpio_state { unsigned int fifop_irq; unsigned int sfd_irq; }; -enum cc2520_radio_state_enum { - CC2520_RADIO_STATE_IDLE, - CC2520_RADIO_STATE_RX, - CC2520_RADIO_STATE_TX -}; - struct cc2520_state { // Hardware struct cc2520_gpio_state gpios; - - //////////////////////////////////// - // Character device and buffers - //////////////////////////////////// - unsigned int major; - u8 *tx_buf_c; - u8 *rx_buf_c; - size_t tx_pkt_len; - - // Allows for only a single rx or tx - // to occur simultaneously. - struct semaphore tx_sem; - struct semaphore rx_sem; - - // Used by the character driver - // to indicate when a blocking tx - // or rx has completed. - struct semaphore tx_done_sem; - struct semaphore rx_done_sem; - - // Results, stored by the callbacks - int tx_result; - int rx_result; - - //////////////////////////////////// - // Spi device and buffers - ////////////////////////////////// struct spi_device *spi_device; - - //////////////////////////////////// - // Radio parameters - ////////////////////////////////// // CURRENTLY UNUSED: struct work_struct work; /* for deferred work */ struct workqueue_struct *wq; }; -// Platform -int cc2520_plat_gpio_init(void); -void cc2520_plat_gpio_free(void); - -int cc2520_plat_spi_init(void); -void cc2520_plat_spi_free(void); - -// Interface -int cc2520_interface_init(void); -void cc2520_interface_free(void); -void cc2520_interface_write_cb(int result); - -// Software ACK Layer -void cc2520_sack_tx(u8 *buf, u8 len); - extern struct cc2520_state state; - extern const char cc2520_name[]; ////////////////////////////// diff --git a/interface.c b/interface.c index bf5dd71..73ac719 100644 --- a/interface.c +++ b/interface.c @@ -6,8 +6,47 @@ #include #include #include + #include "ioctl.h" #include "cc2520.h" +#include "interface.h" +#include "radio.h" + +struct cc2520_interface *interface_bottom; + +static unsigned int major; +static u8 *tx_buf_c; +static u8 *rx_buf_c; +static size_t tx_pkt_len; + +// Allows for only a single rx or tx +// to occur simultaneously. +static struct semaphore tx_sem; +static struct semaphore rx_sem; + +// Used by the character driver +// to indicate when a blocking tx +// or rx has completed. +static struct semaphore tx_done_sem; +static struct semaphore rx_done_sem; + +// Results, stored by the callbacks +static int tx_result; +static int rx_result; + +/////////////////////// +// Interface callbacks +/////////////////////// +void cc2520_interface_tx_done(u8 status) +{ + tx_result = status; + up(&tx_done_sem); +} + +void cc2520_interface_rx_done(u8 *buf, u8 len) +{ + +} // Should accept a 6LowPAN frame, no longer than 127 bytes. static ssize_t interface_write( @@ -21,12 +60,12 @@ static ssize_t interface_write( // Step 1: Get an exclusive lock on writing to the // radio. if (filp->f_flags & O_NONBLOCK) { - result = down_trylock(&state.tx_sem); + result = down_trylock(&tx_sem); if (result) return -EAGAIN; } else { - result = down_interruptible(&state.tx_sem); + result = down_interruptible(&tx_sem); if (result) return -ERESTARTSYS; } @@ -34,39 +73,33 @@ static ssize_t interface_write( // Step 2: Copy the packet to the incoming buffer. pkt_len = min(len, (size_t)127); - if (copy_from_user(state.tx_buf_c, in_buf, pkt_len)) { + if (copy_from_user(tx_buf_c, in_buf, pkt_len)) { result = -EFAULT; goto error; } - state.tx_pkt_len = pkt_len; + tx_pkt_len = pkt_len; // Step 3: Launch off into sending this packet, // wait for an asynchronous callback to occur in // the form of a semaphore. printk(KERN_INFO "[cc2520] - performing software ack test %d.\n", pkt_len); - cc2520_sack_tx(state.tx_buf_c, pkt_len); - result = down_interruptible(&state.tx_done_sem); + interface_bottom->tx(tx_buf_c, pkt_len); + result = down_interruptible(&tx_done_sem); if (result) return -ERESTARTSYS; // Step 4: Finally return and allow other callers to write // packets. printk(KERN_INFO "[cc2520] - returned from sack cb.\n"); - up(&state.tx_sem); + up(&tx_sem); - return state.tx_result ? state.tx_result : pkt_len; + return tx_result ? tx_result : pkt_len; error: - up(&state.tx_sem); + up(&tx_sem); return -EFAULT; } -void cc2520_interface_write_cb(int result) -{ - state.tx_result = result; - up(&state.tx_done_sem); -} - static ssize_t interface_read(struct file *filp, char __user *buff, size_t count, loff_t *offp) { @@ -164,38 +197,41 @@ int cc2520_interface_init() { int result; - sema_init(&state.tx_sem, 1); - sema_init(&state.rx_sem, 1); + interface_bottom->tx_done = cc2520_interface_tx_done; + interface_bottom->rx_done = cc2520_interface_rx_done; + + sema_init(&tx_sem, 1); + sema_init(&rx_sem, 1); - sema_init(&state.tx_done_sem, 0); - sema_init(&state.rx_done_sem, 0); + sema_init(&tx_done_sem, 0); + sema_init(&rx_done_sem, 0); - state.tx_buf_c = kmalloc(PKT_BUFF_SIZE, GFP_KERNEL); - if (!state.tx_buf_c) { + tx_buf_c = kmalloc(PKT_BUFF_SIZE, GFP_KERNEL); + if (!tx_buf_c) { result = -EFAULT; goto error; } - state.rx_buf_c = kmalloc(PKT_BUFF_SIZE, GFP_KERNEL); - if (!state.rx_buf_c) { + rx_buf_c = kmalloc(PKT_BUFF_SIZE, GFP_KERNEL); + if (!rx_buf_c) { result = -EFAULT; goto error; } - state.major = register_chrdev(0, cc2520_name, &fops); - printk(KERN_INFO "[cc2520] - Char interface registered on %d\n", state.major); + major = register_chrdev(0, cc2520_name, &fops); + printk(KERN_INFO "[cc2520] - Char interface registered on %d\n", major); return 0; error: - if (state.rx_buf_c) { - kfree(state.rx_buf_c); - state.rx_buf_c = 0; + if (rx_buf_c) { + kfree(rx_buf_c); + rx_buf_c = 0; } - if (state.tx_buf_c) { - kfree(state.tx_buf_c); - state.tx_buf_c = 0; + if (tx_buf_c) { + kfree(tx_buf_c); + tx_buf_c = 0; } return result; @@ -205,25 +241,25 @@ void cc2520_interface_free() { int result; - result = down_interruptible(&state.tx_sem); + result = down_interruptible(&tx_sem); if (result) { printk("[cc2520] - critical error occurred on free."); } - result = down_interruptible(&state.rx_sem); + result = down_interruptible(&rx_sem); if (result) { printk("[cc2520] - critical error occurred on free."); } - unregister_chrdev(state.major, cc2520_name); + unregister_chrdev(major, cc2520_name); - if (state.rx_buf_c) { - kfree(state.rx_buf_c); - state.rx_buf_c = 0; + if (rx_buf_c) { + kfree(rx_buf_c); + rx_buf_c = 0; } - if (state.tx_buf_c) { - kfree(state.tx_buf_c); - state.tx_buf_c = 0; + if (tx_buf_c) { + kfree(tx_buf_c); + tx_buf_c = 0; } } \ No newline at end of file diff --git a/interface.h b/interface.h new file mode 100644 index 0000000..1c52574 --- /dev/null +++ b/interface.h @@ -0,0 +1,10 @@ +#ifndef INTERFACE_H +#define iNTERFACE_H + +// Interface +int cc2520_interface_init(void); +void cc2520_interface_free(void); + +extern struct cc2520_interface *interface_bottom; + +#endif \ No newline at end of file diff --git a/lpl.c b/lpl.c index e69de29..112036f 100644 --- a/lpl.c +++ b/lpl.c @@ -0,0 +1,39 @@ +#include +#include "lpl.h" +#include "cc2520.h" + +struct cc2520_interface *lpl_top; +struct cc2520_interface *lpl_bottom; + +static int cc2520_lpl_tx(u8 * buf, u8 len); +static void cc2520_lpl_tx_done(u8 status); +static void cc2520_lpl_rx_done(u8 *buf, u8 len); + +int cc2520_lpl_init() +{ + lpl_top->tx = cc2520_lpl_tx; + lpl_bottom->tx_done = cc2520_lpl_tx_done; + lpl_bottom->rx_done = cc2520_lpl_rx_done; + + return 0; +} + +void cc2520_lpl_free() +{ + +} + +static int cc2520_lpl_tx(u8 * buf, u8 len) +{ + return lpl_bottom->tx(buf, len); +} + +static void cc2520_lpl_tx_done(u8 status) +{ + lpl_top->tx_done(status); +} + +static void cc2520_lpl_rx_done(u8 *buf, u8 len) +{ + lpl_top->rx_done(buf, len); +} \ No newline at end of file diff --git a/lpl.h b/lpl.h new file mode 100644 index 0000000..ab726a3 --- /dev/null +++ b/lpl.h @@ -0,0 +1,12 @@ +#ifndef LPL_H +#define LPL_H + +#include "cc2520.h" + +extern struct cc2520_interface *lpl_top; +extern struct cc2520_interface *lpl_bottom; + +int cc2520_lpl_init(void); +void cc2520_lpl_free(void); + +#endif \ No newline at end of file diff --git a/module.c b/module.c index 1bad90c..ef47617 100644 --- a/module.c +++ b/module.c @@ -10,6 +10,11 @@ #include #include "cc2520.h" +#include "radio.h" +#include "platform.h" +#include "lpl.h" +#include "interface.h" +#include "sack.h" #define DRIVER_AUTHOR "Andrew Robinson " #define DRIVER_DESC "A driver for the CC2520 radio. Be afraid." diff --git a/platform.c b/platform.c index f780801..1b4b065 100644 --- a/platform.c +++ b/platform.c @@ -11,6 +11,8 @@ #include #include "cc2520.h" +#include "radio.h" +#include "platform.h" ////////////////////////// // SPI Stuff diff --git a/platform.h b/platform.h new file mode 100644 index 0000000..30cd252 --- /dev/null +++ b/platform.h @@ -0,0 +1,10 @@ +#ifndef PLATFORM_H +#define PLATFORM_H + +// Platform +int cc2520_plat_gpio_init(void); +void cc2520_plat_gpio_free(void); +int cc2520_plat_spi_init(void); +void cc2520_plat_spi_free(void); + +#endif \ No newline at end of file diff --git a/radio.c b/radio.c index 1a0302a..3bfce14 100644 --- a/radio.c +++ b/radio.c @@ -15,8 +15,13 @@ #include #include "cc2520.h" +#include "radio.h" #include "radio_config.h" +static u16 short_addr; +static u64 extended_addr; +static u16 pan_id; +static u8 channel; static struct spi_message msg; static struct spi_transfer tsfer; @@ -24,11 +29,6 @@ static struct spi_transfer tsfer; static u8 *tx_buf; static u8 *rx_buf; -static u16 short_addr; -static u64 extended_addr; -static u16 pan_id; -static u8 channel; - static u8 *tx_buf_r; static u8 *rx_buf_r; @@ -40,7 +40,6 @@ static u64 sfd_nanos_ts; static spinlock_t radio_sl; static int radio_state; - static cc2520_status_t cc2520_radio_strobe(u8 cmd); static void cc2520_radio_writeRegister(u8 reg, u8 value); static void cc2520_radio_writeMemory(u16 mem_addr, u8 *value, u8 len); @@ -248,7 +247,7 @@ void cc2520_radio_fifop_occurred() //queue_work(wq, &work); } -void cc2520_radio_reset() +void cc2520_radio_reset(void) { } diff --git a/radio.h b/radio.h new file mode 100644 index 0000000..306ddb5 --- /dev/null +++ b/radio.h @@ -0,0 +1,33 @@ +#ifndef RADIO_H +#define RADIO_H + +#include +#include /* Semaphore */ +#include +#include + +enum cc2520_radio_state_enum { + CC2520_RADIO_STATE_IDLE, + CC2520_RADIO_STATE_RX, + CC2520_RADIO_STATE_TX +}; + +// Radio Initializers +int cc2520_radio_init(void); +void cc2520_radio_free(void); + +// Radio Commands +void cc2520_radio_start(void); +void cc2520_radio_on(void); +void cc2520_radio_off(void); +void cc2520_radio_set_channel(int channel); +void cc2520_radio_set_address(u16 short_addr, u64 extended_addr, u16 pan_id); +void cc2520_radio_set_txpower(u8 power); + +// Radio Interrupt Callbacks +void cc2520_radio_sfd_occurred(u64 nano_timestamp); +void cc2520_radio_fifop_occurred(void); + +int cc2520_radio_tx(u8 *buf, u8 len); + +#endif \ No newline at end of file diff --git a/sack.c b/sack.c index ade9ed4..f9c6a48 100644 --- a/sack.c +++ b/sack.c @@ -1,28 +1,39 @@ +#include +#include "sack.h" +#include "cc2520.h" +struct cc2520_interface *sack_top; +struct cc2520_interface *sack_bottom; -#include "cc2520.h" +static int cc2520_sack_tx(u8 * buf, u8 len); +static void cc2520_sack_tx_done(u8 status); +static void cc2520_sack_rx_done(u8 *buf, u8 len); -// Context: process -void cc2520_sack_tx(u8 *buf, u8 len) +int cc2520_sack_init() { - // send the packet - // setup hr_timer - cc2520_interface_write_cb(0); + sack_top->tx = cc2520_sack_tx; + sack_bottom->tx_done = cc2520_sack_tx_done; + sack_bottom->rx_done = cc2520_sack_rx_done; + + return 0; } -void cc2520_sack_subtx() +void cc2520_sack_free() { } -// Context: interrupt -void cc2520_sack_subrx() +static int cc2520_sack_tx(u8 * buf, u8 len) { - + return sack_bottom->tx(buf, len); } -void cc2520_sack_rx_cb() +static void cc2520_sack_tx_done(u8 status) { + sack_top->tx_done(status); +} - +static void cc2520_sack_rx_done(u8 *buf, u8 len) +{ + sack_top->rx_done(buf, len); } \ No newline at end of file diff --git a/sack.h b/sack.h new file mode 100644 index 0000000..1d98ee9 --- /dev/null +++ b/sack.h @@ -0,0 +1,12 @@ +#ifndef SACK_H +#define SACK_H + +#include "cc2520.h" + +extern struct cc2520_interface *sack_top; +extern struct cc2520_interface *sack_bottom; + +int cc2520_sack_init(void); +void cc2520_sack_free(void); + +#endif \ No newline at end of file