1 /*******************************************************************************
2 * (c) Copyright 2011-2013 Microsemi SoC Products Group. All rights reserved.
3 *
4 * SmartFusion2 Microcontroller Subsystem MMUART bare metal software driver
5 * implementation.
6 *
7 * SVN $Revision: 5610 $
8 * SVN $Date: 2013-04-05 18:49:30 +0530 (Fri, 05 Apr 2013) $
9 */
10 #include "mss_uart.h"
11 #include "mss_uart_regs.h"
12 #include "../../CMSIS/mss_assert.h"
13 #include "../../CMSIS/hw_reg_io.h"
14 #include "../../CMSIS/system_m2sxxx.h"
15
16 #ifdef __cplusplus
17 extern "C" {
18 #endif
19
20 /*******************************************************************************
21 * Defines
22 */
23 #define TX_COMPLETE 0u
24 #define TX_FIFO_SIZE 16u
25
26 #define FCR_TRIG_LEVEL_MASK 0xC0u
27
28 #define IIRF_MASK 0x0Fu
29
30 #define INVALID_INTERRUPT 0u
31 #define INVALID_IRQ_HANDLER ((mss_uart_irq_handler_t) 0)
32 #define NULL_HANDLER ((mss_uart_irq_handler_t) 0)
33
34 #define MSS_UART_DATA_READY ((uint8_t) 0x01)
35
36 #define SYNC_ASYNC_MODE_MASK (0x7u)
37
38 /*******************************************************************************
39 * Possible values for Interrupt Identification Register Field.
40 */
41 #define IIRF_MODEM_STATUS 0x00u
42 #define IIRF_THRE 0x02u
43 #define IIRF_MMI 0x03u
44 #define IIRF_RX_DATA 0x04u
45 #define IIRF_RX_LINE_STATUS 0x06u
46 #define IIRF_DATA_TIMEOUT 0x0Cu
47
48 /*******************************************************************************
49 * Receiver error status mask.
50 */
51 #define STATUS_ERROR_MASK ( MSS_UART_OVERUN_ERROR | MSS_UART_PARITY_ERROR | \
52 MSS_UART_FRAMING_ERROR | MSS_UART_BREAK_ERROR | \
53 MSS_UART_FIFO_ERROR)
54
55 /*******************************************************************************
56 * Cortex-M3 interrupt handler functions implemented as part of the MSS UART
57 * driver.
58 */
59 #if defined(__GNUC__)
60 __attribute__((__interrupt__)) void UART0_IRQHandler(void);
61 #else
62 void UART0_IRQHandler(void);
63 #endif
64
65 #if defined(__GNUC__)
66 __attribute__((__interrupt__)) void UART1_IRQHandler(void);
67 #else
68 void UART1_IRQHandler(void);
69 #endif
70
71 /*******************************************************************************
72 * Local functions.
73 */
74 static void global_init(mss_uart_instance_t * this_uart, uint32_t baud_rate,
75 uint8_t line_config);
76 static void MSS_UART_isr(mss_uart_instance_t * this_uart);
77 static void default_tx_handler(mss_uart_instance_t * this_uart);
78
79 static void config_baud_divisors
80 (
81 mss_uart_instance_t * this_uart,
82 uint32_t baudrate
83 );
84
85 /*******************************************************************************
86 * Instance definitions
87 */
88 mss_uart_instance_t g_mss_uart0;
89 mss_uart_instance_t g_mss_uart1;
90
91
92 /*******************************************************************************
93 * Public Functions
94 *******************************************************************************/
95 /***************************************************************************//**
96 * See mss_uart.h for details of how to use this function.
97 */
98 void
MSS_UART_init(mss_uart_instance_t * this_uart,uint32_t baud_rate,uint8_t line_config)99 MSS_UART_init
100 (
101 mss_uart_instance_t* this_uart,
102 uint32_t baud_rate,
103 uint8_t line_config
104 )
105 {
106 /* The driver expects g_mss_uart0 and g_mss_uart1 to be the only
107 * mss_uart_instance_t instances used to identify UART0 and UART1. */
108 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
109
110 /* Perform generic initialization */
111 global_init(this_uart, baud_rate, line_config);
112
113 /* Disable LIN mode */
114 clear_bit_reg8(&this_uart->hw_reg->MM0, ELIN);
115
116 /* Disable IrDA mode */
117 clear_bit_reg8(&this_uart->hw_reg->MM1, EIRD);
118
119 /* Disable SmartCard Mode */
120 clear_bit_reg8(&this_uart->hw_reg->MM2, EERR);
121
122 /* set default tx handler for automated TX using interrupt in USART mode */
123 this_uart->tx_handler = default_tx_handler;
124 }
125
126 /***************************************************************************//**
127 * See mss_uart.h for details of how to use this function.
128 */
MSS_UART_lin_init(mss_uart_instance_t * this_uart,uint32_t baud_rate,uint8_t line_config)129 void MSS_UART_lin_init
130 (
131 mss_uart_instance_t* this_uart,
132 uint32_t baud_rate,
133 uint8_t line_config
134 )
135 {
136 /* The driver expects g_mss_uart0 and g_mss_uart1 to be the only
137 * mss_uart_instance_t instances used to identify UART0 and UART1. */
138 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
139
140 /* Perform generic initialization */
141 global_init(this_uart, baud_rate, line_config);
142
143 /* Enable LIN mode */
144 set_bit_reg8(&this_uart->hw_reg->MM0, ELIN);
145
146 /* Disable IrDA mode */
147 clear_bit_reg8(&this_uart->hw_reg->MM1, EIRD);
148
149 /* Disable SmartCard Mode */
150 clear_bit_reg8(&this_uart->hw_reg->MM2, EERR);
151 }
152
153 /***************************************************************************//**
154 * See mss_uart.h for details of how to use this function.
155 */
156 void
MSS_UART_irda_init(mss_uart_instance_t * this_uart,uint32_t baud_rate,uint8_t line_config,mss_uart_rzi_polarity_t rxpol,mss_uart_rzi_polarity_t txpol,mss_uart_rzi_pulsewidth_t pw)157 MSS_UART_irda_init
158 (
159 mss_uart_instance_t* this_uart,
160 uint32_t baud_rate,
161 uint8_t line_config,
162 mss_uart_rzi_polarity_t rxpol,
163 mss_uart_rzi_polarity_t txpol,
164 mss_uart_rzi_pulsewidth_t pw
165 )
166 {
167 /* The driver expects g_mss_uart0 and g_mss_uart1 to be the only
168 * mss_uart_instance_t instances used to identify UART0 and UART1. */
169 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
170
171 /* Perform generic initialization */
172 global_init(this_uart, baud_rate, line_config);
173
174 /* Enable LIN mode */
175 clear_bit_reg8(&this_uart->hw_reg->MM0, ELIN);
176
177 /* Disable IrDA mode */
178 set_bit_reg8(&this_uart->hw_reg->MM1, EIRD);
179 ((rxpol == MSS_UART_ACTIVE_LOW) ? clear_bit_reg8(&this_uart->hw_reg->MM1,EIRX) :
180 set_bit_reg8(&this_uart->hw_reg->MM1,EIRX));
181
182 ((txpol == MSS_UART_ACTIVE_LOW) ? clear_bit_reg8(&this_uart->hw_reg->MM1,EITX) :
183 set_bit_reg8(&this_uart->hw_reg->MM1,EITX));
184
185 ((pw == MSS_UART_3_BY_16) ? clear_bit_reg8(&this_uart->hw_reg->MM1,EITP) :
186 set_bit_reg8(&this_uart->hw_reg->MM1,EITP));
187 /* Disable SmartCard Mode */
188 clear_bit_reg8(&this_uart->hw_reg->MM2, EERR);
189 }
190
191 /***************************************************************************//**
192 * See mss_uart.h for details of how to use this function.
193 */
194 void
MSS_UART_smartcard_init(mss_uart_instance_t * this_uart,uint32_t baud_rate,uint8_t line_config)195 MSS_UART_smartcard_init
196 (
197 mss_uart_instance_t* this_uart,
198 uint32_t baud_rate,
199 uint8_t line_config
200 )
201 {
202 /* The driver expects g_mss_uart0 and g_mss_uart1 to be the only
203 * mss_uart_instance_t instances used to identify UART0 and UART1. */
204 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
205
206 /* Perform generic initialization */
207 global_init(this_uart, baud_rate, line_config);
208
209 /* Disable LIN mode */
210 clear_bit_reg8(&this_uart->hw_reg->MM0, ELIN);
211
212 /* Disable IrDA mode */
213 clear_bit_reg8(&this_uart->hw_reg->MM1, EIRD);
214
215 /* Enable SmartCard Mode : Only when data is 8-bit and 2 stop bits*/
216 if( ( MSS_UART_DATA_8_BITS | MSS_UART_TWO_STOP_BITS) ==
217 (line_config & (MSS_UART_DATA_8_BITS | MSS_UART_TWO_STOP_BITS)))
218 {
219 set_bit_reg8(&this_uart->hw_reg->MM2, EERR);
220 /* Enable single wire half-duplex mode */
221 set_bit_reg8(&this_uart->hw_reg->MM2,ESWM);
222 }
223 }
224
225 /***************************************************************************//**
226 * See mss_uart.h for details of how to use this function.
227 */
228 void
MSS_UART_polled_tx(mss_uart_instance_t * this_uart,const uint8_t * pbuff,uint32_t tx_size)229 MSS_UART_polled_tx
230 (
231 mss_uart_instance_t * this_uart,
232 const uint8_t * pbuff,
233 uint32_t tx_size
234 )
235 {
236 uint32_t char_idx = 0u;
237 uint32_t size_sent;
238 uint8_t status;
239
240 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
241 ASSERT(pbuff != ( (uint8_t *)0));
242 ASSERT(tx_size > 0u);
243
244 if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&
245 (pbuff != ((uint8_t *)0)) && (tx_size > 0u))
246 {
247 /* Remain in this loop until the entire input buffer
248 * has been transferred to the UART.
249 */
250 do {
251 /* Read the Line Status Register and update the sticky record */
252 status = this_uart->hw_reg->LSR;
253 this_uart->status |= status;
254
255 /* Check if TX FIFO is empty. */
256 if(status & MSS_UART_THRE)
257 {
258 uint32_t fill_size = TX_FIFO_SIZE;
259
260 /* Calculate the number of bytes to transmit. */
261 if(tx_size < TX_FIFO_SIZE)
262 {
263 fill_size = tx_size;
264 }
265
266 /* Fill the TX FIFO with the calculated the number of bytes. */
267 for(size_sent = 0u; size_sent < fill_size; ++size_sent)
268 {
269 /* Send next character in the buffer. */
270 this_uart->hw_reg->THR = pbuff[char_idx];
271 char_idx++;
272 }
273
274 /* Calculate the number of untransmitted bytes remaining. */
275 tx_size -= size_sent;
276 }
277 } while(tx_size);
278 }
279 }
280
281 /***************************************************************************//**
282 * See mss_uart.h for details of how to use this function.
283 */
284 void
MSS_UART_polled_tx_string(mss_uart_instance_t * this_uart,const uint8_t * p_sz_string)285 MSS_UART_polled_tx_string
286 (
287 mss_uart_instance_t * this_uart,
288 const uint8_t * p_sz_string
289 )
290 {
291 uint32_t char_idx = 0u;
292 uint32_t fill_size;
293 uint8_t data_byte;
294 uint8_t status;
295
296 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
297 ASSERT(p_sz_string != ((uint8_t *)0));
298
299 if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&
300 (p_sz_string != ((uint8_t *)0)))
301 {
302 /* Get the first data byte from the input buffer */
303 data_byte = p_sz_string[char_idx];
304
305 /* First check for the NULL terminator byte.
306 * Then remain in this loop until the entire string in the input buffer
307 * has been transferred to the UART.
308 */
309 while(0u != data_byte)
310 {
311 /* Wait until TX FIFO is empty. */
312 do {
313 status = this_uart->hw_reg->LSR;
314 this_uart->status |= status;
315 } while (0u == (status & MSS_UART_THRE));
316
317 /* Send bytes from the input buffer until the TX FIFO is full
318 * or we reach the NULL terminator byte.
319 */
320 fill_size = 0u;
321 while((0u != data_byte) && (fill_size < TX_FIFO_SIZE))
322 {
323 /* Send the data byte */
324 this_uart->hw_reg->THR = data_byte;
325 ++fill_size;
326 char_idx++;
327 /* Get the next data byte from the input buffer */
328 data_byte = p_sz_string[char_idx];
329 }
330 }
331 }
332 }
333
334 /***************************************************************************//**
335 * See mss_uart.h for details of how to use this function.
336 */
337 void
MSS_UART_irq_tx(mss_uart_instance_t * this_uart,const uint8_t * pbuff,uint32_t tx_size)338 MSS_UART_irq_tx
339 (
340 mss_uart_instance_t * this_uart,
341 const uint8_t * pbuff,
342 uint32_t tx_size
343 )
344 {
345 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
346 ASSERT(pbuff != ((uint8_t *)0));
347 ASSERT(tx_size > 0u);
348
349 if((tx_size > 0u) && ( pbuff != ((uint8_t *)0)) &&
350 ((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)))
351 {
352 /*Initialise the transmit info for the UART instance with the arguments.*/
353 this_uart->tx_buffer = pbuff;
354 this_uart->tx_buff_size = tx_size;
355 this_uart->tx_idx = (uint16_t)0;
356
357 /* Clear any previously pended interrupts */
358 NVIC_ClearPendingIRQ(this_uart->irqn);
359
360 /* assign default handler for data transfer */
361 this_uart->tx_handler = default_tx_handler;
362
363 /* enables TX interrupt */
364 set_bit_reg8(&this_uart->hw_reg->IER,ETBEI);
365
366 /* Enable UART instance interrupt in Cortex-M3 NVIC. */
367 NVIC_EnableIRQ(this_uart->irqn);
368 }
369 }
370
371 /***************************************************************************//**
372 * See mss_uart.h for details of how to use this function.
373 */
374 int8_t
MSS_UART_tx_complete(mss_uart_instance_t * this_uart)375 MSS_UART_tx_complete
376 (
377 mss_uart_instance_t * this_uart
378 )
379 {
380 int8_t ret_value = 0;
381 uint8_t status = 0u;
382
383 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
384
385 if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))
386 {
387 /* Read the Line Status Register and update the sticky record. */
388 status = this_uart->hw_reg->LSR;
389 this_uart->status |= status;
390
391 if((TX_COMPLETE == this_uart->tx_buff_size) &&
392 ((status & MSS_UART_TEMT) != 0u))
393 {
394 ret_value = (int8_t)1;
395 }
396 }
397 return ret_value;
398 }
399
400
401 /***************************************************************************//**
402 * See mss_uart.h for details of how to use this function.
403 */
404 size_t
MSS_UART_get_rx(mss_uart_instance_t * this_uart,uint8_t * rx_buff,size_t buff_size)405 MSS_UART_get_rx
406 (
407 mss_uart_instance_t * this_uart,
408 uint8_t * rx_buff,
409 size_t buff_size
410 )
411 {
412 size_t rx_size = 0u;
413 uint8_t status = 0u;
414
415 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
416 ASSERT(rx_buff != ((uint8_t *)0));
417 ASSERT(buff_size > 0u);
418
419 if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&
420 (rx_buff != ((uint8_t *)0)) && (buff_size > 0u))
421 {
422 status = this_uart->hw_reg->LSR;
423 this_uart->status |= status;
424
425 while(((status & MSS_UART_DATA_READY) != 0u) &&
426 (rx_size < buff_size))
427 {
428 rx_buff[rx_size] = this_uart->hw_reg->RBR;
429 ++rx_size;
430 status = this_uart->hw_reg->LSR;
431 this_uart->status |= status;
432 }
433 }
434 return rx_size;
435 }
436 /***************************************************************************//**
437 * See mss_uart.h for details of how to use this function.
438 */
439 void
MSS_UART_enable_irq(mss_uart_instance_t * this_uart,mss_uart_irq_t irq_mask)440 MSS_UART_enable_irq
441 (
442 mss_uart_instance_t * this_uart,
443 mss_uart_irq_t irq_mask
444 )
445 {
446 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
447 ASSERT(MSS_UART_INVALID_IRQ > irq_mask);
448
449 if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&
450 (MSS_UART_INVALID_IRQ > irq_mask))
451 {
452 /* Clear any previously pended interrupts */
453 NVIC_ClearPendingIRQ(this_uart->irqn);
454
455 /* irq_mask encoding: 1- enable
456 * bit 0 - Receive Data Available Interrupt
457 * bit 1 - Transmitter Holding Register Empty Interrupt
458 * bit 2 - Receiver Line Status Interrupt
459 * bit 3 - Modem Status Interrupt
460 */
461 this_uart->hw_reg->IER |= (uint8_t)irq_mask & IIRF_MASK;
462
463 /*
464 * bit 4 - Receiver time-out interrupt
465 * bit 5 - NACK / ERR signal interrupt
466 * bit 6 - PID parity error interrupt
467 * bit 7 - LIN break detection interrupt
468 * bit 8 - LIN Sync detection interrupt
469 */
470 this_uart->hw_reg->IEM |= (uint8_t)(((uint32_t)irq_mask & ~((uint32_t)IIRF_MASK)) >> 4u);
471
472 /* Enable UART instance interrupt in Cortex-M3 NVIC. */
473 NVIC_EnableIRQ(this_uart->irqn);
474 }
475 }
476
477 /***************************************************************************//**
478 * See mss_uart.h for details of how to use this function.
479 */
480 void
MSS_UART_disable_irq(mss_uart_instance_t * this_uart,mss_uart_irq_t irq_mask)481 MSS_UART_disable_irq
482 (
483 mss_uart_instance_t * this_uart,
484 mss_uart_irq_t irq_mask
485 )
486 {
487 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
488
489 if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))
490 {
491 /* irq_mask encoding: 1 - disable
492 * bit 0 - Receive Data Available Interrupt
493 * bit 1 - Transmitter Holding Register Empty Interrupt
494 * bit 2 - Receiver Line Status Interrupt
495 * bit 3 - Modem Status Interrupt
496 */
497 this_uart->hw_reg->IER &= ((uint8_t)(~((uint32_t)irq_mask & (uint32_t)IIRF_MASK)));
498
499 /*
500 * bit 4 - Receiver time-out interrupt
501 * bit 5 - NACK / ERR signal interrupt
502 * bit 6 - PID parity error interrupt
503 * bit 7 - LIN break detection interrupt
504 * bit 8 - LIN Sync detection interrupt
505 */
506 this_uart->hw_reg->IEM |= (uint8_t)(~(((uint32_t)irq_mask & ~((uint32_t)IIRF_MASK)) >> 8u));
507
508 /* Clear any previously pended interrupts */
509 NVIC_ClearPendingIRQ(this_uart->irqn);
510
511 if(irq_mask == IIRF_MASK)
512 {
513 /* Disable UART instance interrupt in Cortex-M3 NVIC. */
514 NVIC_DisableIRQ(this_uart->irqn);
515
516 }
517 }
518 }
519
520 /***************************************************************************//**
521 * See mss_uart.h for details of how to use this function.
522 */
523 void
MSS_UART_set_rx_handler(mss_uart_instance_t * this_uart,mss_uart_irq_handler_t handler,mss_uart_rx_trig_level_t trigger_level)524 MSS_UART_set_rx_handler
525 (
526 mss_uart_instance_t * this_uart,
527 mss_uart_irq_handler_t handler,
528 mss_uart_rx_trig_level_t trigger_level
529 )
530 {
531 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
532 ASSERT(handler != INVALID_IRQ_HANDLER );
533 ASSERT(trigger_level < MSS_UART_FIFO_INVALID_TRIG_LEVEL);
534
535 if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&
536 (handler != INVALID_IRQ_HANDLER) &&
537 (trigger_level < MSS_UART_FIFO_INVALID_TRIG_LEVEL))
538 {
539 this_uart->rx_handler = handler;
540
541 /* Set the receive interrupt trigger level. */
542 this_uart->hw_reg->FCR = (this_uart->hw_reg->FCR &
543 (uint8_t)(~((uint8_t)FCR_TRIG_LEVEL_MASK))) |
544 (uint8_t)trigger_level;
545 /* Clear any previously pended interrupts */
546 NVIC_ClearPendingIRQ(this_uart->irqn);
547
548 /* Enable receive interrupt. */
549 set_bit_reg8(&this_uart->hw_reg->IER,ERBFI);
550
551 /* Enable UART instance interrupt in Cortex-M3 NVIC. */
552 NVIC_EnableIRQ(this_uart->irqn);
553 }
554 }
555
556 /***************************************************************************//**
557 * See mss_uart.h for details of how to use this function.
558 */
559 void
MSS_UART_set_loopback(mss_uart_instance_t * this_uart,mss_uart_loopback_t loopback)560 MSS_UART_set_loopback
561 (
562 mss_uart_instance_t * this_uart,
563 mss_uart_loopback_t loopback
564 )
565 {
566 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
567 ASSERT(MSS_UART_INVALID_LOOPBACK > loopback);
568
569 if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) ||
570 (MSS_UART_INVALID_LOOPBACK > loopback))
571 {
572 switch(loopback)
573 {
574 case MSS_UART_LOCAL_LOOPBACK_OFF:
575 /* Disable local loopback */
576 clear_bit_reg8(&this_uart->hw_reg->MCR,LOOP);
577 break;
578
579 case MSS_UART_LOCAL_LOOPBACK_ON:
580 /* Enable local loopback */
581 set_bit_reg8(&this_uart->hw_reg->MCR,LOOP);
582 break;
583
584 case MSS_UART_REMOTE_LOOPBACK_OFF:
585 case MSS_UART_AUTO_ECHO_OFF:
586 /* Disable remote loopback & automatic echo*/
587 this_uart->hw_reg->MCR &= ~RLOOP_MASK;
588 break;
589
590 case MSS_UART_REMOTE_LOOPBACK_ON:
591 /* Enable remote loopback */
592 this_uart->hw_reg->MCR |= (1u << RLOOP);
593 break;
594
595 case MSS_UART_AUTO_ECHO_ON:
596 /* Enable automatic echo */
597 this_uart->hw_reg->MCR |= (1u << ECHO);
598 break;
599
600 case MSS_UART_INVALID_LOOPBACK:
601 /* Fall through to default. */
602 default:
603 ASSERT(0);
604 break;
605 }
606 }
607 }
608
609 /***************************************************************************//**
610 * UART0 interrupt service routine.
611 * UART0_IRQHandler is included within the Cortex-M3 vector table as part of the
612 * Fusion 2 CMSIS.
613 */
614 #if defined(__GNUC__)
UART0_IRQHandler(void)615 __attribute__((__interrupt__)) void UART0_IRQHandler(void)
616 #else
617 void UART0_IRQHandler(void)
618 #endif
619 {
620 MSS_UART_isr(&g_mss_uart0);
621 }
622
623 /***************************************************************************//**
624 * UART1 interrupt service routine.
625 * UART2_IRQHandler is included within the Cortex-M3 vector table as part of the
626 * Fusion 2 CMSIS.
627 */
628 #if defined(__GNUC__)
UART1_IRQHandler(void)629 __attribute__((__interrupt__)) void UART1_IRQHandler(void)
630 #else
631 void UART1_IRQHandler(void)
632 #endif
633 {
634 MSS_UART_isr(&g_mss_uart1);
635 }
636
637 /***************************************************************************//**
638 * See mss_uart.h for details of how to use this function.
639 */
640 void
MSS_UART_set_rxstatus_handler(mss_uart_instance_t * this_uart,mss_uart_irq_handler_t handler)641 MSS_UART_set_rxstatus_handler
642 (
643 mss_uart_instance_t * this_uart,
644 mss_uart_irq_handler_t handler
645 )
646 {
647 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
648 ASSERT(handler != INVALID_IRQ_HANDLER);
649
650 if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&
651 (handler != INVALID_IRQ_HANDLER))
652 {
653 this_uart->linests_handler = handler;
654
655 /* Clear any previously pended interrupts */
656 NVIC_ClearPendingIRQ(this_uart->irqn);
657
658 /* Enable receiver line status interrupt. */
659 set_bit_reg8(&this_uart->hw_reg->IER,ELSI);
660
661 /* Enable UART instance interrupt in Cortex-M3 NVIC. */
662 NVIC_EnableIRQ(this_uart->irqn);
663 }
664 }
665
666 /***************************************************************************//**
667 * See mss_uart.h for details of how to use this function.
668 */
669 void
MSS_UART_set_tx_handler(mss_uart_instance_t * this_uart,mss_uart_irq_handler_t handler)670 MSS_UART_set_tx_handler
671 (
672 mss_uart_instance_t * this_uart,
673 mss_uart_irq_handler_t handler
674 )
675 {
676 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
677 ASSERT(handler != INVALID_IRQ_HANDLER);
678
679 if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&
680 (handler != INVALID_IRQ_HANDLER))
681 {
682 this_uart->tx_handler = handler;
683
684 /* Make TX buffer info invalid */
685 this_uart->tx_buffer = (const uint8_t *)0;
686 this_uart->tx_buff_size = 0u;
687
688 /* Clear any previously pended interrupts */
689 NVIC_ClearPendingIRQ(this_uart->irqn);
690
691 /* Enable transmitter holding register Empty interrupt. */
692 set_bit_reg8(&this_uart->hw_reg->IER,ETBEI);
693
694 /* Enable UART instance interrupt in Cortex-M3 NVIC. */
695 NVIC_EnableIRQ(this_uart->irqn);
696 }
697 }
698
699 /***************************************************************************//**
700 * See mss_uart.h for details of how to use this function.
701 */
702 void
MSS_UART_set_modemstatus_handler(mss_uart_instance_t * this_uart,mss_uart_irq_handler_t handler)703 MSS_UART_set_modemstatus_handler
704 (
705 mss_uart_instance_t * this_uart,
706 mss_uart_irq_handler_t handler
707 )
708 {
709 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
710 ASSERT(handler != INVALID_IRQ_HANDLER);
711
712 if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&
713 (handler != INVALID_IRQ_HANDLER))
714 {
715 this_uart->modemsts_handler = handler;
716
717 /* Clear any previously pended interrupts */
718 NVIC_ClearPendingIRQ(this_uart->irqn);
719
720 /* Enable modem status interrupt. */
721 set_bit_reg8(&this_uart->hw_reg->IER,EDSSI);
722
723 /* Enable UART instance interrupt in Cortex-M3 NVIC. */
724 NVIC_EnableIRQ(this_uart->irqn);
725 }
726 }
727
728 /***************************************************************************//**
729 * See mss_uart.h for details of how to use this function.
730 */
731 size_t
MSS_UART_fill_tx_fifo(mss_uart_instance_t * this_uart,const uint8_t * tx_buffer,size_t tx_size)732 MSS_UART_fill_tx_fifo
733 (
734 mss_uart_instance_t * this_uart,
735 const uint8_t * tx_buffer,
736 size_t tx_size
737 )
738 {
739 uint8_t status = 0u;
740 size_t size_sent = 0u;
741
742 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
743 ASSERT(tx_buffer != ( (uint8_t *)0));
744 ASSERT(tx_size > 0);
745
746 /* Fill the UART's Tx FIFO until the FIFO is full or the complete input
747 * buffer has been written. */
748 if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&
749 (tx_buffer != ((uint8_t *)0)) &&
750 (tx_size > 0u))
751 {
752 status = this_uart->hw_reg->LSR;
753 this_uart->status |= status;
754
755 if(status & MSS_UART_THRE)
756 {
757 uint32_t fill_size = TX_FIFO_SIZE;
758
759 if(tx_size < TX_FIFO_SIZE)
760 {
761 fill_size = tx_size;
762 }
763 /* Fill up FIFO */
764 for(size_sent = 0u; size_sent < fill_size; ++size_sent)
765 {
766
767 /* Send next character in the buffer. */
768 this_uart->hw_reg->THR = tx_buffer[size_sent];
769 }
770 }
771 }
772 return size_sent;
773 }
774
775 /***************************************************************************//**
776 * See mss_uart.h for details of how to use this function.
777 */
778 uint8_t
MSS_UART_get_rx_status(mss_uart_instance_t * this_uart)779 MSS_UART_get_rx_status
780 (
781 mss_uart_instance_t * this_uart
782 )
783 {
784 uint8_t status = MSS_UART_INVALID_PARAM;
785
786 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
787
788 if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))
789 {
790 /*
791 * Extract UART receive error status.
792 * Bit 1 - Overflow error status
793 * Bit 2 - Parity error status
794 * Bit 3 - Frame error status
795 * Bit 4 - Break interrupt indicator
796 * Bit 7 - FIFO data error status
797 */
798 this_uart->status |= (this_uart->hw_reg->LSR);
799 status = (this_uart->status & STATUS_ERROR_MASK);
800 /* Clear the sticky status after reading */
801 this_uart->status = 0u;
802 }
803 return status;
804 }
805
806 /***************************************************************************//**
807 * See mss_uart.h for details of how to use this function.
808 */
809 uint8_t
MSS_UART_get_modem_status(mss_uart_instance_t * this_uart)810 MSS_UART_get_modem_status
811 (
812 mss_uart_instance_t * this_uart
813 )
814 {
815 uint8_t status = MSS_UART_INVALID_PARAM;
816
817 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
818
819 if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))
820 {
821 /*
822 * Extract UART modem status and place in lower bits of "status".
823 * Bit 0 - Delta Clear to Send Indicator
824 * Bit 1 - Delta Clear to Receive Indicator
825 * Bit 2 - Trailing edge of Ring Indicator detector
826 * Bit 3 - Delta Data Carrier Detect indicator
827 * Bit 4 - Clear To Send
828 * Bit 5 - Data Set Ready
829 * Bit 6 - Ring Indicator
830 * Bit 7 - Data Carrier Detect
831 */
832 status = this_uart->hw_reg->MSR;
833 }
834 return status;
835 }
836
837 /***************************************************************************//**
838 * MSS_UART_get_tx_status.
839 * See mss_uart.h for details of how to use this function.
840 */
841 uint8_t
MSS_UART_get_tx_status(mss_uart_instance_t * this_uart)842 MSS_UART_get_tx_status
843 (
844 mss_uart_instance_t * this_uart
845 )
846 {
847 uint8_t status = MSS_UART_TX_BUSY;
848
849 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
850
851 if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))
852 {
853 /* Read the Line Status Register and update the sticky record. */
854 status = this_uart->hw_reg->LSR;
855 this_uart->status |= status;
856 /*
857 * Extract the transmit status bits from the UART's Line Status Register.
858 * Bit 5 - Transmitter Holding Register/FIFO Empty (THRE) status. (If = 1, TX FIFO is empty)
859 * Bit 6 - Transmitter Empty (TEMT) status. (If = 1, both TX FIFO and shift register are empty)
860 */
861 status &= (MSS_UART_THRE | MSS_UART_TEMT);
862 }
863 return status;
864 }
865
866 /***************************************************************************//**
867 * See mss_uart.h for details of how to use this function.
868 */
869 void
MSS_UART_set_break(mss_uart_instance_t * this_uart)870 MSS_UART_set_break
871 (
872 mss_uart_instance_t * this_uart
873 )
874 {
875 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
876 if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))
877 {
878 /* set break charecter on Tx line */
879 set_bit_reg8(&this_uart->hw_reg->LCR,SB);
880 }
881 }
882
883 /***************************************************************************//**
884 * See mss_uart.h for details of how to use this function.
885 */
886 void
MSS_UART_clear_break(mss_uart_instance_t * this_uart)887 MSS_UART_clear_break
888 (
889 mss_uart_instance_t * this_uart
890 )
891 {
892 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
893 if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))
894 {
895 /* remove break charecter from Tx line */
896 clear_bit_reg8(&this_uart->hw_reg->LCR,SB);
897 }
898 }
899
900 /***************************************************************************//**
901 * See mss_uart.h for details of how to use this function.
902 */
903 void
MSS_UART_set_pidpei_handler(mss_uart_instance_t * this_uart,mss_uart_irq_handler_t handler)904 MSS_UART_set_pidpei_handler
905 (
906 mss_uart_instance_t * this_uart,
907 mss_uart_irq_handler_t handler
908 )
909 {
910 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
911 ASSERT(handler != INVALID_IRQ_HANDLER);
912
913 if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&
914 (handler != INVALID_IRQ_HANDLER))
915 {
916 this_uart->pid_pei_handler = handler;
917
918 /* Clear any previously pended interrupts */
919 NVIC_ClearPendingIRQ( this_uart->irqn );
920
921 /* Enable PID parity error interrupt. */
922 set_bit_reg8(&this_uart->hw_reg->IEM,EPID_PEI);
923
924 /* Enable UART instance interrupt in Cortex-M3 NVIC. */
925 NVIC_EnableIRQ(this_uart->irqn);
926 }
927 }
928
929 /***************************************************************************//**
930 * See mss_uart.h for details of how to use this function.
931 */
932 void
MSS_UART_set_linbreak_handler(mss_uart_instance_t * this_uart,mss_uart_irq_handler_t handler)933 MSS_UART_set_linbreak_handler
934 (
935 mss_uart_instance_t * this_uart,
936 mss_uart_irq_handler_t handler
937 )
938 {
939 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
940 ASSERT(handler != INVALID_IRQ_HANDLER);
941
942 if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&
943 (handler != INVALID_IRQ_HANDLER))
944 {
945 this_uart->break_handler = handler;
946
947 /* Clear any previously pended interrupts */
948 NVIC_ClearPendingIRQ( this_uart->irqn );
949
950 /* Enable LIN break detection interrupt. */
951 set_bit_reg8(&this_uart->hw_reg->IEM,ELINBI);
952
953 /* Enable UART instance interrupt in Cortex-M3 NVIC. */
954 NVIC_EnableIRQ(this_uart->irqn);
955 }
956 }
957
958 /***************************************************************************//**
959 * See mss_uart.h for details of how to use this function.
960 */
961 void
MSS_UART_set_linsync_handler(mss_uart_instance_t * this_uart,mss_uart_irq_handler_t handler)962 MSS_UART_set_linsync_handler
963 (
964 mss_uart_instance_t * this_uart,
965 mss_uart_irq_handler_t handler
966 )
967 {
968 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
969 ASSERT(handler != INVALID_IRQ_HANDLER);
970
971 if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&
972 (handler != INVALID_IRQ_HANDLER))
973 {
974 this_uart->sync_handler = handler;
975
976 /* Clear any previously pended interrupts */
977 NVIC_ClearPendingIRQ( this_uart->irqn );
978
979 /* Enable LIN sync detection interrupt. */
980 set_bit_reg8(&this_uart->hw_reg->IEM,ELINSI);
981
982 /* Enable UART instance interrupt in Cortex-M3 NVIC. */
983 NVIC_EnableIRQ(this_uart->irqn);
984 }
985 }
986
987 /***************************************************************************//**
988 * See mss_uart.h for details of how to use this function.
989 */
990 void
MSS_UART_set_nack_handler(mss_uart_instance_t * this_uart,mss_uart_irq_handler_t handler)991 MSS_UART_set_nack_handler
992 (
993 mss_uart_instance_t * this_uart,
994 mss_uart_irq_handler_t handler
995 )
996 {
997 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
998 ASSERT(handler != INVALID_IRQ_HANDLER);
999
1000 if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&
1001 (handler != INVALID_IRQ_HANDLER))
1002 {
1003 this_uart->nack_handler = handler;
1004
1005 /* Clear any previously pended interrupts */
1006 NVIC_ClearPendingIRQ( this_uart->irqn );
1007
1008 /* Enable LIN sync detection interrupt. */
1009 set_bit_reg8(&this_uart->hw_reg->IEM,ENACKI);
1010
1011 /* Enable UART instance interrupt in Cortex-M3 NVIC. */
1012 NVIC_EnableIRQ(this_uart->irqn);
1013 }
1014 }
1015
1016 /***************************************************************************//**
1017 * See mss_uart.h for details of how to use this function.
1018 */
1019 void
MSS_UART_set_rx_timeout_handler(mss_uart_instance_t * this_uart,mss_uart_irq_handler_t handler)1020 MSS_UART_set_rx_timeout_handler
1021 (
1022 mss_uart_instance_t * this_uart,
1023 mss_uart_irq_handler_t handler
1024 )
1025 {
1026 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
1027 ASSERT(handler != INVALID_IRQ_HANDLER);
1028
1029 if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&
1030 (handler != INVALID_IRQ_HANDLER))
1031 {
1032 this_uart->rto_handler = handler;
1033
1034 /* Clear any previously pended interrupts */
1035 NVIC_ClearPendingIRQ( this_uart->irqn );
1036
1037 /* Enable receiver timeout interrupt. */
1038 set_bit_reg8(&this_uart->hw_reg->IEM,ERTOI);
1039
1040 /* Enable UART instance interrupt in Cortex-M3 NVIC. */
1041 NVIC_EnableIRQ(this_uart->irqn);
1042 }
1043 }
1044
1045 /***************************************************************************//**
1046 * See mss_uart.h for details of how to use this function.
1047 */
1048 void
MSS_UART_enable_half_duplex(mss_uart_instance_t * this_uart)1049 MSS_UART_enable_half_duplex
1050 (
1051 mss_uart_instance_t * this_uart
1052 )
1053 {
1054 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
1055 if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))
1056 {
1057 /* enable single wire half-duplex mode */
1058 set_bit_reg8(&this_uart->hw_reg->MM2,ESWM);
1059 }
1060 }
1061
1062 /***************************************************************************//**
1063 * See mss_uart.h for details of how to use this function.
1064 */
1065 void
MSS_UART_disable_half_duplex(mss_uart_instance_t * this_uart)1066 MSS_UART_disable_half_duplex
1067 (
1068 mss_uart_instance_t * this_uart
1069 )
1070 {
1071 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
1072 if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))
1073 {
1074 /* enable single wire half-duplex mode */
1075 clear_bit_reg8(&this_uart->hw_reg->MM2,ESWM);
1076 }
1077 }
1078
1079 /***************************************************************************//**
1080 * See mss_uart.h for details of how to use this function.
1081 */
1082 void
MSS_UART_set_rx_endian(mss_uart_instance_t * this_uart,mss_uart_endian_t endian)1083 MSS_UART_set_rx_endian
1084 (
1085 mss_uart_instance_t * this_uart,
1086 mss_uart_endian_t endian
1087 )
1088 {
1089 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
1090 ASSERT(MSS_UART_INVALID_ENDIAN > endian);
1091
1092 if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&
1093 (MSS_UART_INVALID_ENDIAN > endian))
1094 {
1095 /* Configure MSB first / LSB first for receiver */
1096 ((MSS_UART_LITTLEEND == endian) ? (clear_bit_reg8(&this_uart->hw_reg->MM1,E_MSB_RX)) :
1097 (set_bit_reg8(&this_uart->hw_reg->MM1,E_MSB_RX)));
1098 }
1099 }
1100
1101 /***************************************************************************//**
1102 * See mss_uart.h for details of how to use this function.
1103 */
1104 void
MSS_UART_set_tx_endian(mss_uart_instance_t * this_uart,mss_uart_endian_t endian)1105 MSS_UART_set_tx_endian
1106 (
1107 mss_uart_instance_t * this_uart,
1108 mss_uart_endian_t endian
1109 )
1110 {
1111 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
1112 ASSERT(MSS_UART_INVALID_ENDIAN > endian);
1113
1114 if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&
1115 (MSS_UART_INVALID_ENDIAN > endian))
1116 {
1117 /* Configure MSB first / LSB first for transmitter */
1118 ((MSS_UART_LITTLEEND == endian) ? (clear_bit_reg8(&this_uart->hw_reg->MM1,E_MSB_TX)) :
1119 (set_bit_reg8(&this_uart->hw_reg->MM1,E_MSB_TX)) ) ;
1120 }
1121 }
1122
1123 /***************************************************************************//**
1124 * See mss_uart.h for details of how to use this function.
1125 */
1126 void
MSS_UART_set_filter_length(mss_uart_instance_t * this_uart,mss_uart_filter_length_t length)1127 MSS_UART_set_filter_length
1128 (
1129 mss_uart_instance_t * this_uart,
1130 mss_uart_filter_length_t length
1131 )
1132 {
1133 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
1134 ASSERT(MSS_UART_INVALID_FILTER_LENGTH > length);
1135
1136 if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&
1137 (MSS_UART_INVALID_FILTER_LENGTH > length))
1138 {
1139 /* Configure glitch filter length */
1140 this_uart->hw_reg->GFR = (uint8_t)length;
1141 }
1142 }
1143
1144 /***************************************************************************//**
1145 * See mss_uart.h for details of how to use this function.
1146 */
1147 void
MSS_UART_enable_afm(mss_uart_instance_t * this_uart)1148 MSS_UART_enable_afm
1149 (
1150 mss_uart_instance_t * this_uart
1151 )
1152 {
1153 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
1154
1155 if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))
1156 {
1157 /* Disable RX FIFO till address flag with correct address is received */
1158 set_bit_reg8(&this_uart->hw_reg->MM2,EAFM);
1159 }
1160 }
1161
1162 /***************************************************************************//**
1163 * See mss_uart.h for details of how to use this function.
1164 */
1165 void
MSS_UART_disable_afm(mss_uart_instance_t * this_uart)1166 MSS_UART_disable_afm
1167 (
1168 mss_uart_instance_t * this_uart
1169 )
1170 {
1171 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
1172
1173 if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))
1174 {
1175 /* Enable RX FIFO irrespective of address flag and
1176 correct address is received */
1177 clear_bit_reg8(&this_uart->hw_reg->MM2,EAFM);
1178 }
1179 }
1180
1181 /***************************************************************************//**
1182 * See mss_uart.h for details of how to use this function.
1183 */
1184 void
MSS_UART_enable_afclear(mss_uart_instance_t * this_uart)1185 MSS_UART_enable_afclear
1186 (
1187 mss_uart_instance_t * this_uart
1188 )
1189 {
1190 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
1191
1192 if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))
1193 {
1194 /* Enable address flag clearing */
1195 /* Disable RX FIFO till another address flag with
1196 correct address is received */
1197 set_bit_reg8(&this_uart->hw_reg->MM2,EAFC);
1198 }
1199 }
1200
1201 /***************************************************************************//**
1202 * See mss_uart.h for details of how to use this function.
1203 */
1204 void
MSS_UART_disable_afclear(mss_uart_instance_t * this_uart)1205 MSS_UART_disable_afclear
1206 (
1207 mss_uart_instance_t * this_uart
1208 )
1209 {
1210 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
1211
1212 if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))
1213 {
1214 /* Disable address flag clearing */
1215 clear_bit_reg8(&this_uart->hw_reg->MM2,EAFC);
1216 }
1217 }
1218
1219 /***************************************************************************//**
1220 * See mss_uart.h for details of how to use this function.
1221 */
1222 void
MSS_UART_enable_rx_timeout(mss_uart_instance_t * this_uart,uint8_t timeout)1223 MSS_UART_enable_rx_timeout
1224 (
1225 mss_uart_instance_t * this_uart,
1226 uint8_t timeout
1227 )
1228 {
1229 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
1230
1231 if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))
1232 {
1233 /* Load the receive timeout value */
1234 this_uart->hw_reg->RTO = timeout;
1235 /*Enable receiver time-out */
1236 set_bit_reg8(&this_uart->hw_reg->MM0,ERTO);
1237 }
1238 }
1239
1240 /***************************************************************************//**
1241 * See mss_uart.h for details of how to use this function.
1242 */
1243 void
MSS_UART_disable_rx_timeout(mss_uart_instance_t * this_uart)1244 MSS_UART_disable_rx_timeout
1245 (
1246 mss_uart_instance_t * this_uart
1247 )
1248 {
1249 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
1250
1251 if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))
1252 {
1253 /*Disable receiver time-out */
1254 clear_bit_reg8(&this_uart->hw_reg->MM0,ERTO);
1255 }
1256 }
1257
1258 /***************************************************************************//**
1259 * See mss_uart.h for details of how to use this function.
1260 */
1261 void
MSS_UART_enable_tx_time_guard(mss_uart_instance_t * this_uart,uint8_t timeguard)1262 MSS_UART_enable_tx_time_guard
1263 (
1264 mss_uart_instance_t * this_uart,
1265 uint8_t timeguard
1266 )
1267 {
1268 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
1269
1270 if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))
1271 {
1272 /* Load the transmitter time guard value */
1273 this_uart->hw_reg->TTG = timeguard;
1274 /*Enable transmitter time guard */
1275 set_bit_reg8(&this_uart->hw_reg->MM0,ETTG);
1276 }
1277 }
1278
1279 /***************************************************************************//**
1280 * See mss_uart.h for details of how to use this function.
1281 */
1282 void
MSS_UART_disable_tx_time_guard(mss_uart_instance_t * this_uart)1283 MSS_UART_disable_tx_time_guard
1284 (
1285 mss_uart_instance_t * this_uart
1286 )
1287 {
1288 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
1289
1290 if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))
1291 {
1292 /*Disable transmitter time guard */
1293 clear_bit_reg8(&this_uart->hw_reg->MM0,ETTG);
1294 }
1295 }
1296
1297 /***************************************************************************//**
1298 * See mss_uart.h for details of how to use this function.
1299 */
1300 void
MSS_UART_set_address(mss_uart_instance_t * this_uart,uint8_t address)1301 MSS_UART_set_address
1302 (
1303 mss_uart_instance_t * this_uart,
1304 uint8_t address
1305 )
1306 {
1307 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
1308
1309 if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))
1310 {
1311 this_uart->hw_reg->ADR = address;
1312 }
1313 }
1314
1315 /***************************************************************************//**
1316 * See mss_uart.h for details of how to use this function.
1317 */
1318 void
MSS_UART_set_ready_mode(mss_uart_instance_t * this_uart,mss_uart_ready_mode_t mode)1319 MSS_UART_set_ready_mode
1320 (
1321 mss_uart_instance_t * this_uart,
1322 mss_uart_ready_mode_t mode
1323 )
1324 {
1325 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
1326 ASSERT(MSS_UART_INVALID_READY_MODE > mode);
1327
1328 if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&
1329 (MSS_UART_INVALID_READY_MODE > mode ) )
1330 {
1331 /* Configure mode 0 or mode 1 for TXRDY and RXRDY */
1332 ((MSS_UART_READY_MODE0 == mode) ? clear_bit_reg8(&this_uart->hw_reg->FCR,RDYMODE) :
1333 set_bit_reg8(&this_uart->hw_reg->FCR,RDYMODE) );
1334 }
1335 }
1336
1337 /***************************************************************************//**
1338 * Configure baud divisors using fractional baud rate if possible.
1339 */
1340 static void
config_baud_divisors(mss_uart_instance_t * this_uart,uint32_t baudrate)1341 config_baud_divisors
1342 (
1343 mss_uart_instance_t * this_uart,
1344 uint32_t baudrate
1345 )
1346 {
1347 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
1348
1349 if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))
1350 {
1351 uint32_t baud_value;
1352 uint32_t baud_value_by_64;
1353 uint32_t baud_value_by_128;
1354 uint32_t fractional_baud_value;
1355 uint32_t pclk_freq;
1356
1357 this_uart->baudrate = baudrate;
1358
1359 /* Force the value of the CMSIS global variables holding the various system
1360 * clock frequencies to be updated. */
1361 SystemCoreClockUpdate();
1362 if(this_uart == &g_mss_uart0)
1363 {
1364 pclk_freq = g_FrequencyPCLK0;
1365 }
1366 else
1367 {
1368 pclk_freq = g_FrequencyPCLK1;
1369 }
1370
1371 /*
1372 * Compute baud value based on requested baud rate and PCLK frequency.
1373 * The baud value is computed using the following equation:
1374 * baud_value = PCLK_Frequency / (baud_rate * 16)
1375 */
1376 baud_value_by_128 = (8u * pclk_freq) / baudrate;
1377 baud_value_by_64 = baud_value_by_128 / 2u;
1378 baud_value = baud_value_by_64 / 64u;
1379 fractional_baud_value = baud_value_by_64 - (baud_value * 64u);
1380 fractional_baud_value += (baud_value_by_128 - (baud_value * 128u)) - (fractional_baud_value * 2u);
1381
1382 /* Assert if integer baud value fits in 16-bit. */
1383 ASSERT(baud_value <= UINT16_MAX);
1384
1385 if(baud_value <= (uint32_t)UINT16_MAX)
1386 {
1387 if(baud_value > 1u)
1388 {
1389 /*
1390 * Use Frational baud rate divisors
1391 */
1392 /* set divisor latch */
1393 set_bit_reg8(&this_uart->hw_reg->LCR,DLAB);
1394
1395 /* msb of baud value */
1396 this_uart->hw_reg->DMR = (uint8_t)(baud_value >> 8);
1397 /* lsb of baud value */
1398 this_uart->hw_reg->DLR = (uint8_t)baud_value;
1399
1400 /* reset divisor latch */
1401 clear_bit_reg8(&this_uart->hw_reg->LCR,DLAB);
1402
1403 /* Enable Fractional baud rate */
1404 set_bit_reg8(&this_uart->hw_reg->MM0,EFBR);
1405
1406 /* Load the fractional baud rate register */
1407 ASSERT(fractional_baud_value <= (uint32_t)UINT8_MAX);
1408 this_uart->hw_reg->DFR = (uint8_t)fractional_baud_value;
1409 }
1410 else
1411 {
1412 /*
1413 * Do NOT use Frational baud rate divisors.
1414 */
1415 /* set divisor latch */
1416 set_bit_reg8(&this_uart->hw_reg->LCR,DLAB);
1417
1418 /* msb of baud value */
1419 this_uart->hw_reg->DMR = (uint8_t)(baud_value >> 8u);
1420 /* lsb of baud value */
1421 this_uart->hw_reg->DLR = (uint8_t)baud_value;
1422
1423 /* reset divisor latch */
1424 clear_bit_reg8(&this_uart->hw_reg->LCR,DLAB);
1425
1426 /* Disable Fractional baud rate */
1427 clear_bit_reg8(&this_uart->hw_reg->MM0,EFBR);
1428 }
1429 }
1430 }
1431 }
1432
1433 /***************************************************************************//**
1434 * See mss_uart.h for details of how to use this function.
1435 */
1436 void
MSS_UART_set_usart_mode(mss_uart_instance_t * this_uart,mss_uart_usart_mode_t mode)1437 MSS_UART_set_usart_mode
1438 (
1439 mss_uart_instance_t * this_uart,
1440 mss_uart_usart_mode_t mode
1441 )
1442 {
1443 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
1444 ASSERT(MSS_UART_INVALID_SYNC_MODE > mode);
1445
1446 if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&
1447 (MSS_UART_INVALID_SYNC_MODE > mode))
1448 {
1449 /* Nothing to do for the baudrate: operates at PCLK / 2 + glitch filter length */
1450 /* Clear the ESYN bits 2:0 */
1451 this_uart->hw_reg->MM0 &= ~SYNC_ASYNC_MODE_MASK;
1452 this_uart->hw_reg->MM0 |= (uint8_t)mode;
1453 }
1454 }
1455
1456 /*******************************************************************************
1457 * Local Functions
1458 *******************************************************************************/
1459 /*******************************************************************************
1460 * Global initialization for all modes
1461 */
global_init(mss_uart_instance_t * this_uart,uint32_t baud_rate,uint8_t line_config)1462 static void global_init
1463 (
1464 mss_uart_instance_t * this_uart,
1465 uint32_t baud_rate,
1466 uint8_t line_config
1467 )
1468 {
1469 /* The driver expects g_mss_uart0 and g_mss_uart1 to be the only
1470 * mss_uart_instance_t instances used to identify UART0 and UART1. */
1471 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
1472
1473 if(this_uart == &g_mss_uart0)
1474 {
1475 this_uart->hw_reg = UART0;
1476 this_uart->irqn = UART0_IRQn;
1477 /* reset UART0 */
1478 SYSREG->SOFT_RST_CR |= SYSREG_MMUART0_SOFTRESET_MASK;
1479 /* Clear any previously pended UART0 interrupt */
1480 NVIC_ClearPendingIRQ(UART0_IRQn);
1481 /* Take UART0 out of reset. */
1482 SYSREG->SOFT_RST_CR &= ~SYSREG_MMUART0_SOFTRESET_MASK;
1483 }
1484 else
1485 {
1486 this_uart->hw_reg = UART1;
1487 this_uart->irqn = UART1_IRQn;
1488 /* Reset UART1 */
1489 SYSREG->SOFT_RST_CR |= SYSREG_MMUART1_SOFTRESET_MASK;
1490 /* Clear any previously pended UART1 interrupt */
1491 NVIC_ClearPendingIRQ(UART1_IRQn);
1492 /* Take UART1 out of reset. */
1493 SYSREG->SOFT_RST_CR &= ~SYSREG_MMUART1_SOFTRESET_MASK;
1494 }
1495
1496 /* disable interrupts */
1497 this_uart->hw_reg->IER = 0u;
1498
1499 /* FIFO configuration */
1500 this_uart->hw_reg->FCR = (uint8_t)MSS_UART_FIFO_SINGLE_BYTE;
1501 /* clear receiver FIFO */
1502 set_bit_reg8(&this_uart->hw_reg->FCR,CLEAR_RX_FIFO);
1503 /* clear transmitter FIFO */
1504 set_bit_reg8(&this_uart->hw_reg->FCR,CLEAR_TX_FIFO);
1505
1506 /* set default READY mode : Mode 0*/
1507 /* enable RXRDYN and TXRDYN pins. The earlier FCR write to set the TX FIFO
1508 * trigger level inadvertently disabled the FCR_RXRDY_TXRDYN_EN bit. */
1509 set_bit_reg8(&this_uart->hw_reg->FCR,RXRDY_TXRDYN_EN);
1510
1511 /* disable loopback : local * remote */
1512 clear_bit_reg8(&this_uart->hw_reg->MCR,LOOP);
1513 clear_bit_reg8(&this_uart->hw_reg->MCR,RLOOP);
1514
1515 /* set default TX endian */
1516 clear_bit_reg8(&this_uart->hw_reg->MM1,E_MSB_TX);
1517 /* set default RX endian */
1518 clear_bit_reg8(&this_uart->hw_reg->MM1,E_MSB_RX);
1519
1520 /* default AFM : disabled */
1521 clear_bit_reg8(&this_uart->hw_reg->MM2,EAFM);
1522
1523 /* disable TX time gaurd */
1524 clear_bit_reg8(&this_uart->hw_reg->MM0,ETTG);
1525
1526 /* set default RX timeout */
1527 clear_bit_reg8(&this_uart->hw_reg->MM0,ERTO);
1528
1529 /* disable fractional baud-rate */
1530 clear_bit_reg8(&this_uart->hw_reg->MM0,EFBR);
1531
1532 /* disable single wire mode */
1533 clear_bit_reg8(&this_uart->hw_reg->MM2,ESWM);
1534
1535 /* set filter to minimum value */
1536 this_uart->hw_reg->GFR = 0u;
1537 /* set default TX time gaurd */
1538 this_uart->hw_reg->TTG = 0u;
1539 /* set default RX timeout */
1540 this_uart->hw_reg->RTO = 0u;
1541
1542 /*
1543 * Configure baud rate divisors. This uses the frational baud rate divisor
1544 * where possible to provide the most accurate baud rat possible.
1545 */
1546 config_baud_divisors(this_uart, baud_rate);
1547
1548 /* set the line control register (bit length, stop bits, parity) */
1549 this_uart->hw_reg->LCR = line_config;
1550
1551 /* Instance setup */
1552 this_uart->baudrate = baud_rate;
1553 this_uart->lineconfig = line_config;
1554 this_uart->tx_buff_size = TX_COMPLETE;
1555 this_uart->tx_buffer = (const uint8_t *)0;
1556 this_uart->tx_idx = 0u;
1557
1558 /* Default handlers for MSS UART interrupts */
1559 this_uart->rx_handler = NULL_HANDLER;
1560 this_uart->tx_handler = NULL_HANDLER;
1561 this_uart->linests_handler = NULL_HANDLER;
1562 this_uart->modemsts_handler = NULL_HANDLER;
1563 this_uart->rto_handler = NULL_HANDLER;
1564 this_uart->nack_handler = NULL_HANDLER;
1565 this_uart->pid_pei_handler = NULL_HANDLER;
1566 this_uart->break_handler = NULL_HANDLER;
1567 this_uart->sync_handler = NULL_HANDLER;
1568
1569 /* Initialize the sticky status */
1570 this_uart->status = 0u;
1571 }
1572
1573 /***************************************************************************//**
1574 * Interrupt service routine triggered by any MSS UART interrupt. This routine
1575 * will call the handler function appropriate to the interrupt from the
1576 * handlers previously registered with the driver through calls to the
1577 * MSS_UART_set_*_handler() functions, or it will call the default_tx_handler()
1578 * function in response to transmit interrupts if MSS_UART_irq_tx() is used to
1579 * transmit data.
1580 */
1581 static void
MSS_UART_isr(mss_uart_instance_t * this_uart)1582 MSS_UART_isr
1583 (
1584 mss_uart_instance_t * this_uart
1585 )
1586 {
1587 uint8_t iirf;
1588
1589 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
1590
1591 if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))
1592 {
1593 iirf = this_uart->hw_reg->IIR & IIRF_MASK;
1594
1595 switch (iirf)
1596 {
1597 case IIRF_MODEM_STATUS: /* Modem status interrupt */
1598 {
1599 ASSERT(NULL_HANDLER != this_uart->modemsts_handler);
1600 if(NULL_HANDLER != this_uart->modemsts_handler)
1601 {
1602 (*(this_uart->modemsts_handler))(this_uart);
1603 }
1604 }
1605 break;
1606
1607 case IIRF_THRE: /* Transmitter Holding Register Empty */
1608 {
1609 ASSERT(NULL_HANDLER != this_uart->tx_handler);
1610 if(NULL_HANDLER != this_uart->tx_handler)
1611 {
1612 (*(this_uart->tx_handler))(this_uart);
1613 }
1614 }
1615 break;
1616
1617 case IIRF_RX_DATA: /* Received Data Available */
1618 case IIRF_DATA_TIMEOUT: /* Received Data Timed-out */
1619 {
1620 ASSERT(NULL_HANDLER != this_uart->rx_handler);
1621 if(NULL_HANDLER != this_uart->rx_handler)
1622 {
1623 (*(this_uart->rx_handler))(this_uart);
1624 }
1625 }
1626 break;
1627
1628 case IIRF_RX_LINE_STATUS: /* Line Status Interrupt */
1629 {
1630 ASSERT(NULL_HANDLER != this_uart->linests_handler);
1631 if(NULL_HANDLER != this_uart->linests_handler)
1632 {
1633 (*(this_uart->linests_handler))(this_uart);
1634 }
1635 }
1636 break;
1637
1638 case IIRF_MMI:
1639 {
1640 /* Identify multimode interrupts and handle */
1641
1642 /* Receiver time-out interrupt */
1643 if(read_bit_reg8(&this_uart->hw_reg->IIM,ERTOI))
1644 {
1645 ASSERT(NULL_HANDLER != this_uart->rto_handler);
1646 if(NULL_HANDLER != this_uart->rto_handler)
1647 {
1648 (*(this_uart->rto_handler))(this_uart);
1649 }
1650 }
1651 /* NACK interrupt */
1652 if(read_bit_reg8(&this_uart->hw_reg->IIM,ENACKI))
1653 {
1654 ASSERT(NULL_HANDLER != this_uart->nack_handler);
1655 if(NULL_HANDLER != this_uart->nack_handler)
1656 {
1657 (*(this_uart->nack_handler))(this_uart);
1658 }
1659 }
1660
1661 /* PID parity error interrupt */
1662 if(read_bit_reg8(&this_uart->hw_reg->IIM,EPID_PEI))
1663 {
1664 ASSERT(NULL_HANDLER != this_uart->pid_pei_handler);
1665 if(NULL_HANDLER != this_uart->pid_pei_handler)
1666 {
1667 (*(this_uart->pid_pei_handler))(this_uart);
1668 }
1669 }
1670
1671 /* LIN break detection interrupt */
1672 if(read_bit_reg8(&this_uart->hw_reg->IIM,ELINBI))
1673 {
1674 ASSERT(NULL_HANDLER != this_uart->break_handler);
1675 if(NULL_HANDLER != this_uart->break_handler)
1676 {
1677 (*(this_uart->break_handler))(this_uart);
1678 }
1679 }
1680
1681 /* LIN Sync detection interrupt */
1682 if(read_bit_reg8(&this_uart->hw_reg->IIM,ELINSI))
1683 {
1684 ASSERT(NULL_HANDLER != this_uart->sync_handler);
1685 if(NULL_HANDLER != this_uart->sync_handler)
1686 {
1687 (*(this_uart->sync_handler))(this_uart);
1688 }
1689 }
1690 break;
1691 }
1692
1693 default:
1694 {
1695 ASSERT(INVALID_INTERRUPT);
1696 }
1697 break;
1698 }
1699 }
1700 }
1701
1702 /***************************************************************************//**
1703 * See mss_uart.h for details of how to use this function.
1704 */
1705 static void
default_tx_handler(mss_uart_instance_t * this_uart)1706 default_tx_handler
1707 (
1708 mss_uart_instance_t * this_uart
1709 )
1710 {
1711 uint8_t status;
1712
1713 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
1714 ASSERT(( (uint8_t *)0 ) != this_uart->tx_buffer);
1715 ASSERT(0u < this_uart->tx_buff_size);
1716
1717 if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&
1718 (((uint8_t *)0 ) != this_uart->tx_buffer) &&
1719 (0u < this_uart->tx_buff_size))
1720 {
1721 /* Read the Line Status Register and update the sticky record. */
1722 status = this_uart->hw_reg->LSR;
1723 this_uart->status |= status;
1724
1725 /*
1726 * This function should only be called as a result of a THRE interrupt.
1727 * Verify that this is true before proceeding to transmit data.
1728 */
1729 if(status & MSS_UART_THRE)
1730 {
1731 uint32_t i;
1732 uint32_t fill_size = TX_FIFO_SIZE;
1733 uint32_t tx_remain = this_uart->tx_buff_size - this_uart->tx_idx;
1734
1735 /* Calculate the number of bytes to transmit. */
1736 if(tx_remain < TX_FIFO_SIZE)
1737 {
1738 fill_size = tx_remain;
1739 }
1740
1741 /* Fill the TX FIFO with the calculated the number of bytes. */
1742 for(i = 0u; i < fill_size; ++i)
1743 {
1744 /* Send next character in the buffer. */
1745 this_uart->hw_reg->THR = this_uart->tx_buffer[this_uart->tx_idx];
1746 ++this_uart->tx_idx;
1747 }
1748 }
1749
1750 /* Flag Tx as complete if all data has been pushed into the Tx FIFO. */
1751 if(this_uart->tx_idx == this_uart->tx_buff_size)
1752 {
1753 this_uart->tx_buff_size = TX_COMPLETE;
1754 /* disables TX interrupt */
1755 clear_bit_reg8(&this_uart->hw_reg->IER,ETBEI);
1756 }
1757 }
1758 }
1759
1760 #ifdef __cplusplus
1761 }
1762 #endif
1763