Contributions from Michael Baar:
CC1020 o Turns off only after transmission has ended and not in between o Using events for DMA takes too long. It should use a callback when DMA finishes to turn off the transmit mode as early as possible. Core/UART o Added profiling and energest initialization o Changed low-power mode from LPM1 to LPM3
This commit is contained in:
parent
b1d87bf0d3
commit
665c58fd2a
4 changed files with 267 additions and 163 deletions
|
@ -47,21 +47,21 @@
|
||||||
|
|
||||||
#include "sys/procinit.h"
|
#include "sys/procinit.h"
|
||||||
#include "sys/autostart.h"
|
#include "sys/autostart.h"
|
||||||
#include "sys/rtimer.h"
|
|
||||||
|
|
||||||
#include "dev/adc.h"
|
#include "dev/adc.h"
|
||||||
#include "dev/dma.h"
|
|
||||||
#include "dev/sht11.h"
|
|
||||||
#include "dev/slip.h"
|
|
||||||
|
|
||||||
#include "net/mac/nullmac.h"
|
#include "net/mac/nullmac.h"
|
||||||
#include "net/mac/xmac.h"
|
#include "net/mac/xmac.h"
|
||||||
|
|
||||||
|
#include "dev/slip.h"
|
||||||
|
|
||||||
|
extern volatile bool uart_edge;
|
||||||
|
|
||||||
SENSORS(NULL);
|
SENSORS(NULL);
|
||||||
|
|
||||||
#if WITH_UIP
|
#if WITH_UIP
|
||||||
static struct uip_fw_netif slipif =
|
static struct uip_fw_netif slipif =
|
||||||
{UIP_FW_NETIF(172,16,0,1, 255,255,255,0, slip_send)};
|
{UIP_FW_NETIF(192,168,1,2, 255,255,255,255, slip_send)};
|
||||||
#else
|
#else
|
||||||
int
|
int
|
||||||
putchar(int c)
|
putchar(int c)
|
||||||
|
@ -75,7 +75,6 @@ static void
|
||||||
set_rime_addr(void)
|
set_rime_addr(void)
|
||||||
{
|
{
|
||||||
rimeaddr_t addr;
|
rimeaddr_t addr;
|
||||||
|
|
||||||
addr.u16[0] = node_id;
|
addr.u16[0] = node_id;
|
||||||
rimeaddr_set_node_addr(&addr);
|
rimeaddr_set_node_addr(&addr);
|
||||||
}
|
}
|
||||||
|
@ -83,12 +82,29 @@ set_rime_addr(void)
|
||||||
static void
|
static void
|
||||||
msb_ports_init(void)
|
msb_ports_init(void)
|
||||||
{
|
{
|
||||||
P1DIR = 0x00; P1SEL = 0x00; P1OUT = 0x00;
|
P1SEL = 0x00;
|
||||||
P2DIR = 0x1A; P2SEL = 0x00; P2OUT = 0x18;
|
P1OUT = 0x00;
|
||||||
P3DIR = 0x21; P3SEL = 0x00; P3OUT = 0x09;
|
P1DIR = 0x00;
|
||||||
P4DIR = 0x00; P4SEL = 0x00; P4OUT = 0x07;
|
|
||||||
P5DIR = 0xFD; P5SEL = 0x0E; P5OUT = 0xF9;
|
P2SEL = 0x00;
|
||||||
P6DIR = 0xC8; P6SEL = 0x07; P6OUT = 0x00;
|
P2OUT = 0x18;
|
||||||
|
P2DIR = 0x1A;
|
||||||
|
|
||||||
|
P3SEL = 0x00;
|
||||||
|
P3OUT = 0x09;
|
||||||
|
P3DIR = 0x21;
|
||||||
|
|
||||||
|
P4SEL = 0x00;
|
||||||
|
P4OUT = 0x00;
|
||||||
|
P4DIR = 0x00;
|
||||||
|
|
||||||
|
P5SEL = 0x0E;
|
||||||
|
P5OUT = 0xF9;
|
||||||
|
P5DIR = 0xFD;
|
||||||
|
|
||||||
|
P6SEL = 0x07;
|
||||||
|
P6OUT = 0x00;
|
||||||
|
P6DIR = 0xC8;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -99,12 +115,10 @@ main(void)
|
||||||
/* Platform-specific initialization. */
|
/* Platform-specific initialization. */
|
||||||
msb_ports_init();
|
msb_ports_init();
|
||||||
adc_init();
|
adc_init();
|
||||||
dma_init();
|
|
||||||
|
|
||||||
clock_init();
|
clock_init();
|
||||||
leds_init();
|
leds_init();
|
||||||
leds_on(LEDS_ALL);
|
leds_on(LEDS_ALL);
|
||||||
sht11_init();
|
|
||||||
|
|
||||||
// low level
|
// low level
|
||||||
irq_init();
|
irq_init();
|
||||||
|
@ -123,55 +137,101 @@ main(void)
|
||||||
slip_arch_init(BAUD2UBR(115200));
|
slip_arch_init(BAUD2UBR(115200));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
rtimer_init();
|
|
||||||
ctimer_init();
|
|
||||||
|
|
||||||
energest_init();
|
|
||||||
node_id_restore();
|
|
||||||
|
|
||||||
/* System services */
|
/* System services */
|
||||||
process_start(&etimer_process, NULL);
|
process_start(&etimer_process, NULL);
|
||||||
#if 0
|
//process_start(&sensors_process, NULL);
|
||||||
process_start(&sensors_process, NULL);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Radio driver */
|
//cc1020_init(cc1020_config_19200);
|
||||||
cc1020_init(cc1020_config_19200);
|
|
||||||
|
// network configuration
|
||||||
|
node_id_restore();
|
||||||
|
|
||||||
/* Network configuration */
|
|
||||||
#if WITH_UIP
|
#if WITH_UIP
|
||||||
uip_init();
|
uip_init();
|
||||||
uip_sethostaddr(&slipif.ipaddr);
|
uip_sethostaddr(&slipif.ipaddr);
|
||||||
uip_setnetmask(&slipif.netmask);
|
uip_setnetmask(&slipif.netmask);
|
||||||
/* Point-to-point, no default router. */
|
uip_fw_default(&slipif); /* Point2point, no default router. */
|
||||||
uip_fw_default(&slipif);
|
|
||||||
tcpip_set_forwarding(0);
|
tcpip_set_forwarding(0);
|
||||||
|
|
||||||
process_start(&tcpip_process, NULL);
|
|
||||||
process_start(&uip_fw_process, NULL);
|
|
||||||
process_start(&slip_process, NULL);
|
|
||||||
#endif /* WITH_UIP */
|
#endif /* WITH_UIP */
|
||||||
|
|
||||||
nullmac_init(&cc1020_driver);
|
nullmac_init(&cc1020_driver);
|
||||||
rime_init(&nullmac_driver);
|
rime_init(&nullmac_driver);
|
||||||
set_rime_addr();
|
set_rime_addr();
|
||||||
|
|
||||||
printf(CONTIKI_VERSION_STRING " started. Node id %d.\n", node_id);
|
#if WITH_UIP
|
||||||
|
process_start(&tcpip_process, NULL);
|
||||||
|
process_start(&uip_fw_process, NULL); /* Start IP output */
|
||||||
|
process_start(&slip_process, NULL);
|
||||||
|
#endif /* WITH_UIP */
|
||||||
|
|
||||||
printf("Autostarting processes\n");
|
#if PROFILE_CONF_ON
|
||||||
autostart_start((struct process **) autostart_processes);
|
profile_init();
|
||||||
|
#endif /* PROFILE_CONF_ON */
|
||||||
|
|
||||||
leds_off(LEDS_ALL);
|
leds_off(LEDS_ALL);
|
||||||
lpm_on();
|
lpm_on();
|
||||||
|
|
||||||
for (;;) {
|
printf(CONTIKI_VERSION_STRING " started. Node id %u.", node_id);
|
||||||
while (process_run() > 0);
|
|
||||||
if (process_nevents() == 0) {
|
autostart_start((struct process **) autostart_processes);
|
||||||
|
|
||||||
|
energest_init();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is the scheduler loop.
|
||||||
|
*/
|
||||||
|
ENERGEST_ON(ENERGEST_TYPE_CPU);
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
int r;
|
||||||
|
#if PROFILE_CONF_ON
|
||||||
|
profile_episode_start();
|
||||||
|
#endif /* PROFILE_CONF_ON */
|
||||||
|
do {
|
||||||
|
/* Reset watchdog. */
|
||||||
|
r = process_run();
|
||||||
|
} while(r > 0);
|
||||||
|
|
||||||
|
#if PROFILE_CONF_ON
|
||||||
|
profile_episode_end();
|
||||||
|
#endif /* PROFILE_CONF_ON */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Idle processing.
|
||||||
|
*/
|
||||||
|
int s = splhigh(); /* Disable interrupts. */
|
||||||
|
if (process_nevents() != 0) {
|
||||||
|
splx(s); /* Re-enable interrupts. */
|
||||||
|
} else {
|
||||||
|
static unsigned long irq_energest = 0;
|
||||||
|
/* Re-enable interrupts and go to sleep atomically. */
|
||||||
ENERGEST_OFF(ENERGEST_TYPE_CPU);
|
ENERGEST_OFF(ENERGEST_TYPE_CPU);
|
||||||
ENERGEST_ON(ENERGEST_TYPE_LPM);
|
ENERGEST_ON(ENERGEST_TYPE_LPM);
|
||||||
LPM_SLEEP();
|
/*
|
||||||
|
* We only want to measure the processing done in IRQs when we
|
||||||
|
* are asleep, so we discard the processing time done when we
|
||||||
|
* were awake.
|
||||||
|
*/
|
||||||
|
energest_type_set(ENERGEST_TYPE_IRQ, irq_energest);
|
||||||
|
|
||||||
|
if (uart_edge) {
|
||||||
|
_BIS_SR(LPM1_bits + GIE);
|
||||||
|
} else {
|
||||||
|
_BIS_SR(LPM1_bits + GIE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We get the current processing time for interrupts that was
|
||||||
|
* done during the LPM and store it for next time around.
|
||||||
|
*/
|
||||||
|
dint();
|
||||||
|
irq_energest = energest_type_time(ENERGEST_TYPE_IRQ);
|
||||||
|
eint();
|
||||||
ENERGEST_OFF(ENERGEST_TYPE_LPM);
|
ENERGEST_OFF(ENERGEST_TYPE_LPM);
|
||||||
ENERGEST_ON(ENERGEST_TYPE_CPU);
|
ENERGEST_ON(ENERGEST_TYPE_CPU);
|
||||||
|
#if PROFILE_CONF_ON
|
||||||
|
profile_clear_timestamps();
|
||||||
|
#endif /* PROFILE_CONF_ON */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -214,11 +214,21 @@ const uint8_t cc1020_config_115200[41] = {
|
||||||
|
|
||||||
/// cc1020 state
|
/// cc1020 state
|
||||||
enum cc1020_state {
|
enum cc1020_state {
|
||||||
CC1020_OFF,
|
CC1020_OFF = 0,
|
||||||
CC1020_RX,
|
CC1020_RX = 0x01,
|
||||||
CC1020_TX
|
CC1020_TX = 0x02,
|
||||||
|
|
||||||
|
CC1020_RX_SEARCHING = 0x10, // searching for preamble + sync word
|
||||||
|
CC1020_RX_RECEIVING = 0x20, // receiving bytes
|
||||||
|
CC1020_RX_PROCESSING = 0x40, // processing data in buffer
|
||||||
|
|
||||||
|
CC1020_OP_STATE = 0x73,
|
||||||
|
|
||||||
|
CC1020_TURN_OFF = 0x80,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define CC1020_SET_OPSTATE(opstate) cc1020_state = ((cc1020_state & ~CC1020_OP_STATE) | (opstate))
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* @name Packet specification
|
* @name Packet specification
|
||||||
* @{
|
* @{
|
||||||
|
@ -241,10 +251,3 @@ struct cc1020_header {
|
||||||
#define HDRSIZE (sizeof (struct cc1020_header))
|
#define HDRSIZE (sizeof (struct cc1020_header))
|
||||||
|
|
||||||
///@}
|
///@}
|
||||||
|
|
||||||
/// cc1020 receiver state
|
|
||||||
enum cc1020_rxstate {
|
|
||||||
CC1020_RX_SEARCHING, // searching for preamble + sync word
|
|
||||||
CC1020_RX_RECEIVING, // receiving bytes
|
|
||||||
CC1020_RX_PROCESSING // processing data in buffer
|
|
||||||
};
|
|
||||||
|
|
|
@ -52,6 +52,7 @@ Berlin, 2006
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
|
||||||
|
#include "contiki.h"
|
||||||
#include "contiki-msb430.h"
|
#include "contiki-msb430.h"
|
||||||
#include "cc1020-internal.h"
|
#include "cc1020-internal.h"
|
||||||
#include "cc1020.h"
|
#include "cc1020.h"
|
||||||
|
@ -59,6 +60,7 @@ Berlin, 2006
|
||||||
#include "net/rime/rimestats.h"
|
#include "net/rime/rimestats.h"
|
||||||
#include "dev/irq.h"
|
#include "dev/irq.h"
|
||||||
#include "dev/dma.h"
|
#include "dev/dma.h"
|
||||||
|
#include "energest.h"
|
||||||
|
|
||||||
static int cc1020_calibrate(void);
|
static int cc1020_calibrate(void);
|
||||||
static int cc1020_setupTX(int);
|
static int cc1020_setupTX(int);
|
||||||
|
@ -76,16 +78,16 @@ static enum cc1020_state cc1020_state = CC1020_OFF;
|
||||||
static volatile uint8_t cc1020_rxbuf[HDRSIZE + CC1020_BUFFERSIZE];
|
static volatile uint8_t cc1020_rxbuf[HDRSIZE + CC1020_BUFFERSIZE];
|
||||||
static uint8_t cc1020_txbuf[PREAMBLESIZE + HDRSIZE + CC1020_BUFFERSIZE +
|
static uint8_t cc1020_txbuf[PREAMBLESIZE + HDRSIZE + CC1020_BUFFERSIZE +
|
||||||
TAILSIZE];
|
TAILSIZE];
|
||||||
static volatile enum cc1020_rxstate cc1020_rxstate = CC1020_RX_SEARCHING;
|
//static volatile enum cc1020_rxstate cc1020_rxstate = CC1020_RX_SEARCHING;
|
||||||
|
|
||||||
/// number of bytes in receive and transmit buffers respectively.
|
// number of bytes in receive and transmit buffers respectively.
|
||||||
static uint16_t cc1020_rxlen;
|
static uint16_t cc1020_rxlen;
|
||||||
static uint16_t cc1020_txlen;
|
static uint16_t cc1020_txlen;
|
||||||
|
|
||||||
/// received signal strength indicator reading for last received packet
|
// received signal strength indicator reading for last received packet
|
||||||
static volatile uint8_t rssi;
|
static volatile uint8_t rssi;
|
||||||
|
|
||||||
/// callback when a packet has been received
|
// callback when a packet has been received
|
||||||
static uint8_t cc1020_pa_power = PA_POWER;
|
static uint8_t cc1020_pa_power = PA_POWER;
|
||||||
|
|
||||||
static void (*receiver_callback)(const struct radio_driver *);
|
static void (*receiver_callback)(const struct radio_driver *);
|
||||||
|
@ -155,17 +157,15 @@ cc1020_set_rx(void)
|
||||||
|
|
||||||
// configure driver
|
// configure driver
|
||||||
cc1020_rxlen = 0; // receive buffer position to start
|
cc1020_rxlen = 0; // receive buffer position to start
|
||||||
cc1020_rxstate = CC1020_RX_SEARCHING; // rx state machine to searching mode
|
//cc1020_rxstate = CC1020_RX_SEARCHING; // rx state machine to searching mode
|
||||||
cc1020_state = CC1020_RX; // driver state to receive mode
|
CC1020_SET_OPSTATE(CC1020_RX | CC1020_RX_SEARCHING); // driver state to receive mode
|
||||||
|
|
||||||
// configure radio
|
// configure radio
|
||||||
|
ENERGEST_ON(ENERGEST_TYPE_LISTEN);
|
||||||
cc1020_wakeupRX(RX_CURRENT);
|
cc1020_wakeupRX(RX_CURRENT);
|
||||||
cc1020_setupRX(RX_CURRENT);
|
cc1020_setupRX(RX_CURRENT);
|
||||||
LNA_POWER_ON(); // enable amplifier
|
LNA_POWER_ON(); // enable amplifier
|
||||||
|
|
||||||
ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT);
|
|
||||||
ENERGEST_ON(ENERGEST_TYPE_LISTEN);
|
|
||||||
|
|
||||||
// activate
|
// activate
|
||||||
IE1 |= URXIE0; // enable interrupt
|
IE1 |= URXIE0; // enable interrupt
|
||||||
}
|
}
|
||||||
|
@ -176,6 +176,7 @@ cc1020_set_tx(void)
|
||||||
int s;
|
int s;
|
||||||
|
|
||||||
// configure radio rx
|
// configure radio rx
|
||||||
|
ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
|
||||||
LNA_POWER_OFF(); // power down LNA
|
LNA_POWER_OFF(); // power down LNA
|
||||||
s = splhigh();
|
s = splhigh();
|
||||||
DISABLE_RX_IRQ();
|
DISABLE_RX_IRQ();
|
||||||
|
@ -183,17 +184,15 @@ cc1020_set_tx(void)
|
||||||
splx(s);
|
splx(s);
|
||||||
|
|
||||||
// configure radio tx
|
// configure radio tx
|
||||||
|
ENERGEST_ON(ENERGEST_TYPE_TRANSMIT);
|
||||||
cc1020_wakeupTX(TX_CURRENT);
|
cc1020_wakeupTX(TX_CURRENT);
|
||||||
cc1020_setupTX(TX_CURRENT);
|
cc1020_setupTX(TX_CURRENT);
|
||||||
P3SEL |= 0x0C; // select Tx line and clk
|
P3SEL |= 0x0C; // select Tx line and clk
|
||||||
U0CTL |= SWRST; // UART to reset mode
|
U0CTL |= SWRST; // UART to reset mode
|
||||||
IFG1 &= ~UTXIFG0; // Reset IFG.
|
IFG1 &= ~UTXIFG0; // Reset IFG.
|
||||||
|
|
||||||
ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
|
|
||||||
ENERGEST_ON(ENERGEST_TYPE_TRANSMIT);
|
|
||||||
|
|
||||||
// configure driver
|
// configure driver
|
||||||
cc1020_state = CC1020_TX;
|
CC1020_SET_OPSTATE(CC1020_TX);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -218,8 +217,10 @@ cc1020_send(const void *buf, unsigned short len)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* Previous data hasn't been sent yet. */
|
/* Previous data hasn't been sent yet. */
|
||||||
if (cc1020_txlen > 0)
|
if (cc1020_txlen > 0) {
|
||||||
|
printf("data in buffer");
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* The preamble and the sync word are already in buffer. */
|
/* The preamble and the sync word are already in buffer. */
|
||||||
cc1020_txlen = PREAMBLESIZE + SYNCWDSIZE;
|
cc1020_txlen = PREAMBLESIZE + SYNCWDSIZE;
|
||||||
|
@ -235,7 +236,8 @@ cc1020_send(const void *buf, unsigned short len)
|
||||||
cc1020_txbuf[cc1020_txlen++] = TAIL;
|
cc1020_txbuf[cc1020_txlen++] = TAIL;
|
||||||
cc1020_txbuf[cc1020_txlen++] = TAIL;
|
cc1020_txbuf[cc1020_txlen++] = TAIL;
|
||||||
|
|
||||||
process_poll(&cc1020_sender_process);
|
//process_poll(&cc1020_sender_process);
|
||||||
|
process_post_synch(&cc1020_sender_process, PROCESS_EVENT_POLL, NULL);
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
@ -269,6 +271,7 @@ cc1020_set_receiver(void (*recv)(const struct radio_driver *))
|
||||||
int
|
int
|
||||||
cc1020_on(void)
|
cc1020_on(void)
|
||||||
{
|
{
|
||||||
|
cc1020_state &= ~CC1020_TURN_OFF;
|
||||||
// Switch to receive mode
|
// Switch to receive mode
|
||||||
cc1020_set_rx();
|
cc1020_set_rx();
|
||||||
|
|
||||||
|
@ -280,21 +283,22 @@ cc1020_off(void)
|
||||||
{
|
{
|
||||||
int s;
|
int s;
|
||||||
|
|
||||||
|
if (cc1020_state & CC1020_RX_SEARCHING) {
|
||||||
// Discard the current read buffer when the radio is shutting down.
|
// Discard the current read buffer when the radio is shutting down.
|
||||||
cc1020_rxlen = 0;
|
cc1020_rxlen = 0;
|
||||||
|
|
||||||
LNA_POWER_OFF(); // power down lna
|
LNA_POWER_OFF(); // power down lna
|
||||||
s = splhigh();
|
s = splhigh();
|
||||||
cc1020_rxstate = CC1020_OFF;
|
//cc1020_rxstate = CC1020_OFF;
|
||||||
DISABLE_RX_IRQ();
|
DISABLE_RX_IRQ();
|
||||||
cc1020_state = CC1020_OFF;
|
cc1020_state = CC1020_OFF;
|
||||||
splx(s);
|
splx(s);
|
||||||
cc1020_setupPD(); // power down radio
|
cc1020_setupPD(); // power down radio
|
||||||
cc1020_state = CC1020_OFF;
|
|
||||||
|
|
||||||
ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
|
ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
|
||||||
ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT);
|
cc1020_state = CC1020_OFF;
|
||||||
|
} else {
|
||||||
|
cc1020_state |= CC1020_TURN_OFF;
|
||||||
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -328,8 +332,7 @@ interrupt(UART0RX_VECTOR) cc1020_rxhandler(void)
|
||||||
} shiftbuf;
|
} shiftbuf;
|
||||||
static unsigned char pktlen;
|
static unsigned char pktlen;
|
||||||
|
|
||||||
switch (cc1020_rxstate) {
|
if (cc1020_state & CC1020_RX_SEARCHING) {
|
||||||
case CC1020_RX_SEARCHING:
|
|
||||||
shiftbuf.b1 = shiftbuf.b2;
|
shiftbuf.b1 = shiftbuf.b2;
|
||||||
shiftbuf.b2 = shiftbuf.b3;
|
shiftbuf.b2 = shiftbuf.b3;
|
||||||
shiftbuf.b3 = shiftbuf.b4;
|
shiftbuf.b3 = shiftbuf.b4;
|
||||||
|
@ -364,10 +367,9 @@ interrupt(UART0RX_VECTOR) cc1020_rxhandler(void)
|
||||||
}
|
}
|
||||||
// Update RSSI.
|
// Update RSSI.
|
||||||
rssi = cc1020_read_reg(CC1020_RSS);
|
rssi = cc1020_read_reg(CC1020_RSS);
|
||||||
cc1020_rxstate = CC1020_RX_RECEIVING;
|
CC1020_SET_OPSTATE(CC1020_RX | CC1020_RX_RECEIVING);
|
||||||
|
|
||||||
break;
|
} else if( cc1020_state & CC1020_RX_RECEIVING ) {
|
||||||
case CC1020_RX_RECEIVING:
|
|
||||||
if (syncbs == 0) {
|
if (syncbs == 0) {
|
||||||
cc1020_rxbuf[cc1020_rxlen] = RXBUF0;
|
cc1020_rxbuf[cc1020_rxlen] = RXBUF0;
|
||||||
} else {
|
} else {
|
||||||
|
@ -387,13 +389,15 @@ interrupt(UART0RX_VECTOR) cc1020_rxhandler(void)
|
||||||
pktlen = ((struct cc1020_header *)cc1020_rxbuf)->length;
|
pktlen = ((struct cc1020_header *)cc1020_rxbuf)->length;
|
||||||
if (pktlen == 0 || pktlen > sizeof (cc1020_rxbuf)) {
|
if (pktlen == 0 || pktlen > sizeof (cc1020_rxbuf)) {
|
||||||
cc1020_rxlen = 0;
|
cc1020_rxlen = 0;
|
||||||
cc1020_rxstate = CC1020_RX_SEARCHING;
|
CC1020_SET_OPSTATE(CC1020_RX | CC1020_RX_SEARCHING);
|
||||||
|
//cc1020_rxstate = CC1020_RX_SEARCHING;
|
||||||
}
|
}
|
||||||
} else if (cc1020_rxlen > HDRSIZE) {
|
} else if (cc1020_rxlen > HDRSIZE) {
|
||||||
if (cc1020_rxlen == pktlen) {
|
if (cc1020_rxlen == pktlen) {
|
||||||
// disable receiver
|
// disable receiver
|
||||||
DISABLE_RX_IRQ();
|
DISABLE_RX_IRQ();
|
||||||
cc1020_rxstate = CC1020_RX_PROCESSING;
|
CC1020_SET_OPSTATE(CC1020_RX | CC1020_RX_PROCESSING);
|
||||||
|
//cc1020_rxstate = CC1020_RX_PROCESSING;
|
||||||
|
|
||||||
// call receiver to copy from buffer
|
// call receiver to copy from buffer
|
||||||
if (receiver_callback != NULL) {
|
if (receiver_callback != NULL) {
|
||||||
|
@ -402,18 +406,21 @@ interrupt(UART0RX_VECTOR) cc1020_rxhandler(void)
|
||||||
|
|
||||||
// reset receiver
|
// reset receiver
|
||||||
cc1020_rxlen = 0;
|
cc1020_rxlen = 0;
|
||||||
cc1020_rxstate = CC1020_RX_SEARCHING;
|
CC1020_SET_OPSTATE(CC1020_RX | CC1020_RX_SEARCHING);
|
||||||
|
//cc1020_rxstate = CC1020_RX_SEARCHING;
|
||||||
|
if ((cc1020_state & CC1020_TURN_OFF) && (cc1020_txlen == 0)) {
|
||||||
|
cc1020_off();
|
||||||
|
} else {
|
||||||
ENABLE_RX_IRQ();
|
ENABLE_RX_IRQ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PROCESS_THREAD(cc1020_sender_process, ev, data)
|
PROCESS_THREAD(cc1020_sender_process, ev, data)
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
PROCESS_BEGIN();
|
PROCESS_BEGIN();
|
||||||
|
|
||||||
dma_subscribe(0, &cc1020_sender_process);
|
dma_subscribe(0, &cc1020_sender_process);
|
||||||
|
@ -423,9 +430,9 @@ PROCESS_THREAD(cc1020_sender_process, ev, data)
|
||||||
|
|
||||||
cc1020_set_rx();
|
cc1020_set_rx();
|
||||||
|
|
||||||
if (cc1020_rxstate != CC1020_RX_SEARCHING) {
|
if((cc1020_state & CC1020_RX_SEARCHING) == 0) {
|
||||||
// Wait until the receiver is idle.
|
// Wait until the receiver is idle.
|
||||||
PROCESS_WAIT_UNTIL(cc1020_rxstate == CC1020_RX_SEARCHING);
|
PROCESS_WAIT_UNTIL(cc1020_state & CC1020_RX_SEARCHING);
|
||||||
|
|
||||||
// Wait for the medium to become idle.
|
// Wait for the medium to become idle.
|
||||||
while (cc1020_carrier_sense());
|
while (cc1020_carrier_sense());
|
||||||
|
@ -437,18 +444,32 @@ PROCESS_THREAD(cc1020_sender_process, ev, data)
|
||||||
// Switch to transceive mode.
|
// Switch to transceive mode.
|
||||||
cc1020_set_tx();
|
cc1020_set_tx();
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
U0CTL &= ~SWRST;
|
||||||
|
for (i = 0; i < cc1020_txlen; i++) {
|
||||||
|
UART0_TX = cc1020_txbuf[i];
|
||||||
|
UART0_WAIT_TX();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Initiate radio transfer.
|
// Initiate radio transfer.
|
||||||
dma_transfer(&TXBUF0, cc1020_txbuf, cc1020_txlen);
|
dma_transfer(&TXBUF0, cc1020_txbuf, cc1020_txlen);
|
||||||
|
|
||||||
// wait for DMA0 to finish
|
// wait for DMA0 to finish
|
||||||
PROCESS_WAIT_UNTIL(ev == dma_event);
|
PROCESS_WAIT_UNTIL(ev == dma_event);
|
||||||
|
ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT);
|
||||||
|
|
||||||
RIMESTATS_ADD(lltx);
|
RIMESTATS_ADD(lltx);
|
||||||
|
|
||||||
// clean up
|
// clean up
|
||||||
cc1020_txlen = 0;
|
cc1020_txlen = 0;
|
||||||
|
if (cc1020_state & CC1020_TURN_OFF) {
|
||||||
|
CC1020_SET_OPSTATE(CC1020_RX | CC1020_RX_SEARCHING);
|
||||||
|
cc1020_off();
|
||||||
|
} else {
|
||||||
cc1020_set_rx();
|
cc1020_set_rx();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
PROCESS_END();
|
PROCESS_END();
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,11 +32,19 @@ whether in contract, strict liability, or tort (including negligence
|
||||||
or otherwise) arising in any way out of the use of this software, even
|
or otherwise) arising in any way out of the use of this software, even
|
||||||
if advised of the possibility of such damage.
|
if advised of the possibility of such damage.
|
||||||
|
|
||||||
|
This implementation was developed by the CST group at the FUB.
|
||||||
|
|
||||||
|
For documentation and questions please use the web site
|
||||||
|
http://scatterweb.mi.fu-berlin.de and the mailinglist
|
||||||
|
scatterweb@lists.spline.inf.fu-berlin.de (subscription via the Website).
|
||||||
|
Berlin, 2007
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \file UART interface
|
* @file ScatterWeb.Uart.c
|
||||||
* \author Michael Baar <baar@inf.fu-berlin.de>
|
* @addtogroup interfaces
|
||||||
|
* @brief UART interface
|
||||||
|
* @author Michael Baar <baar@inf.fu-berlin.de>
|
||||||
*
|
*
|
||||||
* UART switch for RS232 and SPI protocols on UART1 written for
|
* UART switch for RS232 and SPI protocols on UART1 written for
|
||||||
* ScatterWeb MSB boards. Compatible to ScatterWeb EOS,
|
* ScatterWeb MSB boards. Compatible to ScatterWeb EOS,
|
||||||
|
@ -54,36 +62,38 @@ if advised of the possibility of such damage.
|
||||||
#define U1ME ME2
|
#define U1ME ME2
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void uart_configure(unsigned char mode);
|
void _uart_configure(unsigned char mode);
|
||||||
static void uart_set_mode(unsigned char mode);
|
void _uart_set_mode(unsigned char mode);
|
||||||
|
|
||||||
static volatile unsigned char uart_mode = UART_MODE_RESET;
|
volatile unsigned char uart_mode = UART_MODE_RESET;
|
||||||
static volatile unsigned char uart_lockcnt;
|
volatile unsigned char uart_lockcnt = 0;
|
||||||
|
volatile uint8_t uart_edge = 0;
|
||||||
|
|
||||||
static unsigned char uart_speed_br0[UART_NUM_MODES];
|
static unsigned char _uart_speed_br0[UART_NUM_MODES];
|
||||||
static unsigned char uart_speed_br1[UART_NUM_MODES];
|
static unsigned char _uart_speed_br1[UART_NUM_MODES];
|
||||||
static unsigned char uart_speed_bmn[UART_NUM_MODES];
|
static unsigned char _uart_speed_bmn[UART_NUM_MODES];
|
||||||
static fp_uart_handler uart_handler[UART_NUM_MODES];
|
static fp_uart_handler _uart_handler[UART_NUM_MODES] = {NULL, NULL};
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
void
|
void
|
||||||
uart_set_speed(unsigned char mode, unsigned char ubr0,
|
uart_set_speed(unsigned char mode, unsigned char ubr0,
|
||||||
unsigned char ubr1, unsigned char umctl)
|
unsigned char ubr1, unsigned char umctl)
|
||||||
{
|
{
|
||||||
// store setting
|
// store setting
|
||||||
uart_speed_br0[mode] = ubr0; // baudrate
|
_uart_speed_br0[mode] = ubr0; // baudrate
|
||||||
uart_speed_br1[mode] = ubr1; // baudrate
|
_uart_speed_br1[mode] = ubr1; // baudrate
|
||||||
uart_speed_bmn[mode] = umctl; // modulation
|
_uart_speed_bmn[mode] = umctl; // modulation
|
||||||
|
|
||||||
// reconfigure, if mode active
|
// reconfigure, if mode active
|
||||||
if (uart_mode == mode)
|
if (uart_mode == mode)
|
||||||
uart_configure(mode);
|
_uart_configure(mode);
|
||||||
}
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
void
|
void
|
||||||
uart_set_handler(unsigned char mode, fp_uart_handler fpHandler)
|
uart_set_handler(unsigned char mode, fp_uart_handler fpHandler)
|
||||||
{
|
{
|
||||||
// store setting
|
// store setting
|
||||||
uart_handler[mode] = fpHandler;
|
_uart_handler[mode] = fpHandler;
|
||||||
if (mode == uart_mode) {
|
if (mode == uart_mode) {
|
||||||
if (fpHandler == NULL)
|
if (fpHandler == NULL)
|
||||||
IE2 &= ~URXIE1; // Disable USART1 RX interrupt
|
IE2 &= ~URXIE1; // Disable USART1 RX interrupt
|
||||||
|
@ -91,28 +101,30 @@ uart_set_handler(unsigned char mode, fp_uart_handler fpHandler)
|
||||||
IE2 |= URXIE1; // Enable USART1 RX interrupt
|
IE2 |= URXIE1; // Enable USART1 RX interrupt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
int
|
int
|
||||||
uart_lock(unsigned char mode)
|
uart_lock(unsigned char mode)
|
||||||
{
|
{
|
||||||
// already locked?
|
// already locked?
|
||||||
if ((mode != uart_mode) && (uart_lockcnt)) {
|
if ((mode != uart_mode) && (uart_lockcnt)) {
|
||||||
return FALSE;
|
return 0;
|
||||||
}
|
} else {
|
||||||
|
|
||||||
// increase lock count
|
// increase lock count
|
||||||
uart_lockcnt++;
|
uart_lockcnt++;
|
||||||
// switch mode (if neccessary)
|
// switch mode (if neccessary)
|
||||||
uart_set_mode(mode);
|
_uart_set_mode(mode);
|
||||||
return TRUE;
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
int
|
int
|
||||||
uart_unlock(unsigned char mode)
|
uart_unlock(unsigned char mode)
|
||||||
{
|
{
|
||||||
/* Strict checking. */
|
/*
|
||||||
if (mode != uart_mode)
|
Do we wan't strict checking?
|
||||||
return FALSE;
|
if( (uart_lockcnt == 0) || (mode != uart_mode) )
|
||||||
|
return false;
|
||||||
|
*/
|
||||||
|
|
||||||
// decrement lock
|
// decrement lock
|
||||||
if (uart_lockcnt > 0) {
|
if (uart_lockcnt > 0) {
|
||||||
|
@ -120,28 +132,28 @@ uart_unlock(unsigned char mode)
|
||||||
|
|
||||||
// if no more locks, switch back to default mode
|
// if no more locks, switch back to default mode
|
||||||
if (uart_lockcnt == 0) {
|
if (uart_lockcnt == 0) {
|
||||||
uart_set_mode(UART_MODE_DEFAULT);
|
_uart_set_mode(UART_MODE_DEFAULT);
|
||||||
}
|
}
|
||||||
return TRUE;
|
return 1;
|
||||||
}
|
}
|
||||||
return FALSE;
|
return 0;
|
||||||
}
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
static void
|
void
|
||||||
uart_configure(unsigned char mode)
|
_uart_configure(unsigned char mode)
|
||||||
{
|
{
|
||||||
int s;
|
_DINT(); // disable interrupts
|
||||||
|
|
||||||
s = splhigh();
|
|
||||||
|
|
||||||
UART_WAIT_TXDONE();
|
UART_WAIT_TXDONE();
|
||||||
|
// wait till all buffered data has been transmitted
|
||||||
|
|
||||||
// configure
|
// configure
|
||||||
if (mode == UART_MODE_RS232) {
|
if (mode == UART_MODE_RS232) {
|
||||||
P5OUT |= 0x01;
|
P5OUT |= 0x01;
|
||||||
// unselect SPI
|
// unselect SPI
|
||||||
P3SEL |= 0xC0;
|
P3SEL |= 0xC0;
|
||||||
// select rs232 to RS232 mode
|
// select rs232
|
||||||
|
// to RS232 mode
|
||||||
UCTL1 = SWRST | CHAR; // 8-bit character
|
UCTL1 = SWRST | CHAR; // 8-bit character
|
||||||
UTCTL1 |= SSEL1; // UCLK = MCLK
|
UTCTL1 |= SSEL1; // UCLK = MCLK
|
||||||
// activate
|
// activate
|
||||||
|
@ -159,48 +171,56 @@ uart_configure(unsigned char mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
// restore speed settings
|
// restore speed settings
|
||||||
UBR01 = uart_speed_br0[mode]; // set baudrate
|
UBR01 = _uart_speed_br0[mode]; // set baudrate
|
||||||
UBR11 = uart_speed_br1[mode];
|
UBR11 = _uart_speed_br1[mode];
|
||||||
UMCTL1 = uart_speed_bmn[mode]; // set modulation
|
UMCTL1 = _uart_speed_bmn[mode]; // set modulation
|
||||||
|
|
||||||
UCTL1 &= ~SWRST; // clear reset flag
|
UCTL1 &= ~SWRST; // clear reset flag
|
||||||
|
_EINT(); // enable interrupts
|
||||||
splx(s);
|
|
||||||
}
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
static void
|
void
|
||||||
uart_set_mode(unsigned char mode)
|
_uart_set_mode(unsigned char mode)
|
||||||
{
|
{
|
||||||
// do nothing if mode already set
|
// do nothing if mode already set
|
||||||
if (mode == uart_mode )
|
if (mode == uart_mode)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
IE2 &= ~(URXIE1 | UTXIE1); // disable irq
|
IE2 &= ~(URXIE1 | UTXIE1); // disable irq
|
||||||
uart_configure(mode); // configure uart parameters
|
_uart_configure(mode); // configure uart parameters
|
||||||
uart_mode = mode;
|
uart_mode = mode;
|
||||||
|
|
||||||
if (uart_handler[mode] != NULL)
|
if (_uart_handler[mode] != NULL)
|
||||||
IE2 |= URXIE1; // Enable USART1 RX interrupt
|
IE2 |= URXIE1; // Enable USART1 RX interrupt
|
||||||
}
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
interrupt(UART1RX_VECTOR) uart_rx(void)
|
|
||||||
{
|
|
||||||
fp_uart_handler handler = uart_handler[uart_mode];
|
|
||||||
|
|
||||||
/* Check status register for receive errors. - before reading RXBUF since
|
|
||||||
it clears the error and interrupt flags */
|
|
||||||
if (!(URCTL1 & RXERR) && handler != NULL) {
|
|
||||||
if(handler(UART_RX)) {
|
|
||||||
LPM_AWAKE();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// read out the char to clear the I-flags, etc.
|
|
||||||
UART_RX;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
uart_get_mode(void)
|
uart_get_mode(void)
|
||||||
{
|
{
|
||||||
return uart_mode;
|
return uart_mode;
|
||||||
}
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
interrupt(UART1RX_VECTOR)_uart_rx(void)
|
||||||
|
{
|
||||||
|
fp_uart_handler handler = _uart_handler[uart_mode];
|
||||||
|
int c;
|
||||||
|
|
||||||
|
if (!(IFG2 & URXIFG1)) {
|
||||||
|
// If start edge detected, toggle & return
|
||||||
|
uart_edge = 1;
|
||||||
|
U1TCTL &= ~URXSE;
|
||||||
|
U1TCTL |= URXSE;
|
||||||
|
_BIC_SR_IRQ(LPM3_bits);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
uart_edge = 0;
|
||||||
|
if (!(URCTL1 & RXERR)) {
|
||||||
|
c = UART_RX;
|
||||||
|
if (handler(c)) {
|
||||||
|
_BIC_SR_IRQ(LPM3_bits);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// read out the char to clear the I-flags, etc.
|
||||||
|
c = UART_RX;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue