Paparazzi UAS  v5.2.2_stable-0-gd6b9f29
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_periph_set_bits_stop_parity(struct uart_periph* p __attribute__((unused)), uint8_t bits __attribute__((unused)), uint8_t stop __attribute__((unused)), uint8_t __attribute__((unused)) parity) {
72  // TBD
73 }
74 
75 void uart_transmit(struct uart_periph* p, uint8_t data ) {
76  uint16_t temp;
77  unsigned cpsr;
78 
79  temp = (p->tx_insert_idx + 1) % UART_TX_BUFFER_SIZE;
80 
81  if (temp == p->tx_extract_idx) {
82  return; // no room
83  }
84 
85  cpsr = disableIRQ(); // disable global interrupts
86  ((uartRegs_t *)(p->reg_addr))->ier &= ~UIER_ETBEI; // disable TX interrupts
87  restoreIRQ(cpsr); // restore global interrupts
88 
89  // check if in process of sending data
90  if (p->tx_running) {
91  // add to queue
92  p->tx_buf[p->tx_insert_idx] = data;
93  p->tx_insert_idx = temp;
94  } else {
95  // set running flag and write to output register
96  p->tx_running = 1;
97  ((uartRegs_t *)(p->reg_addr))->thr = data;
98  }
99 
100  cpsr = disableIRQ(); // disable global interrupts
101  ((uartRegs_t *)(p->reg_addr))->ier |= UIER_ETBEI; // enable TX interrupts
102  restoreIRQ(cpsr); // restore global interrupts
103 }
104 
105 static inline void uart_ISR(struct uart_periph* p)
106 {
107  uint8_t iid;
108  // loop until not more interrupt sources
109  while (((iid = ((uartRegs_t *)(p->reg_addr))->iir) & UIIR_NO_INT) == 0)
110  {
111  // identify & process the highest priority interrupt
112  switch (iid & UIIR_ID_MASK)
113  {
114  case UIIR_RLS_INT: // Receive Line Status
115  ((uartRegs_t *)(p->reg_addr))->lsr; // read LSR to clear
116  break;
117 
118  case UIIR_CTI_INT: // Character Timeout Indicator
119  case UIIR_RDA_INT: // Receive Data Available
120  do
121  {
122  uint16_t temp;
123 
124  // calc next insert index & store character
125  temp = (p->rx_insert_idx + 1) % UART_RX_BUFFER_SIZE;
126  p->rx_buf[p->rx_insert_idx] = ((uartRegs_t *)(p->reg_addr))->rbr;
127 
128  // check for more room in queue
129  if (temp != p->rx_extract_idx)
130  p->rx_insert_idx = temp; // update insert index
131  }
132  while (((uartRegs_t *)(p->reg_addr))->lsr & ULSR_RDR);
133 
134  break;
135 
136  case UIIR_THRE_INT: // Transmit Holding Register Empty
137  while (((uartRegs_t *)(p->reg_addr))->lsr & ULSR_THRE)
138  {
139  // check if more data to send
140  if (p->tx_insert_idx != p->tx_extract_idx)
141  {
142  ((uartRegs_t *)(p->reg_addr))->thr = p->tx_buf[p->tx_extract_idx];
143  p->tx_extract_idx++;
145  }
146  else
147  {
148  // no
149  p->tx_running = 0; // clear running flag
150  break;
151  }
152  }
153 
154  break;
155 
156  default: // Unknown
157  ((uartRegs_t *)(p->reg_addr))->lsr;
158  ((uartRegs_t *)(p->reg_addr))->rbr;
159  break;
160  }
161  }
162 }
163 
164 #if USE_UART0
165 
166 #ifndef UART0_VIC_SLOT
167 #define UART0_VIC_SLOT 5
168 #endif
169 
170 /* by default enable UART Tx and Rx */
171 #ifndef USE_UART0_TX
172  #ifdef USE_UART0_RX_ONLY
173  #warning "USE_UART0_RX_ONLY is deprecated, please set USE_UART0_TX=FALSE instead"
174  #define USE_UART0_TX FALSE
175  #else
176  #define USE_UART0_TX TRUE
177  #endif
178 #endif
179 #ifndef USE_UART0_RX
180 #define USE_UART0_RX TRUE
181 #endif
182 
183 void uart0_ISR(void) __attribute__((naked));
184 
185 void uart0_ISR(void) {
186  // perform proper ISR entry so thumb-interwork works properly
187  ISR_ENTRY();
188 
189  uart_ISR(&uart0);
190 
191  VICVectAddr = 0x00000000; // clear this interrupt from the VIC
192  ISR_EXIT(); // recover registers and return
193 }
194 
195 void uart0_init( void ) {
196 
197  uart_periph_init(&uart0);
198  uart0.reg_addr = UART0_BASE;
199 
200 #if USE_UART0_RX && USE_UART0_TX
201  // set port pins for UART0
203 #elif USE_UART0_RX
204  // only use the RX0 P0.1 pin, no TX
206 #elif USE_UART0_TX
207  // only use tx
208  PINSEL0 = (PINSEL0 & ~U0_PINMASK_TX) | U0_PINSEL_TX;
209 #endif
210 
211  // initialize uart parameters
212  uart_set_baudrate(&uart0, UART0_BAUD);
213 
214  // initialize the interrupt vector
215  VICIntSelect &= ~VIC_BIT(VIC_UART0); // UART0 selected as IRQ
216  VICIntEnable = VIC_BIT(VIC_UART0); // UART0 interrupt enabled
217  _VIC_CNTL(UART0_VIC_SLOT) = VIC_ENABLE | VIC_UART0;
218  _VIC_ADDR(UART0_VIC_SLOT) = (uint32_t)uart0_ISR; // address of the ISR
219 
220  uart_enable_interrupts(&uart0);
221 }
222 
223 #endif /* USE_UART0 */
224 
225 #if USE_UART1
226 
227 #ifndef UART1_VIC_SLOT
228 #define UART1_VIC_SLOT 6
229 #endif
230 
231 /* by default enable UART Tx and Rx */
232 #ifndef USE_UART1_TX
233  #ifdef USE_UART1_RX_ONLY
234  #warning "USE_UART1_RX_ONLY is deprecated, please set USE_UART1_TX=FALSE instead"
235  #define USE_UART1_TX FALSE
236  #else
237  #define USE_UART1_TX TRUE
238  #endif
239 #endif
240 #ifndef USE_UART1_RX
241 #define USE_UART1_RX TRUE
242 #endif
243 
244 void uart1_ISR(void) __attribute__((naked));
245 
246 void uart1_ISR(void) {
247  // perform proper ISR entry so thumb-interwork works properly
248  ISR_ENTRY();
249 
250  uart_ISR(&uart1);
251 
252  VICVectAddr = 0x00000000; // clear this interrupt from the VIC
253  ISR_EXIT(); // recover registers and return
254 }
255 
256 void uart1_init( void ) {
257 
258  uart_periph_init(&uart1);
259  uart1.reg_addr = UART1_BASE;
260 
261 #if USE_UART1_RX && USE_UART0_TX
262  // set port pins for UART1
264 #elif USE_UART1_RX
265  // only use the RX0 P0.1 pin, no TX
267 #elif USE_UART1_TX
268  // only use tx
269  PINSEL0 = (PINSEL0 & ~U1_PINMASK_TX) | U1_PINSEL_TX;
270 #endif
271 
272  uart_set_baudrate(&uart1, UART1_BAUD);
273 
274  // initialize the interrupt vector
275  VICIntSelect &= ~VIC_BIT(VIC_UART1); // UART1 selected as IRQ
276  VICIntEnable = VIC_BIT(VIC_UART1); // UART1 interrupt enabled
277  _VIC_CNTL(UART1_VIC_SLOT) = VIC_ENABLE | VIC_UART1;
278  _VIC_ADDR(UART1_VIC_SLOT) = (uint32_t)uart1_ISR; // address of the ISR
279 
280  // enable receiver interrupts
281  uart_enable_interrupts(&uart1);
282 }
283 
284 #endif
285 
#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:64
#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
void * reg_addr
UART Register.
Definition: uart.h:66
#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:63
static void uart_ISR(struct uart_periph *p)
Definition: uart_arch.c:105
void uart_transmit(struct uart_periph *p, uint8_t data)
Definition: uart_arch.c:75
#define _VIC_ADDR(idx)
Definition: armVIC.h:20
#define UIIR_NO_INT
Definition: lpcUART.h:64
UART peripheral.
Definition: uart.h:55
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:181
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
void uart_periph_set_bits_stop_parity(struct uart_periph *p, uint8_t bits, uint8_t stop, uint8_t parity)
Definition: uart_arch.c:71
uint16_t rx_insert_idx
Definition: uart.h:58
#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:61
#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:65
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:62
#define VICIntEnable
Definition: LPC21xx.h:431
uint8_t rx_buf[UART_RX_BUFFER_SIZE]
Receive buffer.
Definition: uart.h:57
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:59
#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