uart1.c
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include <stdlib.h>
00037 #include <io.h>
00038 #include <signal.h>
00039
00040 #include <stdio.h>
00041
00042 #include "sys/energest.h"
00043 #include "dev/uart1.h"
00044 #include "dev/watchdog.h"
00045 #include "sys/ctimer.h"
00046 #include "lib/ringbuf.h"
00047
00048 static int (*uart1_input_handler)(unsigned char c);
00049 static volatile uint8_t rx_in_progress;
00050
00051 static volatile uint8_t transmitting;
00052
00053 #ifdef UART1_CONF_TX_WITH_INTERRUPT
00054 #define TX_WITH_INTERRUPT UART1_CONF_TX_WITH_INTERRUPT
00055 #else
00056 #define TX_WITH_INTERRUPT 0
00057 #endif
00058
00059 #ifdef UART1_CONF_RX_WITH_DMA
00060 #define RX_WITH_DMA UART1_CONF_RX_WITH_DMA
00061 #else
00062 #define RX_WITH_DMA 0
00063 #endif
00064
00065 #if RX_WITH_DMA
00066 #warning RX_WITH_DMA ENABLED - WILL NOT WORK WITH MSPSIM / COOJA!
00067 #endif
00068
00069 #if TX_WITH_INTERRUPT
00070 #define TXBUFSIZE 128
00071
00072 static struct ringbuf txbuf;
00073 static uint8_t txbuf_data[TXBUFSIZE];
00074 #endif
00075
00076 #if RX_WITH_DMA
00077 #define RXBUFSIZE 128
00078
00079 static uint8_t rxbuf[RXBUFSIZE];
00080 static uint16_t last_size;
00081 static struct ctimer rxdma_timer;
00082
00083 static void
00084 handle_rxdma_timer(void *ptr)
00085 {
00086 uint16_t size;
00087 size = DMA0SZ;
00088 while(last_size != size) {
00089
00090
00091 uart1_input_handler((unsigned char)rxbuf[RXBUFSIZE - last_size]);
00092 last_size--;
00093 if(last_size == 0) last_size = RXBUFSIZE;
00094 }
00095
00096 ctimer_reset(&rxdma_timer);
00097 }
00098 #endif
00099
00100
00101 uint8_t
00102 uart1_active(void)
00103 {
00104 return ((~ UTCTL1) & TXEPT) | rx_in_progress | transmitting;
00105 }
00106
00107 void
00108 uart1_set_input(int (*input)(unsigned char c))
00109 {
00110 #if RX_WITH_DMA
00111 ctimer_set(&rxdma_timer, CLOCK_SECOND/64, handle_rxdma_timer, NULL);
00112 #endif
00113 uart1_input_handler = input;
00114 }
00115
00116 void
00117 uart1_writeb(unsigned char c)
00118 {
00119 watchdog_periodic();
00120 #if TX_WITH_INTERRUPT
00121
00122
00123
00124
00125 while(ringbuf_put(&txbuf, c) == 0);
00126
00127
00128
00129 if(transmitting == 0) {
00130 transmitting = 1;
00131
00132
00133
00134 TXBUF1 = ringbuf_get(&txbuf);
00135 }
00136
00137 #else
00138
00139
00140 while((IFG2 & UTXIFG1) == 0);
00141
00142
00143 TXBUF1 = c;
00144 #endif
00145 }
00146
00147
00148
00149
00150
00151 void
00152 uart1_init(unsigned long ubr)
00153 {
00154
00155 P3DIR &= ~0x80;
00156 P3DIR |= 0x40;
00157 P3SEL |= 0xC0;
00158
00159 UCTL1 = SWRST | CHAR;
00160
00161 #if 0
00162 U1RCTL &= ~URXEIE;
00163 #endif
00164
00165 UTCTL1 = SSEL1;
00166
00167 UBR01 = ubr;
00168 UBR11 = ubr >> 8;
00169
00170
00171
00172
00173 switch(ubr) {
00174
00175 #if F_CPU == 3900000ul
00176
00177 case UART1_BAUD2UBR(115200ul):
00178 UMCTL1 = 0xF7;
00179 break;
00180 case UART1_BAUD2UBR(57600ul):
00181 UMCTL1 = 0xED;
00182 break;
00183 case UART1_BAUD2UBR(38400ul):
00184 UMCTL1 = 0xD6;
00185 break;
00186 case UART1_BAUD2UBR(19200ul):
00187 UMCTL1 = 0x08;
00188 break;
00189 case UART1_BAUD2UBR(9600ul):
00190 UMCTL1 = 0x22;
00191 break;
00192
00193 #elif F_CPU == 2457600ul
00194
00195 case UART1_BAUD2UBR(115200ul):
00196 UMCTL1 = 0x4A;
00197 break;
00198 case UART1_BAUD2UBR(57600ul):
00199 UMCTL1 = 0x5B;
00200 break;
00201 default:
00202
00203 UMCTL1 = 0x00;
00204
00205 #else
00206
00207 #error Unsupported CPU speed in uart1.c
00208
00209 #endif
00210 }
00211
00212 ME2 &= ~USPIE1;
00213 ME2 |= (UTXE1 | URXE1);
00214
00215 UCTL1 &= ~SWRST;
00216
00217
00218 IFG2 &= ~URXIFG1;
00219 U1TCTL |= URXSE;
00220
00221 rx_in_progress = 0;
00222
00223 transmitting = 0;
00224
00225 IE2 |= URXIE1;
00226 #if TX_WITH_INTERRUPT
00227 ringbuf_init(&txbuf, txbuf_data, sizeof(txbuf_data));
00228 IE2 |= UTXIE1;
00229 #endif
00230
00231 #if RX_WITH_DMA
00232 IE2 &= ~URXIE1;
00233
00234 DMACTL0 = DMA0TSEL_9;
00235
00236
00237 DMA0SA = (unsigned int) &RXBUF1;
00238 DMA0DA = (unsigned int) &rxbuf;
00239 DMA0SZ = RXBUFSIZE;
00240 last_size = RXBUFSIZE;
00241 DMA0CTL = DMADT_4 + DMASBDB + DMADSTINCR_3 + DMAEN + DMAREQ;
00242
00243 msp430_add_lpm_req(MSP430_REQUIRE_LPM1);
00244 #endif
00245
00246 }
00247
00248
00249
00250 #if !RX_WITH_DMA
00251 interrupt(UART1RX_VECTOR)
00252 uart1_rx_interrupt(void)
00253 {
00254 uint8_t c;
00255 ENERGEST_ON(ENERGEST_TYPE_IRQ);
00256
00257 if(!(URXIFG1 & IFG2)) {
00258
00259 U1TCTL &= ~URXSE;
00260 U1TCTL |= URXSE;
00261 rx_in_progress = 1;
00262 LPM4_EXIT;
00263 } else {
00264 rx_in_progress = 0;
00265
00266 if(URCTL1 & RXERR) {
00267 c = RXBUF1;
00268 } else {
00269 c = RXBUF1;
00270 if(uart1_input_handler != NULL) {
00271 if(uart1_input_handler(c)) {
00272 LPM4_EXIT;
00273 }
00274 }
00275 }
00276 }
00277
00278 ENERGEST_OFF(ENERGEST_TYPE_IRQ);
00279 }
00280 #endif
00281
00282 #if TX_WITH_INTERRUPT
00283 interrupt(UART1TX_VECTOR)
00284 uart1_tx_interrupt(void)
00285 {
00286 ENERGEST_ON(ENERGEST_TYPE_IRQ);
00287
00288 if(ringbuf_elements(&txbuf) == 0) {
00289 transmitting = 0;
00290 } else {
00291 TXBUF1 = ringbuf_get(&txbuf);
00292 }
00293
00294 ENERGEST_OFF(ENERGEST_TYPE_IRQ);
00295 }
00296 #endif
00297