2007-08-20 13:01:13 +02:00
|
|
|
|
/*
|
|
|
|
|
Copyright 2007, Freie Universitaet Berlin. All rights reserved.
|
|
|
|
|
|
|
|
|
|
These sources were developed at the Freie Universit<EFBFBD>t Berlin, Computer
|
|
|
|
|
Systems and Telematics group.
|
|
|
|
|
|
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
|
|
|
modification, are permitted provided that the following conditions are
|
|
|
|
|
met:
|
|
|
|
|
|
|
|
|
|
- Redistributions of source code must retain the above copyright
|
|
|
|
|
notice, this list of conditions and the following disclaimer.
|
|
|
|
|
|
|
|
|
|
- Redistributions in binary form must reproduce the above copyright
|
|
|
|
|
notice, this list of conditions and the following disclaimer in the
|
|
|
|
|
documentation and/or other materials provided with the distribution.
|
|
|
|
|
|
|
|
|
|
- Neither the name of Freie Universitaet Berlin (FUB) nor the names of its
|
|
|
|
|
contributors may be used to endorse or promote products derived from
|
|
|
|
|
this software without specific prior written permission.
|
|
|
|
|
|
|
|
|
|
This software is provided by FUB and the contributors on an "as is"
|
|
|
|
|
basis, without any representations or warranties of any kind, express
|
|
|
|
|
or implied including, but not limited to, representations or
|
|
|
|
|
warranties of non-infringement, merchantability or fitness for a
|
|
|
|
|
particular purpose. In no event shall FUB or contributors be liable
|
|
|
|
|
for any direct, indirect, incidental, special, exemplary, or
|
|
|
|
|
consequential damages (including, but not limited to, procurement of
|
|
|
|
|
substitute goods or services; loss of use, data, or profits; or
|
|
|
|
|
business interruption) however caused and on any theory of liability,
|
|
|
|
|
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.
|
|
|
|
|
|
2007-12-13 13:51:38 +01:00
|
|
|
|
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
|
2007-08-20 13:01:13 +02:00
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/**
|
2007-12-13 13:51:38 +01:00
|
|
|
|
* @file ScatterWeb.Uart.c
|
|
|
|
|
* @addtogroup interfaces
|
|
|
|
|
* @brief UART interface
|
|
|
|
|
* @author Michael Baar <baar@inf.fu-berlin.de>
|
2007-08-20 13:01:13 +02:00
|
|
|
|
*
|
|
|
|
|
* UART switch for RS232 and SPI protocols on UART1 written for
|
|
|
|
|
* ScatterWeb MSB boards. Compatible to ScatterWeb EOS,
|
|
|
|
|
* ScatterWeb Bootload and Contiki.
|
|
|
|
|
*/
|
|
|
|
|
|
2011-06-07 18:54:57 +02:00
|
|
|
|
#include "contiki.h"
|
2007-08-20 13:01:13 +02:00
|
|
|
|
#include <string.h>
|
|
|
|
|
#include "dev/msb430-uart1.h"
|
|
|
|
|
#include "dev/lpm.h"
|
|
|
|
|
|
|
|
|
|
#ifndef U1ME
|
|
|
|
|
#define U1ME ME2
|
|
|
|
|
#endif
|
|
|
|
|
|
2010-12-01 11:19:58 +01:00
|
|
|
|
volatile unsigned char uart_mode = UART_MODE_RESET;
|
|
|
|
|
volatile unsigned char uart_lockcnt = 0;
|
2007-12-13 13:51:38 +01:00
|
|
|
|
volatile uint8_t uart_edge = 0;
|
2007-08-20 13:01:13 +02:00
|
|
|
|
|
2008-02-28 16:11:22 +01:00
|
|
|
|
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];
|
2009-06-29 14:46:49 +02:00
|
|
|
|
static uart_handler_t uart_handler[UART_NUM_MODES] = {NULL, NULL};
|
2007-08-20 13:01:13 +02:00
|
|
|
|
|
2008-02-28 16:11:22 +01:00
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
|
static void
|
|
|
|
|
uart_configure(unsigned mode)
|
|
|
|
|
{
|
2009-06-29 14:46:49 +02:00
|
|
|
|
_DINT(); /* disable interrupts */
|
2008-02-28 16:11:22 +01:00
|
|
|
|
|
2009-06-29 14:46:49 +02:00
|
|
|
|
UART_WAIT_TXDONE(); /* wait till all buffered data has been transmitted */
|
2008-02-28 16:11:22 +01:00
|
|
|
|
|
2008-10-28 13:42:53 +01:00
|
|
|
|
if(mode == UART_MODE_RS232) {
|
2008-02-28 16:11:22 +01:00
|
|
|
|
P5OUT |= 0x01;
|
2009-06-29 14:46:49 +02:00
|
|
|
|
/* unselect SPI */
|
2008-02-28 16:11:22 +01:00
|
|
|
|
P3SEL |= 0xC0;
|
2009-06-29 14:46:49 +02:00
|
|
|
|
/* select rs232 */
|
|
|
|
|
UCTL1 = SWRST | CHAR; /* 8-bit character */
|
|
|
|
|
UTCTL1 |= SSEL1; /* UCLK = MCLK */
|
|
|
|
|
/* activate */
|
|
|
|
|
U1ME |= UTXE1 | URXE1; /* Enable USART1 TXD/RXD */
|
2008-10-28 13:42:53 +01:00
|
|
|
|
} else if(mode == UART_MODE_SPI) {
|
2009-06-29 14:46:49 +02:00
|
|
|
|
P3SEL &= ~0xC0; /* unselect RS232 */
|
2008-02-28 16:11:22 +01:00
|
|
|
|
// to SPI mode
|
2009-06-29 14:46:49 +02:00
|
|
|
|
UCTL1 = SWRST | CHAR | SYNC | MM; /* 8-bit SPI Master */
|
2008-02-28 16:11:22 +01:00
|
|
|
|
/*
|
|
|
|
|
* SMCLK, 3-pin mode, clock idle low, data valid on
|
|
|
|
|
* rising edge, UCLK delayed
|
|
|
|
|
*/
|
2009-06-29 14:46:49 +02:00
|
|
|
|
UTCTL1 |= CKPH | SSEL1 | SSEL0 | STC; /* activate */
|
|
|
|
|
U1ME |= USPIE1; /* Enable USART1 SPI */
|
2008-02-28 16:11:22 +01:00
|
|
|
|
}
|
|
|
|
|
|
2009-06-29 14:46:49 +02:00
|
|
|
|
/* restore speed settings */
|
|
|
|
|
UBR01 = uart_speed_br0[mode]; /* set baudrate */
|
2008-02-28 16:11:22 +01:00
|
|
|
|
UBR11 = uart_speed_br1[mode];
|
2009-06-29 14:46:49 +02:00
|
|
|
|
UMCTL1 = uart_speed_bmn[mode]; /* set modulation */
|
2008-02-28 16:11:22 +01:00
|
|
|
|
|
2009-06-29 14:46:49 +02:00
|
|
|
|
UCTL1 &= ~SWRST; /* clear reset flag */
|
|
|
|
|
_EINT(); /* enable interrupts */
|
2008-02-28 16:11:22 +01:00
|
|
|
|
}
|
2007-12-13 13:51:38 +01:00
|
|
|
|
/*---------------------------------------------------------------------------*/
|
2007-08-20 13:01:13 +02:00
|
|
|
|
void
|
2008-02-28 16:11:22 +01:00
|
|
|
|
uart_set_speed(unsigned mode, unsigned ubr0,
|
|
|
|
|
unsigned ubr1, unsigned umctl)
|
2007-08-20 13:01:13 +02:00
|
|
|
|
{
|
2009-06-29 14:46:49 +02:00
|
|
|
|
/* store the setting */
|
|
|
|
|
uart_speed_br0[mode] = ubr0; /* baudrate */
|
|
|
|
|
uart_speed_br1[mode] = ubr1; /* baudrate */
|
|
|
|
|
uart_speed_bmn[mode] = umctl; /* modulation */
|
2007-08-20 13:01:13 +02:00
|
|
|
|
|
2009-06-29 14:46:49 +02:00
|
|
|
|
/* reconfigure, if mode active */
|
|
|
|
|
if(uart_mode == mode) {
|
2008-02-28 16:11:22 +01:00
|
|
|
|
uart_configure(mode);
|
2008-03-28 17:06:28 +01:00
|
|
|
|
}
|
2007-08-20 13:01:13 +02:00
|
|
|
|
}
|
2007-12-13 13:51:38 +01:00
|
|
|
|
/*---------------------------------------------------------------------------*/
|
2007-08-20 13:01:13 +02:00
|
|
|
|
void
|
2009-06-29 14:46:49 +02:00
|
|
|
|
uart_set_handler(unsigned mode, uart_handler_t handler)
|
2007-08-20 13:01:13 +02:00
|
|
|
|
{
|
2009-06-29 14:46:49 +02:00
|
|
|
|
/* store the setting */
|
|
|
|
|
uart_handler[mode] = handler;
|
2008-10-28 13:42:53 +01:00
|
|
|
|
if(mode == uart_mode) {
|
2009-06-29 14:46:49 +02:00
|
|
|
|
if(handler == NULL) {
|
|
|
|
|
IE2 &= ~URXIE1; /* Disable USART1 RX interrupt */
|
2008-02-28 16:11:22 +01:00
|
|
|
|
} else {
|
2009-06-29 14:46:49 +02:00
|
|
|
|
IE2 |= URXIE1; /* Enable USART1 RX interrupt */
|
2008-02-28 16:11:22 +01:00
|
|
|
|
}
|
2007-08-20 13:01:13 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
2007-12-13 13:51:38 +01:00
|
|
|
|
/*---------------------------------------------------------------------------*/
|
2007-08-20 13:01:13 +02:00
|
|
|
|
int
|
2008-02-28 16:11:22 +01:00
|
|
|
|
uart_lock(unsigned mode)
|
2007-08-20 13:01:13 +02:00
|
|
|
|
{
|
2009-06-29 14:46:49 +02:00
|
|
|
|
/* already locked? */
|
2008-10-28 13:42:53 +01:00
|
|
|
|
if(uart_mode != mode && uart_lockcnt > 0) {
|
|
|
|
|
return 0;
|
2008-05-28 15:17:08 +02:00
|
|
|
|
}
|
|
|
|
|
|
2009-06-29 14:46:49 +02:00
|
|
|
|
/* increase lock count */
|
2008-10-28 13:42:53 +01:00
|
|
|
|
uart_lockcnt++;
|
2009-06-29 14:46:49 +02:00
|
|
|
|
/* switch mode (if neccessary) */
|
2008-10-28 13:42:53 +01:00
|
|
|
|
uart_set_mode(mode);
|
|
|
|
|
return 1;
|
2007-08-20 13:01:13 +02:00
|
|
|
|
}
|
2007-12-13 13:51:38 +01:00
|
|
|
|
/*---------------------------------------------------------------------------*/
|
2007-08-20 13:01:13 +02:00
|
|
|
|
int
|
2008-03-28 17:06:28 +01:00
|
|
|
|
uart_lock_wait(unsigned mode)
|
|
|
|
|
{
|
2008-10-28 13:42:53 +01:00
|
|
|
|
while(UART_WAIT_LOCK(mode)) {
|
2008-03-28 17:06:28 +01:00
|
|
|
|
_NOP();
|
|
|
|
|
}
|
|
|
|
|
return uart_lock(mode);
|
|
|
|
|
}
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
|
int
|
2008-02-28 16:11:22 +01:00
|
|
|
|
uart_unlock(unsigned mode)
|
2007-08-20 13:01:13 +02:00
|
|
|
|
{
|
2008-10-28 13:42:53 +01:00
|
|
|
|
if((uart_lockcnt == 0) || (mode != uart_mode)) {
|
|
|
|
|
uart_lockcnt = 0;
|
|
|
|
|
uart_set_mode(UART_MODE_DEFAULT);
|
2008-02-28 16:11:22 +01:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
2007-08-20 13:01:13 +02:00
|
|
|
|
|
2009-06-29 14:46:49 +02:00
|
|
|
|
/* decrement lock */
|
|
|
|
|
if(uart_lockcnt > 0) {
|
2008-10-28 13:42:53 +01:00
|
|
|
|
uart_lockcnt--;
|
2009-06-29 14:46:49 +02:00
|
|
|
|
/* if no more locks, switch back to default mode */
|
2008-10-28 13:42:53 +01:00
|
|
|
|
if(uart_lockcnt == 0) {
|
2008-02-28 16:11:22 +01:00
|
|
|
|
uart_set_mode(UART_MODE_DEFAULT);
|
2008-10-28 13:42:53 +01:00
|
|
|
|
}
|
|
|
|
|
return 1;
|
2007-08-20 13:01:13 +02:00
|
|
|
|
}
|
2008-10-28 13:42:53 +01:00
|
|
|
|
return 0;
|
2007-08-20 13:01:13 +02:00
|
|
|
|
}
|
2007-12-13 13:51:38 +01:00
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
|
void
|
2008-02-28 16:11:22 +01:00
|
|
|
|
uart_set_mode(unsigned mode)
|
2007-08-20 13:01:13 +02:00
|
|
|
|
{
|
2009-06-29 14:46:49 +02:00
|
|
|
|
/* do nothing if the mode is already set */
|
2008-10-28 13:42:53 +01:00
|
|
|
|
if(mode == uart_mode) {
|
2007-08-20 13:01:13 +02:00
|
|
|
|
return;
|
2008-03-28 17:06:28 +01:00
|
|
|
|
}
|
2007-08-20 13:01:13 +02:00
|
|
|
|
|
2009-06-29 14:46:49 +02:00
|
|
|
|
IE2 &= ~(URXIE1 | UTXIE1); /* disable irq */
|
|
|
|
|
uart_configure(mode); /* configure uart parameters */
|
2007-08-20 13:01:13 +02:00
|
|
|
|
uart_mode = mode;
|
|
|
|
|
|
2008-10-28 13:42:53 +01:00
|
|
|
|
if(uart_handler[mode] != NULL) {
|
2009-06-29 14:46:49 +02:00
|
|
|
|
IE2 |= URXIE1; /* Enable USART1 RX interrupt */
|
2008-03-28 17:06:28 +01:00
|
|
|
|
}
|
2007-08-20 13:01:13 +02:00
|
|
|
|
}
|
2007-12-13 13:51:38 +01:00
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
|
int
|
|
|
|
|
uart_get_mode(void)
|
2007-08-20 13:01:13 +02:00
|
|
|
|
{
|
2007-12-13 13:51:38 +01:00
|
|
|
|
return uart_mode;
|
|
|
|
|
}
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
2008-02-28 16:11:22 +01:00
|
|
|
|
interrupt(UART1RX_VECTOR)
|
|
|
|
|
uart_rx(void)
|
2007-12-13 13:51:38 +01:00
|
|
|
|
{
|
2009-06-29 14:46:49 +02:00
|
|
|
|
uart_handler_t handler = uart_handler[uart_mode];
|
2007-12-13 13:51:38 +01:00
|
|
|
|
int c;
|
|
|
|
|
|
2008-10-28 13:42:53 +01:00
|
|
|
|
if(!(IFG2 & URXIFG1)) {
|
2009-06-29 14:46:49 +02:00
|
|
|
|
/* If rising edge is detected, toggle & return */
|
2007-12-13 13:51:38 +01:00
|
|
|
|
uart_edge = 1;
|
|
|
|
|
U1TCTL &= ~URXSE;
|
|
|
|
|
U1TCTL |= URXSE;
|
|
|
|
|
_BIC_SR_IRQ(LPM3_bits);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
uart_edge = 0;
|
2008-10-28 13:42:53 +01:00
|
|
|
|
if(!(URCTL1 & RXERR)) {
|
2007-12-13 13:51:38 +01:00
|
|
|
|
c = UART_RX;
|
2008-10-28 13:42:53 +01:00
|
|
|
|
if(handler(c)) {
|
2007-12-13 13:51:38 +01:00
|
|
|
|
_BIC_SR_IRQ(LPM3_bits);
|
2007-08-20 13:01:13 +02:00
|
|
|
|
}
|
|
|
|
|
} else {
|
2009-06-29 14:46:49 +02:00
|
|
|
|
/* read out the char to clear the interrupt flags. */
|
2007-12-13 13:51:38 +01:00
|
|
|
|
c = UART_RX;
|
2007-08-20 13:01:13 +02:00
|
|
|
|
}
|
|
|
|
|
}
|