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/autostart.h"
|
||||
#include "sys/rtimer.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/xmac.h"
|
||||
|
||||
#include "dev/slip.h"
|
||||
|
||||
extern volatile bool uart_edge;
|
||||
|
||||
SENSORS(NULL);
|
||||
|
||||
#if WITH_UIP
|
||||
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
|
||||
int
|
||||
putchar(int c)
|
||||
|
@ -75,7 +75,6 @@ static void
|
|||
set_rime_addr(void)
|
||||
{
|
||||
rimeaddr_t addr;
|
||||
|
||||
addr.u16[0] = node_id;
|
||||
rimeaddr_set_node_addr(&addr);
|
||||
}
|
||||
|
@ -83,12 +82,29 @@ set_rime_addr(void)
|
|||
static void
|
||||
msb_ports_init(void)
|
||||
{
|
||||
P1DIR = 0x00; P1SEL = 0x00; P1OUT = 0x00;
|
||||
P2DIR = 0x1A; P2SEL = 0x00; P2OUT = 0x18;
|
||||
P3DIR = 0x21; P3SEL = 0x00; P3OUT = 0x09;
|
||||
P4DIR = 0x00; P4SEL = 0x00; P4OUT = 0x07;
|
||||
P5DIR = 0xFD; P5SEL = 0x0E; P5OUT = 0xF9;
|
||||
P6DIR = 0xC8; P6SEL = 0x07; P6OUT = 0x00;
|
||||
P1SEL = 0x00;
|
||||
P1OUT = 0x00;
|
||||
P1DIR = 0x00;
|
||||
|
||||
P2SEL = 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
|
||||
|
@ -99,12 +115,10 @@ main(void)
|
|||
/* Platform-specific initialization. */
|
||||
msb_ports_init();
|
||||
adc_init();
|
||||
dma_init();
|
||||
|
||||
clock_init();
|
||||
leds_init();
|
||||
leds_on(LEDS_ALL);
|
||||
sht11_init();
|
||||
|
||||
// low level
|
||||
irq_init();
|
||||
|
@ -123,55 +137,101 @@ main(void)
|
|||
slip_arch_init(BAUD2UBR(115200));
|
||||
#endif
|
||||
|
||||
rtimer_init();
|
||||
ctimer_init();
|
||||
|
||||
energest_init();
|
||||
node_id_restore();
|
||||
|
||||
/* System services */
|
||||
process_start(&etimer_process, NULL);
|
||||
#if 0
|
||||
process_start(&sensors_process, NULL);
|
||||
#endif
|
||||
//process_start(&sensors_process, NULL);
|
||||
|
||||
/* Radio driver */
|
||||
cc1020_init(cc1020_config_19200);
|
||||
//cc1020_init(cc1020_config_19200);
|
||||
|
||||
// network configuration
|
||||
node_id_restore();
|
||||
|
||||
/* Network configuration */
|
||||
#if WITH_UIP
|
||||
uip_init();
|
||||
uip_sethostaddr(&slipif.ipaddr);
|
||||
uip_setnetmask(&slipif.netmask);
|
||||
/* Point-to-point, no default router. */
|
||||
uip_fw_default(&slipif);
|
||||
uip_fw_default(&slipif); /* Point2point, no default router. */
|
||||
tcpip_set_forwarding(0);
|
||||
|
||||
process_start(&tcpip_process, NULL);
|
||||
process_start(&uip_fw_process, NULL);
|
||||
process_start(&slip_process, NULL);
|
||||
#endif /* WITH_UIP */
|
||||
|
||||
nullmac_init(&cc1020_driver);
|
||||
rime_init(&nullmac_driver);
|
||||
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");
|
||||
autostart_start((struct process **) autostart_processes);
|
||||
#if PROFILE_CONF_ON
|
||||
profile_init();
|
||||
#endif /* PROFILE_CONF_ON */
|
||||
|
||||
leds_off(LEDS_ALL);
|
||||
lpm_on();
|
||||
|
||||
for (;;) {
|
||||
while (process_run() > 0);
|
||||
if (process_nevents() == 0) {
|
||||
printf(CONTIKI_VERSION_STRING " started. Node id %u.", node_id);
|
||||
|
||||
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_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_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
|
||||
enum cc1020_state {
|
||||
CC1020_OFF,
|
||||
CC1020_RX,
|
||||
CC1020_TX
|
||||
CC1020_OFF = 0,
|
||||
CC1020_RX = 0x01,
|
||||
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
|
||||
* @{
|
||||
|
@ -241,10 +251,3 @@ 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 <signal.h>
|
||||
|
||||
#include "contiki.h"
|
||||
#include "contiki-msb430.h"
|
||||
#include "cc1020-internal.h"
|
||||
#include "cc1020.h"
|
||||
|
@ -59,6 +60,7 @@ Berlin, 2006
|
|||
#include "net/rime/rimestats.h"
|
||||
#include "dev/irq.h"
|
||||
#include "dev/dma.h"
|
||||
#include "energest.h"
|
||||
|
||||
static int cc1020_calibrate(void);
|
||||
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 uint8_t cc1020_txbuf[PREAMBLESIZE + HDRSIZE + CC1020_BUFFERSIZE +
|
||||
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_txlen;
|
||||
|
||||
/// received signal strength indicator reading for last received packet
|
||||
// received signal strength indicator reading for last received packet
|
||||
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 void (*receiver_callback)(const struct radio_driver *);
|
||||
|
@ -155,17 +157,15 @@ cc1020_set_rx(void)
|
|||
|
||||
// configure driver
|
||||
cc1020_rxlen = 0; // receive buffer position to start
|
||||
cc1020_rxstate = CC1020_RX_SEARCHING; // rx state machine to searching mode
|
||||
cc1020_state = CC1020_RX; // driver state to receive mode
|
||||
//cc1020_rxstate = CC1020_RX_SEARCHING; // rx state machine to searching mode
|
||||
CC1020_SET_OPSTATE(CC1020_RX | CC1020_RX_SEARCHING); // driver state to receive mode
|
||||
|
||||
// configure radio
|
||||
ENERGEST_ON(ENERGEST_TYPE_LISTEN);
|
||||
cc1020_wakeupRX(RX_CURRENT);
|
||||
cc1020_setupRX(RX_CURRENT);
|
||||
LNA_POWER_ON(); // enable amplifier
|
||||
|
||||
ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT);
|
||||
ENERGEST_ON(ENERGEST_TYPE_LISTEN);
|
||||
|
||||
// activate
|
||||
IE1 |= URXIE0; // enable interrupt
|
||||
}
|
||||
|
@ -176,6 +176,7 @@ cc1020_set_tx(void)
|
|||
int s;
|
||||
|
||||
// configure radio rx
|
||||
ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
|
||||
LNA_POWER_OFF(); // power down LNA
|
||||
s = splhigh();
|
||||
DISABLE_RX_IRQ();
|
||||
|
@ -183,17 +184,15 @@ cc1020_set_tx(void)
|
|||
splx(s);
|
||||
|
||||
// configure radio tx
|
||||
ENERGEST_ON(ENERGEST_TYPE_TRANSMIT);
|
||||
cc1020_wakeupTX(TX_CURRENT);
|
||||
cc1020_setupTX(TX_CURRENT);
|
||||
P3SEL |= 0x0C; // select Tx line and clk
|
||||
U0CTL |= SWRST; // UART to reset mode
|
||||
IFG1 &= ~UTXIFG0; // Reset IFG.
|
||||
|
||||
ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
|
||||
ENERGEST_ON(ENERGEST_TYPE_TRANSMIT);
|
||||
|
||||
// configure driver
|
||||
cc1020_state = CC1020_TX;
|
||||
CC1020_SET_OPSTATE(CC1020_TX);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -218,8 +217,10 @@ cc1020_send(const void *buf, unsigned short len)
|
|||
return -1;
|
||||
|
||||
/* Previous data hasn't been sent yet. */
|
||||
if (cc1020_txlen > 0)
|
||||
if (cc1020_txlen > 0) {
|
||||
printf("data in buffer");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* The preamble and the sync word are already in buffer. */
|
||||
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;
|
||||
|
||||
process_poll(&cc1020_sender_process);
|
||||
//process_poll(&cc1020_sender_process);
|
||||
process_post_synch(&cc1020_sender_process, PROCESS_EVENT_POLL, NULL);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
@ -269,6 +271,7 @@ cc1020_set_receiver(void (*recv)(const struct radio_driver *))
|
|||
int
|
||||
cc1020_on(void)
|
||||
{
|
||||
cc1020_state &= ~CC1020_TURN_OFF;
|
||||
// Switch to receive mode
|
||||
cc1020_set_rx();
|
||||
|
||||
|
@ -280,21 +283,22 @@ cc1020_off(void)
|
|||
{
|
||||
int s;
|
||||
|
||||
if (cc1020_state & CC1020_RX_SEARCHING) {
|
||||
// Discard the current read buffer when the radio is shutting down.
|
||||
cc1020_rxlen = 0;
|
||||
|
||||
LNA_POWER_OFF(); // power down lna
|
||||
s = splhigh();
|
||||
cc1020_rxstate = CC1020_OFF;
|
||||
//cc1020_rxstate = CC1020_OFF;
|
||||
DISABLE_RX_IRQ();
|
||||
cc1020_state = CC1020_OFF;
|
||||
splx(s);
|
||||
cc1020_setupPD(); // power down radio
|
||||
cc1020_state = CC1020_OFF;
|
||||
|
||||
ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
|
||||
ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT);
|
||||
|
||||
cc1020_state = CC1020_OFF;
|
||||
} else {
|
||||
cc1020_state |= CC1020_TURN_OFF;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -328,8 +332,7 @@ interrupt(UART0RX_VECTOR) cc1020_rxhandler(void)
|
|||
} shiftbuf;
|
||||
static unsigned char pktlen;
|
||||
|
||||
switch (cc1020_rxstate) {
|
||||
case CC1020_RX_SEARCHING:
|
||||
if (cc1020_state & CC1020_RX_SEARCHING) {
|
||||
shiftbuf.b1 = shiftbuf.b2;
|
||||
shiftbuf.b2 = shiftbuf.b3;
|
||||
shiftbuf.b3 = shiftbuf.b4;
|
||||
|
@ -364,10 +367,9 @@ interrupt(UART0RX_VECTOR) cc1020_rxhandler(void)
|
|||
}
|
||||
// Update RSSI.
|
||||
rssi = cc1020_read_reg(CC1020_RSS);
|
||||
cc1020_rxstate = CC1020_RX_RECEIVING;
|
||||
CC1020_SET_OPSTATE(CC1020_RX | CC1020_RX_RECEIVING);
|
||||
|
||||
break;
|
||||
case CC1020_RX_RECEIVING:
|
||||
} else if( cc1020_state & CC1020_RX_RECEIVING ) {
|
||||
if (syncbs == 0) {
|
||||
cc1020_rxbuf[cc1020_rxlen] = RXBUF0;
|
||||
} else {
|
||||
|
@ -387,13 +389,15 @@ interrupt(UART0RX_VECTOR) cc1020_rxhandler(void)
|
|||
pktlen = ((struct cc1020_header *)cc1020_rxbuf)->length;
|
||||
if (pktlen == 0 || pktlen > sizeof (cc1020_rxbuf)) {
|
||||
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) {
|
||||
if (cc1020_rxlen == pktlen) {
|
||||
// disable receiver
|
||||
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
|
||||
if (receiver_callback != NULL) {
|
||||
|
@ -402,18 +406,21 @@ interrupt(UART0RX_VECTOR) cc1020_rxhandler(void)
|
|||
|
||||
// reset receiver
|
||||
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();
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PROCESS_THREAD(cc1020_sender_process, ev, data)
|
||||
{
|
||||
int i;
|
||||
PROCESS_BEGIN();
|
||||
|
||||
dma_subscribe(0, &cc1020_sender_process);
|
||||
|
@ -423,9 +430,9 @@ PROCESS_THREAD(cc1020_sender_process, ev, data)
|
|||
|
||||
cc1020_set_rx();
|
||||
|
||||
if (cc1020_rxstate != CC1020_RX_SEARCHING) {
|
||||
if((cc1020_state & CC1020_RX_SEARCHING) == 0) {
|
||||
// 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.
|
||||
while (cc1020_carrier_sense());
|
||||
|
@ -437,18 +444,32 @@ PROCESS_THREAD(cc1020_sender_process, ev, data)
|
|||
// Switch to transceive mode.
|
||||
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.
|
||||
dma_transfer(&TXBUF0, cc1020_txbuf, cc1020_txlen);
|
||||
|
||||
// wait for DMA0 to finish
|
||||
PROCESS_WAIT_UNTIL(ev == dma_event);
|
||||
ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT);
|
||||
|
||||
RIMESTATS_ADD(lltx);
|
||||
|
||||
// clean up
|
||||
cc1020_txlen = 0;
|
||||
if (cc1020_state & CC1020_TURN_OFF) {
|
||||
CC1020_SET_OPSTATE(CC1020_RX | CC1020_RX_SEARCHING);
|
||||
cc1020_off();
|
||||
} else {
|
||||
cc1020_set_rx();
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
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
|
||||
* \author Michael Baar <baar@inf.fu-berlin.de>
|
||||
* @file ScatterWeb.Uart.c
|
||||
* @addtogroup interfaces
|
||||
* @brief UART interface
|
||||
* @author Michael Baar <baar@inf.fu-berlin.de>
|
||||
*
|
||||
* UART switch for RS232 and SPI protocols on UART1 written for
|
||||
* ScatterWeb MSB boards. Compatible to ScatterWeb EOS,
|
||||
|
@ -54,36 +62,38 @@ if advised of the possibility of such damage.
|
|||
#define U1ME ME2
|
||||
#endif
|
||||
|
||||
static void uart_configure(unsigned char mode);
|
||||
static void uart_set_mode(unsigned char mode);
|
||||
void _uart_configure(unsigned char mode);
|
||||
void _uart_set_mode(unsigned char mode);
|
||||
|
||||
static volatile unsigned char uart_mode = UART_MODE_RESET;
|
||||
static volatile unsigned char uart_lockcnt;
|
||||
volatile unsigned char uart_mode = UART_MODE_RESET;
|
||||
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_br1[UART_NUM_MODES];
|
||||
static unsigned char uart_speed_bmn[UART_NUM_MODES];
|
||||
static fp_uart_handler uart_handler[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_bmn[UART_NUM_MODES];
|
||||
static fp_uart_handler _uart_handler[UART_NUM_MODES] = {NULL, NULL};
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
uart_set_speed(unsigned char mode, unsigned char ubr0,
|
||||
unsigned char ubr1, unsigned char umctl)
|
||||
{
|
||||
// store setting
|
||||
uart_speed_br0[mode] = ubr0; // baudrate
|
||||
uart_speed_br1[mode] = ubr1; // baudrate
|
||||
uart_speed_bmn[mode] = umctl; // modulation
|
||||
_uart_speed_br0[mode] = ubr0; // baudrate
|
||||
_uart_speed_br1[mode] = ubr1; // baudrate
|
||||
_uart_speed_bmn[mode] = umctl; // modulation
|
||||
|
||||
// reconfigure, if mode active
|
||||
if (uart_mode == mode)
|
||||
uart_configure(mode);
|
||||
_uart_configure(mode);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
uart_set_handler(unsigned char mode, fp_uart_handler fpHandler)
|
||||
{
|
||||
// store setting
|
||||
uart_handler[mode] = fpHandler;
|
||||
_uart_handler[mode] = fpHandler;
|
||||
if (mode == uart_mode) {
|
||||
if (fpHandler == NULL)
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int
|
||||
uart_lock(unsigned char mode)
|
||||
{
|
||||
// already locked?
|
||||
if ((mode != uart_mode) && (uart_lockcnt)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
} else {
|
||||
// increase lock count
|
||||
uart_lockcnt++;
|
||||
// switch mode (if neccessary)
|
||||
uart_set_mode(mode);
|
||||
return TRUE;
|
||||
_uart_set_mode(mode);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int
|
||||
uart_unlock(unsigned char mode)
|
||||
{
|
||||
/* Strict checking. */
|
||||
if (mode != uart_mode)
|
||||
return FALSE;
|
||||
/*
|
||||
Do we wan't strict checking?
|
||||
if( (uart_lockcnt == 0) || (mode != uart_mode) )
|
||||
return false;
|
||||
*/
|
||||
|
||||
// decrement lock
|
||||
if (uart_lockcnt > 0) {
|
||||
|
@ -120,28 +132,28 @@ uart_unlock(unsigned char mode)
|
|||
|
||||
// if no more locks, switch back to default mode
|
||||
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
|
||||
uart_configure(unsigned char mode)
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
_uart_configure(unsigned char mode)
|
||||
{
|
||||
int s;
|
||||
|
||||
s = splhigh();
|
||||
_DINT(); // disable interrupts
|
||||
|
||||
UART_WAIT_TXDONE();
|
||||
// wait till all buffered data has been transmitted
|
||||
|
||||
// configure
|
||||
if (mode == UART_MODE_RS232) {
|
||||
P5OUT |= 0x01;
|
||||
// unselect SPI
|
||||
P3SEL |= 0xC0;
|
||||
// select rs232 to RS232 mode
|
||||
// select rs232
|
||||
// to RS232 mode
|
||||
UCTL1 = SWRST | CHAR; // 8-bit character
|
||||
UTCTL1 |= SSEL1; // UCLK = MCLK
|
||||
// activate
|
||||
|
@ -159,48 +171,56 @@ uart_configure(unsigned char mode)
|
|||
}
|
||||
|
||||
// restore speed settings
|
||||
UBR01 = uart_speed_br0[mode]; // set baudrate
|
||||
UBR11 = uart_speed_br1[mode];
|
||||
UMCTL1 = uart_speed_bmn[mode]; // set modulation
|
||||
UBR01 = _uart_speed_br0[mode]; // set baudrate
|
||||
UBR11 = _uart_speed_br1[mode];
|
||||
UMCTL1 = _uart_speed_bmn[mode]; // set modulation
|
||||
|
||||
UCTL1 &= ~SWRST; // clear reset flag
|
||||
|
||||
splx(s);
|
||||
_EINT(); // enable interrupts
|
||||
}
|
||||
|
||||
static void
|
||||
uart_set_mode(unsigned char mode)
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
_uart_set_mode(unsigned char mode)
|
||||
{
|
||||
// do nothing if mode already set
|
||||
if (mode == uart_mode )
|
||||
if (mode == uart_mode)
|
||||
return;
|
||||
|
||||
IE2 &= ~(URXIE1 | UTXIE1); // disable irq
|
||||
uart_configure(mode); // configure uart parameters
|
||||
_uart_configure(mode); // configure uart parameters
|
||||
uart_mode = mode;
|
||||
|
||||
if (uart_handler[mode] != NULL)
|
||||
if (_uart_handler[mode] != NULL)
|
||||
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
|
||||
uart_get_mode(void)
|
||||
{
|
||||
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