Contiki-NG
uart1.c
1/*
2 * Copyright (c) 2011, Swedish Institute of Computer Science
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the Institute nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30/*
31 * Yet another machine dependent MSP430X UART0 code.
32 * IF2, etc. can not be used here... need to abstract to some macros
33 * later.
34 */
35
36#include "contiki.h"
37#include <stdlib.h>
38#include "dev/uart1.h"
39#include "dev/watchdog.h"
40#include "isr_compat.h"
41
42static int (*uart1_input_handler)(unsigned char c);
43
44static volatile uint8_t transmitting;
45
46#ifdef UART1_CONF_RX_WITH_DMA
47#define RX_WITH_DMA UART1_CONF_RX_WITH_DMA
48#else /* UART1_CONF_RX_WITH_DMA */
49#define RX_WITH_DMA 1
50#endif /* UART1_CONF_RX_WITH_DMA */
51
52#if RX_WITH_DMA
53#define RXBUFSIZE 128
54
55static uint8_t rxbuf[RXBUFSIZE];
56static uint16_t last_size;
57static struct ctimer rxdma_timer;
58
59static void
60handle_rxdma_timer(void *ptr)
61{
62 uint16_t size;
63 size = DMA0SZ; /* Note: loop requires that size is less or eq to RXBUFSIZE */
64 while(last_size != size) {
65 uart1_input_handler((unsigned char)rxbuf[RXBUFSIZE - last_size]);
66 last_size--;
67 if(last_size == 0) {
68 last_size = RXBUFSIZE;
69 }
70 }
71
72 ctimer_reset(&rxdma_timer);
73}
74#endif /* RX_WITH_DMA */
75
76/*---------------------------------------------------------------------------*/
77uint8_t
78uart1_active(void)
79{
80 return (UCA1STAT & UCBUSY) | transmitting;
81}
82/*---------------------------------------------------------------------------*/
83void
84uart1_set_input(int (*input)(unsigned char c))
85{
86#if RX_WITH_DMA /* This needs to be called after ctimer process is started */
87 ctimer_set(&rxdma_timer, CLOCK_SECOND / 64, handle_rxdma_timer, NULL);
88#endif
89 uart1_input_handler = input;
90}
91/*---------------------------------------------------------------------------*/
92void
93uart1_writeb(unsigned char c)
94{
96 /* Loop until the transmission buffer is available. */
97 while((UCA1STAT & UCBUSY));
98
99 /* Transmit the data. */
100 UCA1TXBUF = c;
101}
102/*---------------------------------------------------------------------------*/
103/**
104 * Initalize the RS232 port.
105 *
106 */
107void
108uart1_init(unsigned long ubr)
109{
110 /* RS232 */
111 UCA1CTL1 |= UCSWRST; /* Hold peripheral in reset state */
112 UCA1CTL1 |= UCSSEL_2; /* CLK = SMCLK */
113
114 ubr = (MSP430_CPU_SPEED / ubr);
115 UCA1BR0 = ubr & 0xff;
116 UCA1BR1 = (ubr >> 8) & 0xff;
117 /* UCA1MCTL |= UCBRS_2 + UCBRF_0; // Modulation UCBRFx=0 */
118 UCA1MCTL = UCBRS_3; /* Modulation UCBRSx = 3 */
119
120 P4DIR |= BIT5;
121 P4OUT |= BIT5;
122 P5SEL |= BIT6 | BIT7; /* P5.6,7 = USCI_A1 TXD/RXD */
123
124 P4SEL |= BIT7;
125 P4DIR |= BIT7;
126
127 /*UCA1CTL1 &= ~UCSWRST;*/ /* Initialize USCI state machine */
128
129 transmitting = 0;
130
131 /* XXX Clear pending interrupts before enable */
132 UCA1IE &= ~UCRXIFG;
133 UCA1IE &= ~UCTXIFG;
134
135 UCA1CTL1 &= ~UCSWRST; /* Initialize USCI state machine **before** enabling interrupts */
136 UCA1IE |= UCRXIE; /* Enable UCA1 RX interrupt */
137
138#if RX_WITH_DMA
139 UCA1IE &= ~UCRXIE; /* disable USART1 RX interrupt */
140 /* UART1_RX trigger */
141 DMACTL0 = DMA0TSEL_20;
142
143 /* source address = RXBUF1 */
144 DMA0SA = (unsigned int)&UCA1RXBUF;
145 DMA0DA = (unsigned int)&rxbuf;
146 DMA0SZ = RXBUFSIZE;
147 last_size = RXBUFSIZE;
148 DMA0CTL = DMADT_4 + DMASBDB + DMADSTINCR_3 + DMAEN + DMAREQ;
149
150 msp430_add_lpm_req(MSP430_REQUIRE_LPM1);
151#endif /* RX_WITH_DMA */
152}
153/*---------------------------------------------------------------------------*/
154#if !RX_WITH_DMA
155ISR(USCI_A1, uart1_rx_interrupt)
156{
157 uint8_t c;
158
159 if(UCA1IV == 2) {
160 if(UCA1STAT & UCRXERR) {
161 c = UCA1RXBUF; /* Clear error flags by forcing a dummy read. */
162 } else {
163 c = UCA1RXBUF;
164 if(uart1_input_handler != NULL) {
165 if(uart1_input_handler(c)) {
166 LPM4_EXIT;
167 }
168 }
169 }
170 }
171}
172#endif /* !RX_WITH_DMA */
173/*---------------------------------------------------------------------------*/
void watchdog_periodic(void)
Writes the WDT clear sequence.
Definition: watchdog.c:85
#define CLOCK_SECOND
A second, measured in system clock time.
Definition: clock.h:82
void ctimer_set(struct ctimer *c, clock_time_t t, void(*f)(void *), void *ptr)
Set a callback timer.
Definition: ctimer.c:99
void ctimer_reset(struct ctimer *c)
Reset a callback timer with the same interval as was previously set.
Definition: ctimer.c:125
static uint8_t transmitting(void)
Check the RF's TX status.
Definition: ieee-mode.c:285
static void input(void)
Process a received 6lowpan packet.
Definition: sicslowpan.c:1833
A brief description of what this file is.
void uart1_init(unsigned long ubr)
Initalize the RS232 port.
Definition: uart1.c:142