From df8c4a5ae6c8d7933dc17ca192f1697b646a13fb Mon Sep 17 00:00:00 2001 From: Oleg Hahm <oleg@hobbykeller.org> Date: Thu, 22 Aug 2013 23:34:10 +0200 Subject: [PATCH] added board dependent part of the cc2420 for TelosB --- telosb/driver_cc2420.c | 247 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 247 insertions(+) create mode 100644 telosb/driver_cc2420.c diff --git a/telosb/driver_cc2420.c b/telosb/driver_cc2420.c new file mode 100644 index 0000000000..67d926855f --- /dev/null +++ b/telosb/driver_cc2420.c @@ -0,0 +1,247 @@ + /* + * driver_cc2420.c - Implementation of the board dependent cc2420 functions. + * Copyright (C) 2005, 2006, 2007, 2008 by Thomas Hillebrandt and Heiko Will + * Copyright (C) 2013 Oliver Hahm <oliver.hahm@inria.fr> + * + * This source code is licensed under the GNU Lesser General Public License, + * Version 2. See the file LICENSE for more details. + */ + +#include <stdio.h> + +#include <board.h> +#include <cpu.h> +#include <irq.h> +#include <hwtimer.h> + +#include <cc2420.h> + +#define ENABLE_DEBUG (1) +#include "debug.h" + +#define CC2420_RESETn_PIN 0x40 +#define CC2420_VREGEN_PIN 0x20 + +#define CC2420_FIFOP_PIN 0x01 +#define CC2420_GIO0_PIN 0x08 +#define CC2420_GIO1_PIN 0x10 +#define CC2420_CCA_PIN 0x40 +#define CC2420_SFD_PIN 0x02 + +#define CC2420_FIFOP (P1IN & CC2420_FIFOP_PIN) /* FIFOP <-> packet interrupt (P1.0) */ +#define CC2420_GIO0 (P1IN & CC2420_GIO0_PIN) /* FIFO <-> GIO0 - RX data available (P1.3) */ +#define CC2420_GIO1 (P1IN & CC2420_GIO1_PIN) /* CCA <-> GIO1 - clear channel (P1.4) */ +#define CC2420_SFD (P4IN & CC2420_SFD_PIN) /* SFD <-> TBL - start frame delimiter (P4.1) */ + +#define CC2420_CS_LOW (P4OUT &= ~0x04) /* P4.2 */ +#define CC2420_CS_HIGH (P4OUT |= 0x04) + +volatile int abort_count; +volatile int retry_count = 0; + +void cc2420_reset(void) +{ + P4OUT |= CC2420_VREGEN_PIN; + P4OUT &= ~CC2420_RESETn_PIN; + hwtimer_wait(500); + P4OUT |= CC2420_RESETn_PIN; +} + +void cc2420_gio0_enable(void) +{ + P1IFG &= ~CC2420_GIO0_PIN; /* Clear IFG for GIO0 */ + P1IE |= CC2420_GIO0_PIN; /* Enable interrupt for GIO0 */ +} + +void cc2420_gio0_disable(void) +{ + P1IE &= ~CC2420_GIO0_PIN; /* Disable interrupt for GIO0 */ + P1IFG &= ~CC2420_GIO0_PIN; /* Clear IFG for GIO0 */ +} + +void cc2420_gio1_enable(void) +{ + P1IFG &= ~CC2420_GIO1_PIN; /* Clear IFG for GIO1 */ + P1IE |= CC2420_GIO1_PIN; /* Enable interrupt for GIO1 */ +} + +void cc2420_gio1_disable(void) +{ + P1IE &= ~CC2420_GIO1_PIN; /* Disable interrupt for GIO1 */ + P1IFG &= ~CC2420_GIO1_PIN; /* Clear IFG for GIO1 */ +} + +void cc2420_before_send(void) +{ + /* Disable SFD interrupt before sending packet */ + /* However this is not used atm */ +} + +void cc2420_after_send(void) +{ + /* Enable SFD interrupt after sending packet */ + /* However this is not used atm */ +} + + +int cc2420_get_gio0(void) +{ + return CC2420_GIO0; +} + +int cc2420_get_gio1(void) +{ + return CC2420_GIO1; +} + +int cc2420_get_sfd(void) +{ + return CC2420_SFD; +} + +void cc2420_spi_cs(void) +{ + CC2420_CS_LOW; +} + +uint8_t cc2420_txrx(uint8_t data) +{ + /* Ensure TX Buf is empty */ + long c = 0; + IFG1 &= ~UTXIFG0; + IFG1 &= ~URXIFG0; + U0TXBUF = data; + while(!(IFG1 & UTXIFG0)) { + if (c++ == 1000000) { + puts("cc2420_txrx alarm()"); + } + } + /* Wait for Byte received */ + c = 0; + while(!(IFG1 & URXIFG0)) { + if (c++ == 1000000) { + puts("cc2420_txrx alarm()"); + } + } + return U0RXBUF; +} + + +void cc2420_spi_select(void) +{ + CC2420_CS_LOW; +} + +void cc2420_spi_unselect(void) { + CC2420_CS_HIGH; +} + +void cc2420_init_interrupts(void) +{ + unsigned int state = disableIRQ(); /* Disable all interrupts */ + P1SEL &= ~CC2420_FIFOP_PIN; /* must be <> 1 to use interrupts */ + + P1IE &= ~CC2420_FIFOP_PIN; /* Disable interrupt for GIO0 */ + P1IFG &= ~CC2420_FIFOP_PIN; /* Clear IFG for GIO0 */ + restoreIRQ(state); /* Enable all interrupts */ +} + +void cc2420_spi_init(void) +{ + /* Switch off async UART */ + while(!(U0TCTL & TXEPT)); /* Wait for empty UxTXBUF register */ + IE1 &= ~(URXIE0 + UTXIE0); /* Disable USART0 receive&transmit interrupt */ + ME1 &= ~(UTXE0 + URXE0); + + /* configure SPI-related pins */ + P3SEL |= 0x0E; /* P3.1 - SIMO mode, P3.2 - SOMI mode, P3.3 - SCL mode */ + P3DIR |= 0x0A; /* P3.1 and P3.3 as output */ + P3DIR &= ~(0x04); /* P3.2 as input for SOMI */ + P4OUT |= 0x04; /* P4.2 radio CS, hold high */ + P4DIR |= 0x04; /* P4.2 radio CS, output */ + + /* Keep peripheral in reset state */ + U0CTL = SWRST; + + /* 8-bit SPI Master 3-pin mode, with SMCLK as clock source */ + /* CKPL works also, but not CKPH+CKPL or none of them!! */ + U0CTL |= CHAR + SYNC + MM; + U0TCTL = CKPH + SSEL1 + SSEL0 + STC + TXEPT;; + + /* Ignore clockrate argument for now, just use clock source/2 */ + /* SMCLK = 8 MHz */ + U0BR0 = 0x02; /* Ensure baud rate >= 2 */ + U0BR1 = 0x00; + U0MCTL = 0x00; /* No modulation */ + U0RCTL = 0x00; /* Reset Receive Control Register */ + + /* Enable SPI mode */ + ME1 |= USPIE0; + + /* Release for operation */ + U0CTL &= ~SWRST; +} + +/* + * CC1100 receive interrupt + */ +interrupt (PORT1_VECTOR) __attribute__ ((naked)) cc2420_isr(void){ + __enter_isr(); + /* Check IFG */ + if ((P1IFG & CC2420_FIFOP_PIN) != 0) { + P1IFG &= ~CC2420_FIFOP_PIN; + if (cc2420_get_gio0()) { + cc2420_rx_irq(); + DEBUG("rx interrupt"); + } + else { + cc2420_rxoverflow_irq(); + DEBUG("[CC2420] rxfifo overflow"); + } + } + + else { + puts("cc2420_isr(): unexpected IFG!"); + /* Should not occur - only GDO1 and GIO1 interrupts are enabled */ + } + __exit_isr(); +} + +/** +\brief TimerB CCR1-6 interrupt service routine (taken from OpenWSN) +*/ +interrupt (TIMERB0_VECTOR) __attribute__ ((naked)) radiotimer_isr(void) { + uint16_t tbiv_local; + + /* reading TBIV returns the value of the highest pending interrupt flag */ + /* and automatically resets that flag. We therefore copy its value to the */ + /* tbiv_local local variable exactly once. If there is more than one */ + /* interrupt pending, we will reenter this function after having just left */ + /* it. */ + tbiv_local = TBIV; + + switch (tbiv_local) { + case 0x0002: /* CCR1 fires */ + if (TBCCTL1 & CCI) { + /* SFD pin is high */ + DEBUG("start of a frame\n"); + } + else { + /* SFD pin is low */ + DEBUG("end of a frame\n"); + } + break; + case 0x0004: /* CCR2 fires */ + break; + case 0x0006: /* CCR3 fires */ + break; + case 0x0008: /* CCR4 fires */ + break; + case 0x000a: /* CCR5 fires */ + break; + case 0x000c: /* CCR6 fires */ + break; + case 0x000e: /* timer overflow */ + break; + } +} -- GitLab