Paparazzi UAS  v5.0.5_stable-7-g4b8bbb7
Paparazzi is a free software Unmanned Aircraft System.
 All Data Structures 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  // disable interrups
36  ((uartRegs_t *)(p->reg_addr))->ier = 0x00; // disable all interrupts
37  ((uartRegs_t *)(p->reg_addr))->iir; // clear interrupt ID
38  ((uartRegs_t *)(p->reg_addr))->rbr; // clear receive register
39  ((uartRegs_t *)(p->reg_addr))->lsr; // clear line status register
40 }
41 
42 static inline void uart_enable_interrupts(struct uart_periph* p) {
43  // enable receiver interrupts
44  ((uartRegs_t *)(p->reg_addr))->ier = UIER_ERBFI;
45 }
46 
47 static inline void uart_set_baudrate(struct uart_periph* p, uint32_t baud) {
48  /* calculate the baudrate */
49  uint32_t _baud_reg_val = (uint16_t)((PCLK / (((float)baud) * 16.0)) + 0.5);
50  /* select divisor latches */
51  ((uartRegs_t *)(p->reg_addr))->lcr = ULCR_DLAB_ENABLE;
52  /* set for baud low byte */
53  ((uartRegs_t *)(p->reg_addr))->dll = (uint8_t)_baud_reg_val;
54  /* set for baud high byte */
55  ((uartRegs_t *)(p->reg_addr))->dlm = (uint8_t)(_baud_reg_val >> 8);
56 
57  // set the number of characters and other
58  // user specified operating parameters
59  // For now: hard wired configuration 8 bits 1 stop no parity
60  // fifo triger -> 8 bytes
61  ((uartRegs_t *)(p->reg_addr))->lcr = (UART_8N1 & ~ULCR_DLAB_ENABLE);
62  ((uartRegs_t *)(p->reg_addr))->fcr = UART_FIFO_8;
63 }
64 
67  uart_set_baudrate(p, baud);
69 }
70 
71 void uart_transmit(struct uart_periph* p, uint8_t data ) {
72  uint16_t temp;
73  unsigned cpsr;
74 
75  temp = (p->tx_insert_idx + 1) % UART_TX_BUFFER_SIZE;
76 
77  if (temp == p->tx_extract_idx) {
78  return; // no room
79  }
80 
81  cpsr = disableIRQ(); // disable global interrupts
82  ((uartRegs_t *)(p->reg_addr))->ier &= ~UIER_ETBEI; // disable TX interrupts
83  restoreIRQ(cpsr); // restore global interrupts
84 
85  // check if in process of sending data
86  if (p->tx_running) {
87  // add to queue
88  p->tx_buf[p->tx_insert_idx] = data;
89  p->tx_insert_idx = temp;
90  } else {
91  // set running flag and write to output register
92  p->tx_running = 1;
93  ((uartRegs_t *)(p->reg_addr))->thr = data;
94  }
95 
96  cpsr = disableIRQ(); // disable global interrupts
97  ((uartRegs_t *)(p->reg_addr))->ier |= UIER_ETBEI; // enable TX interrupts
98  restoreIRQ(cpsr); // restore global interrupts
99 }
100 
101 static inline void uart_ISR(struct uart_periph* p)
102 {
103  uint8_t iid;
104  // loop until not more interrupt sources
105  while (((iid = ((uartRegs_t *)(p->reg_addr))->iir) & UIIR_NO_INT) == 0)
106  {
107  // identify & process the highest priority interrupt
108  switch (iid & UIIR_ID_MASK)
109  {
110  case UIIR_RLS_INT: // Receive Line Status
111  ((uartRegs_t *)(p->reg_addr))->lsr; // read LSR to clear
112  break;
113 
114  case UIIR_CTI_INT: // Character Timeout Indicator
115  case UIIR_RDA_INT: // Receive Data Available
116  do
117  {
118  uint16_t temp;
119 
120  // calc next insert index & store character
121  temp = (p->rx_insert_idx + 1) % UART_RX_BUFFER_SIZE;
122  p->rx_buf[p->rx_insert_idx] = ((uartRegs_t *)(p->reg_addr))->rbr;
123 
124  // check for more room in queue
125  if (temp != p->rx_extract_idx)
126  p->rx_insert_idx = temp; // update insert index
127  }
128  while (((uartRegs_t *)(p->reg_addr))->lsr & ULSR_RDR);
129 
130  break;
131 
132  case UIIR_THRE_INT: // Transmit Holding Register Empty
133  while (((uartRegs_t *)(p->reg_addr))->lsr & ULSR_THRE)
134  {
135  // check if more data to send
136  if (p->tx_insert_idx != p->tx_extract_idx)
137  {
138  ((uartRegs_t *)(p->reg_addr))->thr = p->tx_buf[p->tx_extract_idx];
139  p->tx_extract_idx++;
141  }
142  else
143  {
144  // no
145  p->tx_running = 0; // clear running flag
146  break;
147  }
148  }
149 
150  break;
151 
152  default: // Unknown
153  ((uartRegs_t *)(p->reg_addr))->lsr;
154  ((uartRegs_t *)(p->reg_addr))->rbr;
155  break;
156  }
157  }
158 }
159 
160 #ifdef USE_UART0
161 
162 #ifndef UART0_VIC_SLOT
163 #define UART0_VIC_SLOT 5
164 #endif
165 
166 /* by default enable UART Tx and Rx */
167 #ifndef USE_UART0_TX
168  #ifdef USE_UART0_RX_ONLY
169  #warning "USE_UART0_RX_ONLY is deprecated, please set USE_UART0_TX=FALSE instead"
170  #define USE_UART0_TX FALSE
171  #else
172  #define USE_UART0_TX TRUE
173  #endif
174 #endif
175 #ifndef USE_UART0_RX
176 #define USE_UART0_RX TRUE
177 #endif
178 
179 void uart0_ISR(void) __attribute__((naked));
180 
181 void uart0_ISR(void) {
182  // perform proper ISR entry so thumb-interwork works properly
183  ISR_ENTRY();
184 
185  uart_ISR(&uart0);
186 
187  VICVectAddr = 0x00000000; // clear this interrupt from the VIC
188  ISR_EXIT(); // recover registers and return
189 }
190 
191 void uart0_init( void ) {
192 
193  uart_periph_init(&uart0);
194  uart0.reg_addr = UART0_BASE;
195 
196 #if USE_UART0_RX && USE_UART0_TX
197  // set port pins for UART0
199 #elif USE_UART0_RX
200  // only use the RX0 P0.1 pin, no TX
202 #elif USE_UART0_TX
203  // only use tx
204  PINSEL0 = (PINSEL0 & ~U0_PINMASK_TX) | U0_PINSEL_TX;
205 #endif
206 
207  // initialize uart parameters
208  uart_set_baudrate(&uart0, UART0_BAUD);
209 
210  // initialize the interrupt vector
211  VICIntSelect &= ~VIC_BIT(VIC_UART0); // UART0 selected as IRQ
212  VICIntEnable = VIC_BIT(VIC_UART0); // UART0 interrupt enabled
213  _VIC_CNTL(UART0_VIC_SLOT) = VIC_ENABLE | VIC_UART0;
214  _VIC_ADDR(UART0_VIC_SLOT) = (uint32_t)uart0_ISR; // address of the ISR
215 
216  uart_enable_interrupts(&uart0);
217 }
218 
219 #endif /* USE_UART0 */
220 
221 #ifdef USE_UART1
222 
223 #ifndef UART1_VIC_SLOT
224 #define UART1_VIC_SLOT 6
225 #endif
226 
227 /* by default enable UART Tx and Rx */
228 #ifndef USE_UART1_TX
229  #ifdef USE_UART1_RX_ONLY
230  #warning "USE_UART1_RX_ONLY is deprecated, please set USE_UART1_TX=FALSE instead"
231  #define USE_UART1_TX FALSE
232  #else
233  #define USE_UART1_TX TRUE
234  #endif
235 #endif
236 #ifndef USE_UART1_RX
237 #define USE_UART1_RX TRUE
238 #endif
239 
240 void uart1_ISR(void) __attribute__((naked));
241 
242 void uart1_ISR(void) {
243  // perform proper ISR entry so thumb-interwork works properly
244  ISR_ENTRY();
245 
246  uart_ISR(&uart1);
247 
248  VICVectAddr = 0x00000000; // clear this interrupt from the VIC
249  ISR_EXIT(); // recover registers and return
250 }
251 
252 void uart1_init( void ) {
253 
254  uart_periph_init(&uart1);
255  uart1.reg_addr = UART1_BASE;
256 
257 #if USE_UART1_RX && USE_UART0_TX
258  // set port pins for UART1
260 #elif USE_UART1_RX
261  // only use the RX0 P0.1 pin, no TX
263 #elif USE_UART1_TX
264  // only use tx
265  PINSEL0 = (PINSEL0 & ~U1_PINMASK_TX) | U1_PINSEL_TX;
266 #endif
267 
268  uart_set_baudrate(&uart1, UART1_BAUD);
269 
270  // initialize the interrupt vector
271  VICIntSelect &= ~VIC_BIT(VIC_UART1); // UART1 selected as IRQ
272  VICIntEnable = VIC_BIT(VIC_UART1); // UART1 interrupt enabled
273  _VIC_CNTL(UART1_VIC_SLOT) = VIC_ENABLE | VIC_UART1;
274  _VIC_ADDR(UART1_VIC_SLOT) = (uint32_t)uart1_ISR; // address of the ISR
275 
276  // enable receiver interrupts
277  uart_enable_interrupts(&uart1);
278 }
279 
280 #endif
281 
#define VICIntSelect
Definition: LPC21xx.h:430
unsigned short uint16_t
Definition: types.h:16
#define VIC_UART0
Definition: lpcVIC.h:74
arch independent UART (Universal Asynchronous Receiver/Transmitter) API
#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
uint8_t tx_running
Definition: uart.h:65
#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:37
#define UIER_ERBFI
Definition: lpcUART.h:58
void * reg_addr
UART Register.
Definition: uart.h:67
#define PCLK
Definition: booz_1.0.h:18
#define U1_PINSEL_RX
Definition: LPC21xx.h:135
#define VIC_UART1
Definition: lpcVIC.h:75
uint16_t tx_extract_idx
Definition: uart.h:64
static void uart_ISR(struct uart_periph *p)
Definition: uart_arch.c:101
void uart_transmit(struct uart_periph *p, uint8_t data)
Definition: uart_arch.c:71
#define _VIC_ADDR(idx)
Definition: armVIC.h:20
#define UIIR_NO_INT
Definition: lpcUART.h:64
UART peripheral.
Definition: uart.h:56
static void uart_enable_interrupts(struct uart_periph *p)
Definition: uart_arch.c:42
#define UIIR_ID_MASK
Definition: lpcUART.h:70
#define UART_TX_BUFFER_SIZE
Definition: uart.h:35
#define UIIR_CTI_INT
Definition: lpcUART.h:69
#define U0_PINMASK_RX
Definition: LPC21xx.h:116
static void uart_set_baudrate(struct uart_periph *p, uint32_t baud)
Definition: uart_arch.c:47
#define VICVectAddr
Definition: LPC21xx.h:436
void uart_periph_init(struct uart_periph *p)
Definition: uart.c:53
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_insert_idx
Definition: uart.h:59
#define UART0_BASE
Definition: LPC21xx.h:112
#define VIC_BIT(chan)
Definition: lpcVIC.h:105
#define UIIR_RLS_INT
Definition: lpcUART.h:68
uint8_t tx_buf[UART_TX_BUFFER_SIZE]
Transmit buffer.
Definition: uart.h:62
#define PINSEL0
Definition: LPC21xx.h:347
#define U0_PINMASK
Definition: LPC21xx.h:114
unsigned char uint8_t
Definition: types.h:14
#define UART_FIFO_8
Definition: uart_arch.h:53
unsigned disableIRQ(void)
Definition: armVIC.c:33
#define ISR_EXIT()
Definition: armVIC.h:61
#define ULSR_THRE
Definition: lpcUART.h:107
uint16_t tx_insert_idx
Definition: uart.h:63
#define VICIntEnable
Definition: LPC21xx.h:431
uint8_t rx_buf[UART_RX_BUFFER_SIZE]
Receive buffer.
Definition: uart.h:58
static float p[2][2]
static void uart_disable_interrupts(struct uart_periph *p)
Definition: uart_arch.c:34
uint16_t rx_extract_idx
Definition: uart.h:60
#define UIIR_THRE_INT
Definition: lpcUART.h:66
#define UART_RX_BUFFER_SIZE
Definition: uart.h:34
#define ISR_ENTRY()
Definition: armVIC.h:40
#define VIC_ENABLE
Definition: lpcVIC.h:102
void uart_periph_set_baudrate(struct uart_periph *p, uint32_t baud)
Definition: uart_arch.c:65
#define ULCR_DLAB_ENABLE
Definition: lpcUART.h:94