Paparazzi UAS  v5.15_devel-59-g8c145b7
Paparazzi is a free software Unmanned Aircraft System.
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
uart_arch.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2008-2010 The Paparazzi Team
3  *
4  * This file is part of paparazzi.
5  *
6  * paparazzi is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2, or (at your option)
9  * any later version.
10  *
11  * paparazzi is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with paparazzi; see the file COPYING. If not, write to
18  * the Free Software Foundation, 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  *
21  */
22 
31 #include "mcu_periph/uart.h"
32 #include "armVIC.h"
33 
34 static inline void uart_disable_interrupts(struct uart_periph *p)
35 {
36  // disable interrups
37  ((uartRegs_t *)(p->reg_addr))->ier = 0x00; // disable all interrupts
38  ((uartRegs_t *)(p->reg_addr))->iir; // clear interrupt ID
39  ((uartRegs_t *)(p->reg_addr))->rbr; // clear receive register
40  ((uartRegs_t *)(p->reg_addr))->lsr; // clear line status register
41 }
42 
43 static inline void uart_enable_interrupts(struct uart_periph *p)
44 {
45  // enable receiver interrupts
46  ((uartRegs_t *)(p->reg_addr))->ier = UIER_ERBFI;
47 }
48 
49 static inline void uart_set_baudrate(struct uart_periph *p, uint32_t baud)
50 {
51  p->baudrate = baud;
52 
53  /* calculate the baudrate */
54  uint32_t _baud_reg_val = (uint16_t)((PCLK / (((float)baud) * 16.0)) + 0.5);
55  /* select divisor latches */
56  ((uartRegs_t *)(p->reg_addr))->lcr = ULCR_DLAB_ENABLE;
57  /* set for baud low byte */
58  ((uartRegs_t *)(p->reg_addr))->dll = (uint8_t)_baud_reg_val;
59  /* set for baud high byte */
60  ((uartRegs_t *)(p->reg_addr))->dlm = (uint8_t)(_baud_reg_val >> 8);
61 
62  // set the number of characters and other
63  // user specified operating parameters
64  // For now: hard wired configuration 8 bits 1 stop no parity
65  // fifo triger -> 8 bytes
66  ((uartRegs_t *)(p->reg_addr))->lcr = (UART_8N1 & ~ULCR_DLAB_ENABLE);
67  ((uartRegs_t *)(p->reg_addr))->fcr = UART_FIFO_8;
68 }
69 
71 {
73  uart_set_baudrate(p, baud);
75 }
76 
77 void uart_periph_set_bits_stop_parity(struct uart_periph *p __attribute__((unused)),
78  uint8_t bits __attribute__((unused)), uint8_t stop __attribute__((unused)), uint8_t __attribute__((unused)) parity)
79 {
80  // TBD
81 }
82 
83 void uart_put_byte(struct uart_periph *p, long fd __attribute__((unused)), uint8_t data)
84 {
85  uint16_t temp;
86  unsigned cpsr;
87 
88  temp = (p->tx_insert_idx + 1) % UART_TX_BUFFER_SIZE;
89 
90  if (temp == p->tx_extract_idx) {
91  return; // no room
92  }
93 
94  cpsr = disableIRQ(); // disable global interrupts
95  ((uartRegs_t *)(p->reg_addr))->ier &= ~UIER_ETBEI; // disable TX interrupts
96  restoreIRQ(cpsr); // restore global interrupts
97 
98  // check if in process of sending data
99  if (p->tx_running) {
100  // add to queue
101  p->tx_buf[p->tx_insert_idx] = data;
102  p->tx_insert_idx = temp;
103  } else {
104  // set running flag and write to output register
105  p->tx_running = 1;
106  ((uartRegs_t *)(p->reg_addr))->thr = data;
107  }
108 
109  cpsr = disableIRQ(); // disable global interrupts
110  ((uartRegs_t *)(p->reg_addr))->ier |= UIER_ETBEI; // enable TX interrupts
111  restoreIRQ(cpsr); // restore global interrupts
112 }
113 
114 static inline void uart_ISR(struct uart_periph *p)
115 {
116  uint8_t iid;
117  // loop until not more interrupt sources
118  while (((iid = ((uartRegs_t *)(p->reg_addr))->iir) & UIIR_NO_INT) == 0) {
119  // identify & process the highest priority interrupt
120  switch (iid & UIIR_ID_MASK) {
121  case UIIR_RLS_INT: // Receive Line Status
122  ((uartRegs_t *)(p->reg_addr))->lsr; // read LSR to clear
123  break;
124 
125  case UIIR_CTI_INT: // Character Timeout Indicator
126  case UIIR_RDA_INT: // Receive Data Available
127  do {
128  uint16_t temp;
129 
130  // calc next insert index & store character
131  temp = (p->rx_insert_idx + 1) % UART_RX_BUFFER_SIZE;
132  p->rx_buf[p->rx_insert_idx] = ((uartRegs_t *)(p->reg_addr))->rbr;
133 
134  // check for more room in queue
135  if (temp != p->rx_extract_idx) {
136  p->rx_insert_idx = temp; // update insert index
137  }
138  } while (((uartRegs_t *)(p->reg_addr))->lsr & ULSR_RDR);
139 
140  break;
141 
142  case UIIR_THRE_INT: // Transmit Holding Register Empty
143  while (((uartRegs_t *)(p->reg_addr))->lsr & ULSR_THRE) {
144  // check if more data to send
145  if (p->tx_insert_idx != p->tx_extract_idx) {
146  ((uartRegs_t *)(p->reg_addr))->thr = p->tx_buf[p->tx_extract_idx];
147  p->tx_extract_idx++;
149  } else {
150  // no
151  p->tx_running = 0; // clear running flag
152  break;
153  }
154  }
155 
156  break;
157 
158  default: // Unknown
159  ((uartRegs_t *)(p->reg_addr))->lsr;
160  ((uartRegs_t *)(p->reg_addr))->rbr;
161  break;
162  }
163  }
164 }
165 
166 #if USE_UART0
167 
168 #ifndef UART0_VIC_SLOT
169 #define UART0_VIC_SLOT 5
170 #endif
171 
172 /* by default enable UART Tx and Rx */
173 #ifndef USE_UART0_TX
174 #ifdef USE_UART0_RX_ONLY
175 #warning "USE_UART0_RX_ONLY is deprecated, please set USE_UART0_TX=FALSE instead"
176 #define USE_UART0_TX FALSE
177 #else
178 #define USE_UART0_TX TRUE
179 #endif
180 #endif
181 #ifndef USE_UART0_RX
182 #define USE_UART0_RX TRUE
183 #endif
184 
185 void uart0_ISR(void) __attribute__((naked));
186 
187 void uart0_ISR(void)
188 {
189  // perform proper ISR entry so thumb-interwork works properly
190  ISR_ENTRY();
191 
192  uart_ISR(&uart0);
193 
194  VICVectAddr = 0x00000000; // clear this interrupt from the VIC
195  ISR_EXIT(); // recover registers and return
196 }
197 
198 void uart0_init(void)
199 {
200 
201  uart_periph_init(&uart0);
202  uart0.reg_addr = UART0_BASE;
203 
204 #if USE_UART0_RX && USE_UART0_TX
205  // set port pins for UART0
207 #elif USE_UART0_RX
208  // only use the RX0 P0.1 pin, no TX
210 #elif USE_UART0_TX
211  // only use tx
212  PINSEL0 = (PINSEL0 & ~U0_PINMASK_TX) | U0_PINSEL_TX;
213 #endif
214 
215  // initialize uart parameters
216  uart_set_baudrate(&uart0, UART0_BAUD);
217 
218  // initialize the interrupt vector
219  VICIntSelect &= ~VIC_BIT(VIC_UART0); // UART0 selected as IRQ
220  VICIntEnable = VIC_BIT(VIC_UART0); // UART0 interrupt enabled
221  _VIC_CNTL(UART0_VIC_SLOT) = VIC_ENABLE | VIC_UART0;
222  _VIC_ADDR(UART0_VIC_SLOT) = (uint32_t)uart0_ISR; // address of the ISR
223 
224  uart_enable_interrupts(&uart0);
225 }
226 
227 #endif /* USE_UART0 */
228 
229 #if USE_UART1
230 
231 #ifndef UART1_VIC_SLOT
232 #define UART1_VIC_SLOT 6
233 #endif
234 
235 /* by default enable UART Tx and Rx */
236 #ifndef USE_UART1_TX
237 #ifdef USE_UART1_RX_ONLY
238 #warning "USE_UART1_RX_ONLY is deprecated, please set USE_UART1_TX=FALSE instead"
239 #define USE_UART1_TX FALSE
240 #else
241 #define USE_UART1_TX TRUE
242 #endif
243 #endif
244 #ifndef USE_UART1_RX
245 #define USE_UART1_RX TRUE
246 #endif
247 
248 void uart1_ISR(void) __attribute__((naked));
249 
250 void uart1_ISR(void)
251 {
252  // perform proper ISR entry so thumb-interwork works properly
253  ISR_ENTRY();
254 
255  uart_ISR(&uart1);
256 
257  VICVectAddr = 0x00000000; // clear this interrupt from the VIC
258  ISR_EXIT(); // recover registers and return
259 }
260 
261 void uart1_init(void)
262 {
263 
264  uart_periph_init(&uart1);
265  uart1.reg_addr = UART1_BASE;
266 
267 #if USE_UART1_RX && USE_UART0_TX
268  // set port pins for UART1
270 #elif USE_UART1_RX
271  // only use the RX0 P0.1 pin, no TX
273 #elif USE_UART1_TX
274  // only use tx
275  PINSEL0 = (PINSEL0 & ~U1_PINMASK_TX) | U1_PINSEL_TX;
276 #endif
277 
278  uart_set_baudrate(&uart1, UART1_BAUD);
279 
280  // initialize the interrupt vector
281  VICIntSelect &= ~VIC_BIT(VIC_UART1); // UART1 selected as IRQ
282  VICIntEnable = VIC_BIT(VIC_UART1); // UART1 interrupt enabled
283  _VIC_CNTL(UART1_VIC_SLOT) = VIC_ENABLE | VIC_UART1;
284  _VIC_ADDR(UART1_VIC_SLOT) = (uint32_t)uart1_ISR; // address of the ISR
285 
286  // enable receiver interrupts
287  uart_enable_interrupts(&uart1);
288 }
289 
290 #endif
291 
uint8_t tx_buf[UART_TX_BUFFER_SIZE]
Transmit buffer.
Definition: uart.h:76
#define VICIntSelect
Definition: LPC21xx.h:430
unsigned short uint16_t
Definition: types.h:16
#define VIC_UART0
Definition: lpcVIC.h:74
uint8_t rx_buf[UART_RX_BUFFER_SIZE]
Receive buffer.
Definition: uart.h:72
arch independent UART (Universal Asynchronous Receiver/Transmitter) API
void uart_periph_set_baudrate(struct uart_periph *p, uint32_t baud)
Set baudrate.
Definition: uart_arch.c:861
volatile uint8_t tx_running
Definition: uart.h:79
#define U1_PINMASK_RX
Definition: LPC21xx.h:136
#define U0_PINSEL
Definition: LPC21xx.h:113
#define U1_PINSEL
Definition: LPC21xx.h:133
#define U1_PINMASK
Definition: LPC21xx.h:134
#define _VIC_CNTL(idx)
Definition: armVIC.h:19
#define U0_PINSEL_RX
Definition: LPC21xx.h:115
#define UIER_ETBEI
Definition: lpcUART.h:59
#define UART_8N1
Definition: uart_arch.h:49
#define UIER_ERBFI
Definition: lpcUART.h:58
#define PCLK
Definition: booz_1.0.h:18
#define U1_PINSEL_RX
Definition: LPC21xx.h:135
#define VIC_UART1
Definition: lpcVIC.h:75
static void uart_ISR(struct uart_periph *p)
Definition: uart_arch.c:114
#define UART_RX_BUFFER_SIZE
Definition: uart_arch.h:31
#define _VIC_ADDR(idx)
Definition: armVIC.h:20
void * reg_addr
UART Register.
Definition: uart.h:81
#define UIIR_NO_INT
Definition: lpcUART.h:64
static void uart_enable_interrupts(struct uart_periph *p)
Definition: uart_arch.c:43
uint16_t rx_insert_idx
Definition: uart.h:73
#define UIIR_ID_MASK
Definition: lpcUART.h:70
#define UIIR_CTI_INT
Definition: lpcUART.h:69
UART peripheral.
Definition: uart.h:70
#define U0_PINMASK_RX
Definition: LPC21xx.h:116
static void uart_set_baudrate(struct uart_periph *p, uint32_t baud)
Definition: uart_arch.c:49
#define VICVectAddr
Definition: LPC21xx.h:436
void uart_periph_init(struct uart_periph *p)
Definition: uart.c:231
unsigned long uint32_t
Definition: types.h:18
#define ULSR_RDR
Definition: lpcUART.h:102
#define UIIR_RDA_INT
Definition: lpcUART.h:67
#define UART1_BASE
Definition: LPC21xx.h:132
unsigned restoreIRQ(unsigned oldCPSR)
Definition: armVIC.c:42
uint16_t rx_extract_idx
Definition: uart.h:74
#define UART0_BASE
Definition: LPC21xx.h:112
#define VIC_BIT(chan)
Definition: lpcVIC.h:105
uint16_t tx_insert_idx
Definition: uart.h:77
#define UIIR_RLS_INT
Definition: lpcUART.h:68
void uart_put_byte(struct uart_periph *p, long fd, uint8_t data)
Uart transmit implementation.
Definition: uart_arch.c:972
#define PINSEL0
Definition: LPC21xx.h:347
#define U0_PINMASK
Definition: LPC21xx.h:114
unsigned char uint8_t
Definition: types.h:14
void uart_periph_set_bits_stop_parity(struct uart_periph *p, uint8_t bits, uint8_t stop, uint8_t parity)
Set parity and stop bits.
Definition: uart_arch.c:890
#define UART_FIFO_8
Definition: uart_arch.h:65
unsigned disableIRQ(void)
Definition: armVIC.c:33
#define ISR_EXIT()
Definition: armVIC.h:61
#define ULSR_THRE
Definition: lpcUART.h:107
int fd
Definition: serial.c:26
#define VICIntEnable
Definition: LPC21xx.h:431
int baudrate
UART Baudrate.
Definition: uart.h:83
#define UART_TX_BUFFER_SIZE
Definition: uart_arch.h:34
static float p[2][2]
static void uart_disable_interrupts(struct uart_periph *p)
Definition: uart_arch.c:34
#define UIIR_THRE_INT
Definition: lpcUART.h:66
#define ISR_ENTRY()
Definition: armVIC.h:40
uint16_t tx_extract_idx
Definition: uart.h:78
#define VIC_ENABLE
Definition: lpcVIC.h:102
#define ULCR_DLAB_ENABLE
Definition: lpcUART.h:94