Contiki 3.x
uart.c
1 #include <stddef.h>
2 
3 #include "K60.h"
4 #include "config-board.h"
5 #include "config-clocks.h"
6 #include "uart.h"
7 #include "interrupt.h"
8 #include "llwu.h"
9 #include "ringbuf.h"
10 
11 typedef int (*rx_callback_t)(unsigned char);
12 
13 static rx_callback_t rx_callback[NUM_UARTS] = { NULL };
14 
15 static volatile uint8_t transmitting[NUM_UARTS];
16 
17 #ifdef UART_CONF_DEFAULT_TXBUFSIZE
18 #define UART_DEFAULT_TXBUFSIZE UART_CONF_DEFAULT_TXBUFSIZE
19 #else
20 #define UART_DEFAULT_TXBUFSIZE 8
21 #endif
22 #ifdef UART0_CONF_TXBUFSIZE
23 #define UART0_TXBUFSIZE UART0_CONF_TXBUFSIZE
24 #else
25 #define UART0_TXBUFSIZE UART_DEFAULT_TXBUFSIZE
26 #endif
27 #ifdef UART1_CONF_TXBUFSIZE
28 #define UART1_TXBUFSIZE UART1_CONF_TXBUFSIZE
29 #else
30 #define UART1_TXBUFSIZE UART_DEFAULT_TXBUFSIZE
31 #endif
32 #ifdef UART2_CONF_TXBUFSIZE
33 #define UART2_TXBUFSIZE UART2_CONF_TXBUFSIZE
34 #else
35 #define UART2_TXBUFSIZE UART_DEFAULT_TXBUFSIZE
36 #endif
37 #ifdef UART3_CONF_TXBUFSIZE
38 #define UART3_TXBUFSIZE UART3_CONF_TXBUFSIZE
39 #else
40 #define UART3_TXBUFSIZE UART_DEFAULT_TXBUFSIZE
41 #endif
42 #ifdef UART4_CONF_TXBUFSIZE
43 #define UART4_TXBUFSIZE UART4_CONF_TXBUFSIZE
44 #else
45 #define UART4_TXBUFSIZE UART_DEFAULT_TXBUFSIZE
46 #endif
47 
48 static struct ringbuf uart_txbuf[NUM_UARTS];
49 
50 #if UART0_CONF_ENABLE
51 static uint8_t uart0_txbuf_data[UART0_TXBUFSIZE];
52 #endif
53 #if UART1_CONF_ENABLE
54 static uint8_t uart1_txbuf_data[UART1_TXBUFSIZE];
55 #endif
56 #if UART2_CONF_ENABLE
57 static uint8_t uart2_txbuf_data[UART2_TXBUFSIZE];
58 #endif
59 #if UART3_CONF_ENABLE
60 static uint8_t uart3_txbuf_data[UART3_TXBUFSIZE];
61 #endif
62 #if UART4_CONF_ENABLE
63 static uint8_t uart4_txbuf_data[UART4_TXBUFSIZE];
64 #endif
65 #if UART5_CONF_ENABLE
66 static uint8_t uart5_txbuf_data[UART5_TXBUFSIZE];
67 #endif
68 
69 static inline void tx_irq_handler(const unsigned int uart_num, const uint8_t s1) {
70  volatile UART_Type *uart_dev = UART[uart_num];
71  if((s1 & UART_S1_TC_MASK) && (uart_dev->C2 & UART_C2_TCIE_MASK) && (transmitting[uart_num] != 0)) {
72  /* transmission complete, allow STOP modes again */
73  LLWU_UNINHIBIT_STOP();
74  /* Disable transmission complete interrupt */
75  uart_dev->C2 &= ~(UART_C2_TCIE_MASK);
76  transmitting[uart_num] = 0;
77  }
78 
79  if((s1 & UART_S1_TDRE_MASK) && (uart_dev->C2 & UART_C2_TIE_MASK)) {
80  int ret;
81  ret = ringbuf_get(&uart_txbuf[uart_num]);
82  if (ret < 0) {
83  /* Empty buffer, disable this interrupt */
84  uart_dev->C2 &= ~(UART_C2_TIE_MASK);
85  /* Enable transmission complete interrupt. */
86  uart_dev->C2 |= UART_C2_TCIE_MASK;
87  } else {
88  /* queue next byte */
89  transmitting[uart_num] = 1;
90  uart_dev->D = (uint8_t)(ret & 0xff);
91  }
92  }
93 }
94 
95 static inline void rx_irq_handler(const unsigned int uart_num, const uint8_t s1) {
96  volatile UART_Type *uart_dev = UART[uart_num];
97  if((s1 & UART_S1_RDRF_MASK) && (rx_callback[uart_num] != NULL)) {
98  (rx_callback[uart_num])(uart_dev->D);
99  }
100 
101  if((uart_dev->S2 & UART_S2_RXEDGIF_MASK)) {
102  /* Clear RX wake-up flag by writing a 1 to it */
103  uart_dev->S2 |= UART_S2_RXEDGIF_MASK;
104  }
105 }
106 
107 /**
108  * Enable the clock gate to an UART module
109  *
110  * This is a convenience function mapping UART module number to SIM_SCG register.
111  *
112  * \param uart_num UART module number
113  */
114 void
115 uart_module_enable(const unsigned int uart_num)
116 {
117  switch (uart_num) {
118  case 0:
119  BITBAND_REG(SIM->SCGC4, SIM_SCGC4_UART0_SHIFT) = 1;
120  break;
121  case 1:
122  BITBAND_REG(SIM->SCGC4, SIM_SCGC4_UART1_SHIFT) = 1;
123  break;
124  case 2:
125  BITBAND_REG(SIM->SCGC4, SIM_SCGC4_UART2_SHIFT) = 1;
126  break;
127  case 3:
128  BITBAND_REG(SIM->SCGC4, SIM_SCGC4_UART3_SHIFT) = 1;
129  break;
130  case 4:
131  BITBAND_REG(SIM->SCGC1, SIM_SCGC1_UART4_SHIFT) = 1;
132  break;
133  case 5:
134  BITBAND_REG(SIM->SCGC1, SIM_SCGC1_UART5_SHIFT) = 1;
135  break;
136  default:
137  /* Unknown UART module!! */
138  DEBUGGER_BREAK(BREAK_INVALID_PARAM);
139  return;
140  }
141 }
142 
143 /**
144  * Initialize UART.
145  *
146  * This is based on the example found in the CodeWarrior samples provided by
147  * Freescale.
148  *
149  * \param uart_num UART module number
150  * \param module_clk_hz Module clock (in Hz) of the given UART, if zero: Use current module frequency.
151  * \param baud Desired target baud rate of the UART.
152  */
153 void
154 uart_init(const unsigned int uart_num, uint32_t module_clk_hz, const uint32_t baud)
155 {
156  volatile UART_Type *uart_dev = UART[uart_num];
157  uint16_t sbr;
158  uint16_t brfa;
159  if (module_clk_hz == 0) {
160  switch (uart_num) {
161  case 0:
162  case 1:
163  module_clk_hz = SystemSysClock;
164  break;
165  case 2:
166  case 3:
167  case 4:
168  module_clk_hz = SystemBusClock;
169  break;
170  default:
171  DEBUGGER_BREAK(BREAK_INVALID_PARAM);
172  return;
173  }
174  }
175 
176  /* Enable the clock to the selected UART */
177  uart_module_enable(uart_num);
178 
179  /* Compute new SBR value */
180  sbr = UART_SBR(module_clk_hz, baud);
181  /* Compute new fine-adjust value */
182  brfa = UART_BRFA(module_clk_hz, baud);
183 
184  /* Make sure that the transmitter and receiver are disabled while we
185  * change settings.
186  */
187  uart_dev->C2 &= ~(UART_C2_TE_MASK | UART_C2_RE_MASK);
188 
189  /* Configure the UART for 8-bit mode, no parity */
190  uart_dev->C1 = 0; /* We need all default settings, so entire register is cleared */
191 
192  /* Replace SBR bits in BDH, BDL registers */
193  /* High bits */
194  uart_dev->BDH = (uart_dev->BDH & ~(UART_BDH_SBR_MASK)) | UART_BDH_SBR(sbr >> 8);
195  /* Low bits */
196  uart_dev->BDL = (uart_dev->BDL & ~(UART_BDL_SBR_MASK)) | UART_BDL_SBR(sbr);
197  /* Fine adjust */
198  uart_dev->C4 = (uart_dev->C4 & ~(UART_C4_BRFA_MASK)) | UART_C4_BRFA(brfa);
199 
200  /* Enable transmitter and receiver and enable receive interrupt */
201  uart_dev->C2 |= UART_C2_TE_MASK | UART_C2_RE_MASK;
202 
203  transmitting[uart_num] = 0;
204 
205  /* Set up ring buffer and enable interrupt */
206  switch (uart_num) {
207 #if UART0_CONF_ENABLE
208  case 0:
209  ringbuf_init(&uart_txbuf[uart_num], &uart0_txbuf_data[0], sizeof(uart0_txbuf_data));
211  break;
212 #endif
213 #if UART1_CONF_ENABLE
214  case 1:
215  ringbuf_init(&uart_txbuf[uart_num], &uart1_txbuf_data[0], sizeof(uart1_txbuf_data));
217  break;
218 #endif
219 #if UART2_CONF_ENABLE
220  case 2:
221  ringbuf_init(&uart_txbuf[uart_num], &uart2_txbuf_data[0], sizeof(uart2_txbuf_data));
223  break;
224 #endif
225 #if UART3_CONF_ENABLE
226  case 3:
227  ringbuf_init(&uart_txbuf[uart_num], &uart3_txbuf_data[0], sizeof(uart3_txbuf_data));
229  break;
230 #endif
231 #if UART4_CONF_ENABLE
232  case 4:
233  ringbuf_init(&uart_txbuf[uart_num], &uart4_txbuf_data[0], sizeof(uart4_txbuf_data));
235  break;
236 #endif
237 #if UART5_CONF_ENABLE
238  case 5:
239  ringbuf_init(&uart_txbuf[uart_num], &uart5_txbuf_data[0], sizeof(uart5_txbuf_data));
241  break;
242 #endif
243  }
244 }
245 
246 /*
247  * Send char on UART.
248  */
249 void
250 uart_putchar(const unsigned int uart_num, const char ch)
251 {
252  volatile UART_Type *uart_dev = UART[uart_num];
253  /* Try to push to ring buffer until it succeeds, ringbuf_put will return 0
254  * when there is no space left. */
255  while(ringbuf_put(&uart_txbuf[uart_num], ch) == 0);
256 
257  MK60_ENTER_CRITICAL_REGION();
258  /* Enable transmitter interrupt, txbuf to UART data register data transfer is
259  * performed by the interrupt service routine. */
260  uart_dev->C2 |= UART_C2_TIE_MASK;
261 
262  /* Possible race condition between UART ISR and this flag, transmitting is set
263  * by ISR, but checked here. I think enclosing these few lines with IRQ
264  * disable/enable calls will cure it. */
265  if (transmitting[uart_num] == 0) {
266  LLWU_INHIBIT_STOP();
267  }
268  MK60_LEAVE_CRITICAL_REGION();
269 
270  return;
271 }
272 
273 /*
274  * Send string to UART1.
275  */
276 void
277 uart_putstring(const unsigned int uart_num, const char *str)
278 {
279  const char *p = str;
280  while (*p) {
281  uart_putchar(uart_num, *p++);
282  }
283 }
284 
285 void
286 uart_enable_rx_interrupt(const unsigned int uart_num)
287 {
288  int tmp;
289  volatile UART_Type *uart_dev = UART[uart_num];
290  tmp = uart_dev->S1; /* Clr status 1 register */
291  (void)tmp; /* Avoid compiler warnings [-Wunused-variable] */
292  uart_dev->C2 |= UART_C2_RIE_MASK;
293  uart_dev->BDH |= UART_BDH_RXEDGIE_MASK; /* Enable wake interrupt */
294 }
295 
296 void
297 uart_disable_rx_interrupt(const unsigned int uart_num)
298 {
299  int tmp;
300  volatile UART_Type *uart_dev = UART[uart_num];
301  tmp = uart_dev->S1; /* Clr status 1 register */
302  (void)tmp; /* Avoid compiler warnings [-Wunused-variable] */
303  uart_dev->C2 &= ~(UART_C2_RIE_MASK);
304 }
305 
306 void
307 uart_set_rx_callback(const unsigned int uart_num, rx_callback_t callback)
308 {
309  rx_callback[uart_num] = callback;
310 }
311 
312 #if UART0_CONF_ENABLE
313 void
314 _isr_uart0_status()
315 {
316  int s1;
317  s1 = UART0->S1; /* Clear status 1 register */
318 
319  tx_irq_handler(0, s1);
320  rx_irq_handler(0, s1);
321 }
322 #endif /* UART0_CONF_ENABLE */
323 
324 #if UART1_CONF_ENABLE
325 void
326 _isr_uart1_status()
327 {
328  int s1;
329  s1 = UART1->S1; /* Clear status 1 register */
330 
331  tx_irq_handler(1, s1);
332  rx_irq_handler(1, s1);
333 }
334 #endif /* UART1_CONF_ENABLE */
335 
336 #if UART2_CONF_ENABLE
337 void
338 _isr_uart2_status()
339 {
340  int s1;
341  s1 = UART2->S1; /* Clear status 1 register */
342 
343  tx_irq_handler(2, s1);
344  rx_irq_handler(2, s1);
345 }
346 #endif /* UART2_CONF_ENABLE */
347 
348 #if UART3_CONF_ENABLE
349 void
350 _isr_uart3_status()
351 {
352  int s1;
353  s1 = UART3->S1; /* Clear status 1 register */
354 
355  tx_irq_handler(3, s1);
356  rx_irq_handler(3, s1);
357 }
358 #endif /* UART3_CONF_ENABLE */
359 
360 #if UART4_CONF_ENABLE
361 void
362 _isr_uart4_status()
363 {
364  int s1;
365  s1 = UART4->S1; /* Clear status 1 register */
366 
367  tx_irq_handler(4, s1);
368  rx_irq_handler(4, s1);
369 }
370 #endif /* UART4_CONF_ENABLE */
371 
372 #if UART5_CONF_ENABLE
373 void
374 _isr_uart5_status()
375 {
376  int s1;
377  s1 = UART5->S1; /* Clear status 1 register */
378 
379  tx_irq_handler(5, s1);
380  rx_irq_handler(5, s1);
381 }
382 #endif /* UART5_CONF_ENABLE */
__IO uint8_t BDL
UART Baud Rate Registers: Low, offset: 0x1.
Definition: MK60D10.h:8223
UART0 Receive/Transmit interrupt.
Definition: MK60D10.h:141
__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn)
Enable External Interrupt.
Definition: core_cm0.h:535
K60 clock configuration defines.
#define UART_BRFA(f, b)
UART module fine adjust parameter based on module frequency f and desired baud rate b...
Definition: uart.h:98
Header file for the ring buffer library
UART3 Receive/Transmit interrupt.
Definition: MK60D10.h:147
__IO uint8_t C4
UART Control Register 4, offset: 0xA.
Definition: MK60D10.h:8232
void uart_init(const unsigned int uart_num, uint32_t module_clk_hz, const uint32_t baud)
Initialize UART.
Definition: uart.c:154
Structure that holds the state of a ring buffer.
Definition: ringbuf.h:68
UART - Register Layout Typedef.
Definition: MK60D10.h:8221
#define NUM_UARTS
Number of UART modules in CPU.
Definition: config-board.h:138
#define NULL
The null pointer.
#define SIM
Peripheral SIM base pointer.
Definition: MK60D10.h:7650
int ringbuf_get(struct ringbuf *r)
Get a byte from the ring buffer.
Definition: ringbuf.c:72
void uart_module_enable(const unsigned int uart_num)
Enable the clock gate to an UART module.
Definition: uart.c:115
#define UART3
Peripheral UART3 base pointer.
Definition: MK60D10.h:8675
#define UART_SBR(f, b)
UART module SBR parameter based on module frequency f and desired baud rate b.
Definition: uart.h:77
Board configuration defines for Mulle platform.
K60 hardware register header wrapper.
#define DEBUGGER_BREAK(sig)
Make the CPU signal to the debugger and break execution by issuing a bkpt instruction.
Definition: K60.h:164
__IO uint8_t C1
UART Control Register 1, offset: 0x2.
Definition: MK60D10.h:8224
__IO uint8_t BDH
UART Baud Rate Registers: High, offset: 0x0.
Definition: MK60D10.h:8222
void ringbuf_init(struct ringbuf *r, uint8_t *dataptr, uint8_t size)
Initialize a ring buffer.
Definition: ringbuf.c:43
Provide common UART routines for MK60DZ10.
#define UART4
Peripheral UART4 base pointer.
Definition: MK60D10.h:8679
#define UART1
Peripheral UART1 base pointer.
Definition: MK60D10.h:8667
__IO uint8_t S2
UART Status Register 2, offset: 0x5.
Definition: MK60D10.h:8227
UART5 Receive/Transmit interrupt.
Definition: MK60D10.h:151
UART2 Receive/Transmit interrupt.
Definition: MK60D10.h:145
__I uint8_t S1
UART Status Register 1, offset: 0x4.
Definition: MK60D10.h:8226
UART1 Receive/Transmit interrupt.
Definition: MK60D10.h:143
#define UART2
Peripheral UART2 base pointer.
Definition: MK60D10.h:8671
Provide common UART routines for MK60DZ10.
K60 interrupt save/restore macros.
#define UART0
Peripheral UART0 base pointer.
Definition: MK60D10.h:8663
#define UART5
Peripheral UART5 base pointer.
Definition: MK60D10.h:8683
UART4 Receive/Transmit interrupt.
Definition: MK60D10.h:149
#define BITBAND_REG(Reg, Bit)
Macro to access a single bit of a peripheral register (bit band region 0x40000000 to 0x400FFFFF) usin...
Definition: MK60D10.h:71
uint32_t SystemSysClock
Current system clock frequency.
__IO uint8_t D
UART Data Register, offset: 0x7.
Definition: MK60D10.h:8229
__IO uint8_t C2
UART Control Register 2, offset: 0x3.
Definition: MK60D10.h:8225
uint32_t SystemBusClock
Current bus clock frequency.
int ringbuf_put(struct ringbuf *r, uint8_t c)
Insert a byte into the ring buffer.
Definition: ringbuf.c:52