1 /*******************************************************************************
\r
2 * (c) Copyright 2011-2013 Microsemi SoC Products Group. All rights reserved.
\r
4 * SmartFusion2 Microcontroller Subsystem MMUART bare metal software driver
\r
7 * SVN $Revision: 5610 $
\r
8 * SVN $Date: 2013-04-05 14:19:30 +0100 (Fri, 05 Apr 2013) $
\r
10 #include "mss_uart.h"
\r
11 #include "mss_uart_regs.h"
\r
12 #include "../../CMSIS/mss_assert.h"
\r
13 #include "../../CMSIS/hw_reg_io.h"
\r
14 #include "../../CMSIS/system_m2sxxx.h"
\r
20 /*******************************************************************************
\r
23 #define TX_COMPLETE 0u
\r
24 #define TX_FIFO_SIZE 16u
\r
26 #define FCR_TRIG_LEVEL_MASK 0xC0u
\r
28 #define IIRF_MASK 0x0Fu
\r
30 #define INVALID_INTERRUPT 0u
\r
31 #define INVALID_IRQ_HANDLER ((mss_uart_irq_handler_t) 0)
\r
32 #define NULL_HANDLER ((mss_uart_irq_handler_t) 0)
\r
34 #define MSS_UART_DATA_READY ((uint8_t) 0x01)
\r
36 #define SYNC_ASYNC_MODE_MASK (0x7u)
\r
38 /*******************************************************************************
\r
39 * Possible values for Interrupt Identification Register Field.
\r
41 #define IIRF_MODEM_STATUS 0x00u
\r
42 #define IIRF_THRE 0x02u
\r
43 #define IIRF_MMI 0x03u
\r
44 #define IIRF_RX_DATA 0x04u
\r
45 #define IIRF_RX_LINE_STATUS 0x06u
\r
46 #define IIRF_DATA_TIMEOUT 0x0Cu
\r
48 /*******************************************************************************
\r
49 * Receiver error status mask.
\r
51 #define STATUS_ERROR_MASK ( MSS_UART_OVERUN_ERROR | MSS_UART_PARITY_ERROR | \
\r
52 MSS_UART_FRAMING_ERROR | MSS_UART_BREAK_ERROR | \
\r
53 MSS_UART_FIFO_ERROR)
\r
55 /*******************************************************************************
\r
56 * Cortex-M3 interrupt handler functions implemented as part of the MSS UART
\r
59 #if defined(__GNUC__)
\r
60 __attribute__((__interrupt__)) void UART0_IRQHandler(void);
\r
62 void UART0_IRQHandler(void);
\r
65 #if defined(__GNUC__)
\r
66 __attribute__((__interrupt__)) void UART1_IRQHandler(void);
\r
68 void UART1_IRQHandler(void);
\r
71 /*******************************************************************************
\r
74 static void global_init(mss_uart_instance_t * this_uart, uint32_t baud_rate,
\r
75 uint8_t line_config);
\r
76 static void MSS_UART_isr(mss_uart_instance_t * this_uart);
\r
77 static void default_tx_handler(mss_uart_instance_t * this_uart);
\r
79 static void config_baud_divisors
\r
81 mss_uart_instance_t * this_uart,
\r
85 /*******************************************************************************
\r
86 * Instance definitions
\r
88 mss_uart_instance_t g_mss_uart0;
\r
89 mss_uart_instance_t g_mss_uart1;
\r
92 /*******************************************************************************
\r
94 *******************************************************************************/
\r
95 /***************************************************************************//**
\r
96 * See mss_uart.h for details of how to use this function.
\r
101 mss_uart_instance_t* this_uart,
\r
102 uint32_t baud_rate,
\r
103 uint8_t line_config
\r
106 /* The driver expects g_mss_uart0 and g_mss_uart1 to be the only
\r
107 * mss_uart_instance_t instances used to identify UART0 and UART1. */
\r
108 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
\r
110 /* Perform generic initialization */
\r
111 global_init(this_uart, baud_rate, line_config);
\r
113 /* Disable LIN mode */
\r
114 clear_bit_reg8(&this_uart->hw_reg->MM0, ELIN);
\r
116 /* Disable IrDA mode */
\r
117 clear_bit_reg8(&this_uart->hw_reg->MM1, EIRD);
\r
119 /* Disable SmartCard Mode */
\r
120 clear_bit_reg8(&this_uart->hw_reg->MM2, EERR);
\r
122 /* set default tx handler for automated TX using interrupt in USART mode */
\r
123 this_uart->tx_handler = default_tx_handler;
\r
126 /***************************************************************************//**
\r
127 * See mss_uart.h for details of how to use this function.
\r
129 void MSS_UART_lin_init
\r
131 mss_uart_instance_t* this_uart,
\r
132 uint32_t baud_rate,
\r
133 uint8_t line_config
\r
136 /* The driver expects g_mss_uart0 and g_mss_uart1 to be the only
\r
137 * mss_uart_instance_t instances used to identify UART0 and UART1. */
\r
138 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
\r
140 /* Perform generic initialization */
\r
141 global_init(this_uart, baud_rate, line_config);
\r
143 /* Enable LIN mode */
\r
144 set_bit_reg8(&this_uart->hw_reg->MM0, ELIN);
\r
146 /* Disable IrDA mode */
\r
147 clear_bit_reg8(&this_uart->hw_reg->MM1, EIRD);
\r
149 /* Disable SmartCard Mode */
\r
150 clear_bit_reg8(&this_uart->hw_reg->MM2, EERR);
\r
153 /***************************************************************************//**
\r
154 * See mss_uart.h for details of how to use this function.
\r
159 mss_uart_instance_t* this_uart,
\r
160 uint32_t baud_rate,
\r
161 uint8_t line_config,
\r
162 mss_uart_rzi_polarity_t rxpol,
\r
163 mss_uart_rzi_polarity_t txpol,
\r
164 mss_uart_rzi_pulsewidth_t pw
\r
167 /* The driver expects g_mss_uart0 and g_mss_uart1 to be the only
\r
168 * mss_uart_instance_t instances used to identify UART0 and UART1. */
\r
169 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
\r
171 /* Perform generic initialization */
\r
172 global_init(this_uart, baud_rate, line_config);
\r
174 /* Enable LIN mode */
\r
175 clear_bit_reg8(&this_uart->hw_reg->MM0, ELIN);
\r
177 /* Disable IrDA mode */
\r
178 set_bit_reg8(&this_uart->hw_reg->MM1, EIRD);
\r
179 ((rxpol == MSS_UART_ACTIVE_LOW) ? clear_bit_reg8(&this_uart->hw_reg->MM1,EIRX) :
\r
180 set_bit_reg8(&this_uart->hw_reg->MM1,EIRX));
\r
182 ((txpol == MSS_UART_ACTIVE_LOW) ? clear_bit_reg8(&this_uart->hw_reg->MM1,EITX) :
\r
183 set_bit_reg8(&this_uart->hw_reg->MM1,EITX));
\r
185 ((pw == MSS_UART_3_BY_16) ? clear_bit_reg8(&this_uart->hw_reg->MM1,EITP) :
\r
186 set_bit_reg8(&this_uart->hw_reg->MM1,EITP));
\r
187 /* Disable SmartCard Mode */
\r
188 clear_bit_reg8(&this_uart->hw_reg->MM2, EERR);
\r
191 /***************************************************************************//**
\r
192 * See mss_uart.h for details of how to use this function.
\r
195 MSS_UART_smartcard_init
\r
197 mss_uart_instance_t* this_uart,
\r
198 uint32_t baud_rate,
\r
199 uint8_t line_config
\r
202 /* The driver expects g_mss_uart0 and g_mss_uart1 to be the only
\r
203 * mss_uart_instance_t instances used to identify UART0 and UART1. */
\r
204 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
\r
206 /* Perform generic initialization */
\r
207 global_init(this_uart, baud_rate, line_config);
\r
209 /* Disable LIN mode */
\r
210 clear_bit_reg8(&this_uart->hw_reg->MM0, ELIN);
\r
212 /* Disable IrDA mode */
\r
213 clear_bit_reg8(&this_uart->hw_reg->MM1, EIRD);
\r
215 /* Enable SmartCard Mode : Only when data is 8-bit and 2 stop bits*/
\r
216 if( ( MSS_UART_DATA_8_BITS | MSS_UART_TWO_STOP_BITS) ==
\r
217 (line_config & (MSS_UART_DATA_8_BITS | MSS_UART_TWO_STOP_BITS)))
\r
219 set_bit_reg8(&this_uart->hw_reg->MM2, EERR);
\r
220 /* Enable single wire half-duplex mode */
\r
221 set_bit_reg8(&this_uart->hw_reg->MM2,ESWM);
\r
225 /***************************************************************************//**
\r
226 * See mss_uart.h for details of how to use this function.
\r
231 mss_uart_instance_t * this_uart,
\r
232 const uint8_t * pbuff,
\r
236 uint32_t char_idx = 0u;
\r
237 uint32_t size_sent;
\r
240 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
\r
241 ASSERT(pbuff != ( (uint8_t *)0));
\r
242 ASSERT(tx_size > 0u);
\r
244 if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&
\r
245 (pbuff != ((uint8_t *)0)) && (tx_size > 0u))
\r
247 /* Remain in this loop until the entire input buffer
\r
248 * has been transferred to the UART.
\r
251 /* Read the Line Status Register and update the sticky record */
\r
252 status = this_uart->hw_reg->LSR;
\r
253 this_uart->status |= status;
\r
255 /* Check if TX FIFO is empty. */
\r
256 if(status & MSS_UART_THRE)
\r
258 uint32_t fill_size = TX_FIFO_SIZE;
\r
260 /* Calculate the number of bytes to transmit. */
\r
261 if(tx_size < TX_FIFO_SIZE)
\r
263 fill_size = tx_size;
\r
266 /* Fill the TX FIFO with the calculated the number of bytes. */
\r
267 for(size_sent = 0u; size_sent < fill_size; ++size_sent)
\r
269 /* Send next character in the buffer. */
\r
270 this_uart->hw_reg->THR = pbuff[char_idx];
\r
274 /* Calculate the number of untransmitted bytes remaining. */
\r
275 tx_size -= size_sent;
\r
281 /***************************************************************************//**
\r
282 * See mss_uart.h for details of how to use this function.
\r
285 MSS_UART_polled_tx_string
\r
287 mss_uart_instance_t * this_uart,
\r
288 const uint8_t * p_sz_string
\r
291 uint32_t char_idx = 0u;
\r
292 uint32_t fill_size;
\r
296 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
\r
297 ASSERT(p_sz_string != ((uint8_t *)0));
\r
299 if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&
\r
300 (p_sz_string != ((uint8_t *)0)))
\r
302 /* Get the first data byte from the input buffer */
\r
303 data_byte = p_sz_string[char_idx];
\r
305 /* First check for the NULL terminator byte.
\r
306 * Then remain in this loop until the entire string in the input buffer
\r
307 * has been transferred to the UART.
\r
309 while(0u != data_byte)
\r
311 /* Wait until TX FIFO is empty. */
\r
313 status = this_uart->hw_reg->LSR;
\r
314 this_uart->status |= status;
\r
315 } while (0u == (status & MSS_UART_THRE));
\r
317 /* Send bytes from the input buffer until the TX FIFO is full
\r
318 * or we reach the NULL terminator byte.
\r
321 while((0u != data_byte) && (fill_size < TX_FIFO_SIZE))
\r
323 /* Send the data byte */
\r
324 this_uart->hw_reg->THR = data_byte;
\r
327 /* Get the next data byte from the input buffer */
\r
328 data_byte = p_sz_string[char_idx];
\r
334 /***************************************************************************//**
\r
335 * See mss_uart.h for details of how to use this function.
\r
340 mss_uart_instance_t * this_uart,
\r
341 const uint8_t * pbuff,
\r
345 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
\r
346 ASSERT(pbuff != ((uint8_t *)0));
\r
347 ASSERT(tx_size > 0u);
\r
349 if((tx_size > 0u) && ( pbuff != ((uint8_t *)0)) &&
\r
350 ((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)))
\r
352 /*Initialise the transmit info for the UART instance with the arguments.*/
\r
353 this_uart->tx_buffer = pbuff;
\r
354 this_uart->tx_buff_size = tx_size;
\r
355 this_uart->tx_idx = (uint16_t)0;
\r
357 /* Clear any previously pended interrupts */
\r
358 NVIC_ClearPendingIRQ(this_uart->irqn);
\r
360 /* assign default handler for data transfer */
\r
361 this_uart->tx_handler = default_tx_handler;
\r
363 /* enables TX interrupt */
\r
364 set_bit_reg8(&this_uart->hw_reg->IER,ETBEI);
\r
366 /* Enable UART instance interrupt in Cortex-M3 NVIC. */
\r
367 NVIC_EnableIRQ(this_uart->irqn);
\r
371 /***************************************************************************//**
\r
372 * See mss_uart.h for details of how to use this function.
\r
375 MSS_UART_tx_complete
\r
377 mss_uart_instance_t * this_uart
\r
380 int8_t ret_value = 0;
\r
381 uint8_t status = 0u;
\r
383 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
\r
385 if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))
\r
387 /* Read the Line Status Register and update the sticky record. */
\r
388 status = this_uart->hw_reg->LSR;
\r
389 this_uart->status |= status;
\r
391 if((TX_COMPLETE == this_uart->tx_buff_size) &&
\r
392 ((status & MSS_UART_TEMT) != 0u))
\r
394 ret_value = (int8_t)1;
\r
401 /***************************************************************************//**
\r
402 * See mss_uart.h for details of how to use this function.
\r
407 mss_uart_instance_t * this_uart,
\r
412 size_t rx_size = 0u;
\r
413 uint8_t status = 0u;
\r
415 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
\r
416 ASSERT(rx_buff != ((uint8_t *)0));
\r
417 ASSERT(buff_size > 0u);
\r
419 if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&
\r
420 (rx_buff != ((uint8_t *)0)) && (buff_size > 0u))
\r
422 status = this_uart->hw_reg->LSR;
\r
423 this_uart->status |= status;
\r
425 while(((status & MSS_UART_DATA_READY) != 0u) &&
\r
426 (rx_size < buff_size))
\r
428 rx_buff[rx_size] = this_uart->hw_reg->RBR;
\r
430 status = this_uart->hw_reg->LSR;
\r
431 this_uart->status |= status;
\r
436 /***************************************************************************//**
\r
437 * See mss_uart.h for details of how to use this function.
\r
440 MSS_UART_enable_irq
\r
442 mss_uart_instance_t * this_uart,
\r
443 mss_uart_irq_t irq_mask
\r
446 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
\r
447 ASSERT(MSS_UART_INVALID_IRQ > irq_mask);
\r
449 if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&
\r
450 (MSS_UART_INVALID_IRQ > irq_mask))
\r
452 /* Clear any previously pended interrupts */
\r
453 NVIC_ClearPendingIRQ(this_uart->irqn);
\r
455 /* irq_mask encoding: 1- enable
\r
456 * bit 0 - Receive Data Available Interrupt
\r
457 * bit 1 - Transmitter Holding Register Empty Interrupt
\r
458 * bit 2 - Receiver Line Status Interrupt
\r
459 * bit 3 - Modem Status Interrupt
\r
461 this_uart->hw_reg->IER |= (uint8_t)irq_mask & IIRF_MASK;
\r
464 * bit 4 - Receiver time-out interrupt
\r
465 * bit 5 - NACK / ERR signal interrupt
\r
466 * bit 6 - PID parity error interrupt
\r
467 * bit 7 - LIN break detection interrupt
\r
468 * bit 8 - LIN Sync detection interrupt
\r
470 this_uart->hw_reg->IEM |= (uint8_t)(((uint32_t)irq_mask & ~((uint32_t)IIRF_MASK)) >> 4u);
\r
472 /* Enable UART instance interrupt in Cortex-M3 NVIC. */
\r
473 NVIC_EnableIRQ(this_uart->irqn);
\r
477 /***************************************************************************//**
\r
478 * See mss_uart.h for details of how to use this function.
\r
481 MSS_UART_disable_irq
\r
483 mss_uart_instance_t * this_uart,
\r
484 mss_uart_irq_t irq_mask
\r
487 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
\r
489 if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))
\r
491 /* irq_mask encoding: 1 - disable
\r
492 * bit 0 - Receive Data Available Interrupt
\r
493 * bit 1 - Transmitter Holding Register Empty Interrupt
\r
494 * bit 2 - Receiver Line Status Interrupt
\r
495 * bit 3 - Modem Status Interrupt
\r
497 this_uart->hw_reg->IER &= ((uint8_t)(~((uint32_t)irq_mask & (uint32_t)IIRF_MASK)));
\r
500 * bit 4 - Receiver time-out interrupt
\r
501 * bit 5 - NACK / ERR signal interrupt
\r
502 * bit 6 - PID parity error interrupt
\r
503 * bit 7 - LIN break detection interrupt
\r
504 * bit 8 - LIN Sync detection interrupt
\r
506 this_uart->hw_reg->IEM |= (uint8_t)(~(((uint32_t)irq_mask & ~((uint32_t)IIRF_MASK)) >> 8u));
\r
508 /* Clear any previously pended interrupts */
\r
509 NVIC_ClearPendingIRQ(this_uart->irqn);
\r
511 if(irq_mask == IIRF_MASK)
\r
513 /* Disable UART instance interrupt in Cortex-M3 NVIC. */
\r
514 NVIC_DisableIRQ(this_uart->irqn);
\r
520 /***************************************************************************//**
\r
521 * See mss_uart.h for details of how to use this function.
\r
524 MSS_UART_set_rx_handler
\r
526 mss_uart_instance_t * this_uart,
\r
527 mss_uart_irq_handler_t handler,
\r
528 mss_uart_rx_trig_level_t trigger_level
\r
531 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
\r
532 ASSERT(handler != INVALID_IRQ_HANDLER );
\r
533 ASSERT(trigger_level < MSS_UART_FIFO_INVALID_TRIG_LEVEL);
\r
535 if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&
\r
536 (handler != INVALID_IRQ_HANDLER) &&
\r
537 (trigger_level < MSS_UART_FIFO_INVALID_TRIG_LEVEL))
\r
539 this_uart->rx_handler = handler;
\r
541 /* Set the receive interrupt trigger level. */
\r
542 this_uart->hw_reg->FCR = (this_uart->hw_reg->FCR &
\r
543 (uint8_t)(~((uint8_t)FCR_TRIG_LEVEL_MASK))) |
\r
544 (uint8_t)trigger_level;
\r
545 /* Clear any previously pended interrupts */
\r
546 NVIC_ClearPendingIRQ(this_uart->irqn);
\r
548 /* Enable receive interrupt. */
\r
549 set_bit_reg8(&this_uart->hw_reg->IER,ERBFI);
\r
551 /* Enable UART instance interrupt in Cortex-M3 NVIC. */
\r
552 NVIC_EnableIRQ(this_uart->irqn);
\r
556 /***************************************************************************//**
\r
557 * See mss_uart.h for details of how to use this function.
\r
560 MSS_UART_set_loopback
\r
562 mss_uart_instance_t * this_uart,
\r
563 mss_uart_loopback_t loopback
\r
566 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
\r
567 ASSERT(MSS_UART_INVALID_LOOPBACK > loopback);
\r
569 if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) ||
\r
570 (MSS_UART_INVALID_LOOPBACK > loopback))
\r
574 case MSS_UART_LOCAL_LOOPBACK_OFF:
\r
575 /* Disable local loopback */
\r
576 clear_bit_reg8(&this_uart->hw_reg->MCR,LOOP);
\r
579 case MSS_UART_LOCAL_LOOPBACK_ON:
\r
580 /* Enable local loopback */
\r
581 set_bit_reg8(&this_uart->hw_reg->MCR,LOOP);
\r
584 case MSS_UART_REMOTE_LOOPBACK_OFF:
\r
585 case MSS_UART_AUTO_ECHO_OFF:
\r
586 /* Disable remote loopback & automatic echo*/
\r
587 this_uart->hw_reg->MCR &= ~RLOOP_MASK;
\r
590 case MSS_UART_REMOTE_LOOPBACK_ON:
\r
591 /* Enable remote loopback */
\r
592 this_uart->hw_reg->MCR |= (1u << RLOOP);
\r
595 case MSS_UART_AUTO_ECHO_ON:
\r
596 /* Enable automatic echo */
\r
597 this_uart->hw_reg->MCR |= (1u << ECHO);
\r
600 case MSS_UART_INVALID_LOOPBACK:
\r
601 /* Fall through to default. */
\r
609 /***************************************************************************//**
\r
610 * UART0 interrupt service routine.
\r
611 * UART0_IRQHandler is included within the Cortex-M3 vector table as part of the
\r
614 #if defined(__GNUC__)
\r
615 __attribute__((__interrupt__)) void UART0_IRQHandler(void)
\r
617 void UART0_IRQHandler(void)
\r
620 MSS_UART_isr(&g_mss_uart0);
\r
623 /***************************************************************************//**
\r
624 * UART1 interrupt service routine.
\r
625 * UART2_IRQHandler is included within the Cortex-M3 vector table as part of the
\r
628 #if defined(__GNUC__)
\r
629 __attribute__((__interrupt__)) void UART1_IRQHandler(void)
\r
631 void UART1_IRQHandler(void)
\r
634 MSS_UART_isr(&g_mss_uart1);
\r
637 /***************************************************************************//**
\r
638 * See mss_uart.h for details of how to use this function.
\r
641 MSS_UART_set_rxstatus_handler
\r
643 mss_uart_instance_t * this_uart,
\r
644 mss_uart_irq_handler_t handler
\r
647 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
\r
648 ASSERT(handler != INVALID_IRQ_HANDLER);
\r
650 if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&
\r
651 (handler != INVALID_IRQ_HANDLER))
\r
653 this_uart->linests_handler = handler;
\r
655 /* Clear any previously pended interrupts */
\r
656 NVIC_ClearPendingIRQ(this_uart->irqn);
\r
658 /* Enable receiver line status interrupt. */
\r
659 set_bit_reg8(&this_uart->hw_reg->IER,ELSI);
\r
661 /* Enable UART instance interrupt in Cortex-M3 NVIC. */
\r
662 NVIC_EnableIRQ(this_uart->irqn);
\r
666 /***************************************************************************//**
\r
667 * See mss_uart.h for details of how to use this function.
\r
670 MSS_UART_set_tx_handler
\r
672 mss_uart_instance_t * this_uart,
\r
673 mss_uart_irq_handler_t handler
\r
676 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
\r
677 ASSERT(handler != INVALID_IRQ_HANDLER);
\r
679 if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&
\r
680 (handler != INVALID_IRQ_HANDLER))
\r
682 this_uart->tx_handler = handler;
\r
684 /* Make TX buffer info invalid */
\r
685 this_uart->tx_buffer = (const uint8_t *)0;
\r
686 this_uart->tx_buff_size = 0u;
\r
688 /* Clear any previously pended interrupts */
\r
689 NVIC_ClearPendingIRQ(this_uart->irqn);
\r
691 /* Enable transmitter holding register Empty interrupt. */
\r
692 set_bit_reg8(&this_uart->hw_reg->IER,ETBEI);
\r
694 /* Enable UART instance interrupt in Cortex-M3 NVIC. */
\r
695 NVIC_EnableIRQ(this_uart->irqn);
\r
699 /***************************************************************************//**
\r
700 * See mss_uart.h for details of how to use this function.
\r
703 MSS_UART_set_modemstatus_handler
\r
705 mss_uart_instance_t * this_uart,
\r
706 mss_uart_irq_handler_t handler
\r
709 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
\r
710 ASSERT(handler != INVALID_IRQ_HANDLER);
\r
712 if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&
\r
713 (handler != INVALID_IRQ_HANDLER))
\r
715 this_uart->modemsts_handler = handler;
\r
717 /* Clear any previously pended interrupts */
\r
718 NVIC_ClearPendingIRQ(this_uart->irqn);
\r
720 /* Enable modem status interrupt. */
\r
721 set_bit_reg8(&this_uart->hw_reg->IER,EDSSI);
\r
723 /* Enable UART instance interrupt in Cortex-M3 NVIC. */
\r
724 NVIC_EnableIRQ(this_uart->irqn);
\r
728 /***************************************************************************//**
\r
729 * See mss_uart.h for details of how to use this function.
\r
732 MSS_UART_fill_tx_fifo
\r
734 mss_uart_instance_t * this_uart,
\r
735 const uint8_t * tx_buffer,
\r
739 uint8_t status = 0u;
\r
740 size_t size_sent = 0u;
\r
742 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
\r
743 ASSERT(tx_buffer != ( (uint8_t *)0));
\r
744 ASSERT(tx_size > 0);
\r
746 /* Fill the UART's Tx FIFO until the FIFO is full or the complete input
\r
747 * buffer has been written. */
\r
748 if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&
\r
749 (tx_buffer != ((uint8_t *)0)) &&
\r
752 status = this_uart->hw_reg->LSR;
\r
753 this_uart->status |= status;
\r
755 if(status & MSS_UART_THRE)
\r
757 uint32_t fill_size = TX_FIFO_SIZE;
\r
759 if(tx_size < TX_FIFO_SIZE)
\r
761 fill_size = tx_size;
\r
764 for(size_sent = 0u; size_sent < fill_size; ++size_sent)
\r
767 /* Send next character in the buffer. */
\r
768 this_uart->hw_reg->THR = tx_buffer[size_sent];
\r
775 /***************************************************************************//**
\r
776 * See mss_uart.h for details of how to use this function.
\r
779 MSS_UART_get_rx_status
\r
781 mss_uart_instance_t * this_uart
\r
784 uint8_t status = MSS_UART_INVALID_PARAM;
\r
786 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
\r
788 if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))
\r
791 * Extract UART receive error status.
\r
792 * Bit 1 - Overflow error status
\r
793 * Bit 2 - Parity error status
\r
794 * Bit 3 - Frame error status
\r
795 * Bit 4 - Break interrupt indicator
\r
796 * Bit 7 - FIFO data error status
\r
798 this_uart->status |= (this_uart->hw_reg->LSR);
\r
799 status = (this_uart->status & STATUS_ERROR_MASK);
\r
800 /* Clear the sticky status after reading */
\r
801 this_uart->status = 0u;
\r
806 /***************************************************************************//**
\r
807 * See mss_uart.h for details of how to use this function.
\r
810 MSS_UART_get_modem_status
\r
812 mss_uart_instance_t * this_uart
\r
815 uint8_t status = MSS_UART_INVALID_PARAM;
\r
817 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
\r
819 if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))
\r
822 * Extract UART modem status and place in lower bits of "status".
\r
823 * Bit 0 - Delta Clear to Send Indicator
\r
824 * Bit 1 - Delta Clear to Receive Indicator
\r
825 * Bit 2 - Trailing edge of Ring Indicator detector
\r
826 * Bit 3 - Delta Data Carrier Detect indicator
\r
827 * Bit 4 - Clear To Send
\r
828 * Bit 5 - Data Set Ready
\r
829 * Bit 6 - Ring Indicator
\r
830 * Bit 7 - Data Carrier Detect
\r
832 status = this_uart->hw_reg->MSR;
\r
837 /***************************************************************************//**
\r
838 * MSS_UART_get_tx_status.
\r
839 * See mss_uart.h for details of how to use this function.
\r
842 MSS_UART_get_tx_status
\r
844 mss_uart_instance_t * this_uart
\r
847 uint8_t status = MSS_UART_TX_BUSY;
\r
849 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
\r
851 if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))
\r
853 /* Read the Line Status Register and update the sticky record. */
\r
854 status = this_uart->hw_reg->LSR;
\r
855 this_uart->status |= status;
\r
857 * Extract the transmit status bits from the UART's Line Status Register.
\r
858 * Bit 5 - Transmitter Holding Register/FIFO Empty (THRE) status. (If = 1, TX FIFO is empty)
\r
859 * Bit 6 - Transmitter Empty (TEMT) status. (If = 1, both TX FIFO and shift register are empty)
\r
861 status &= (MSS_UART_THRE | MSS_UART_TEMT);
\r
866 /***************************************************************************//**
\r
867 * See mss_uart.h for details of how to use this function.
\r
872 mss_uart_instance_t * this_uart
\r
875 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
\r
876 if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))
\r
878 /* set break charecter on Tx line */
\r
879 set_bit_reg8(&this_uart->hw_reg->LCR,SB);
\r
883 /***************************************************************************//**
\r
884 * See mss_uart.h for details of how to use this function.
\r
887 MSS_UART_clear_break
\r
889 mss_uart_instance_t * this_uart
\r
892 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
\r
893 if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))
\r
895 /* remove break charecter from Tx line */
\r
896 clear_bit_reg8(&this_uart->hw_reg->LCR,SB);
\r
900 /***************************************************************************//**
\r
901 * See mss_uart.h for details of how to use this function.
\r
904 MSS_UART_set_pidpei_handler
\r
906 mss_uart_instance_t * this_uart,
\r
907 mss_uart_irq_handler_t handler
\r
910 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
\r
911 ASSERT(handler != INVALID_IRQ_HANDLER);
\r
913 if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&
\r
914 (handler != INVALID_IRQ_HANDLER))
\r
916 this_uart->pid_pei_handler = handler;
\r
918 /* Clear any previously pended interrupts */
\r
919 NVIC_ClearPendingIRQ( this_uart->irqn );
\r
921 /* Enable PID parity error interrupt. */
\r
922 set_bit_reg8(&this_uart->hw_reg->IEM,EPID_PEI);
\r
924 /* Enable UART instance interrupt in Cortex-M3 NVIC. */
\r
925 NVIC_EnableIRQ(this_uart->irqn);
\r
929 /***************************************************************************//**
\r
930 * See mss_uart.h for details of how to use this function.
\r
933 MSS_UART_set_linbreak_handler
\r
935 mss_uart_instance_t * this_uart,
\r
936 mss_uart_irq_handler_t handler
\r
939 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
\r
940 ASSERT(handler != INVALID_IRQ_HANDLER);
\r
942 if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&
\r
943 (handler != INVALID_IRQ_HANDLER))
\r
945 this_uart->break_handler = handler;
\r
947 /* Clear any previously pended interrupts */
\r
948 NVIC_ClearPendingIRQ( this_uart->irqn );
\r
950 /* Enable LIN break detection interrupt. */
\r
951 set_bit_reg8(&this_uart->hw_reg->IEM,ELINBI);
\r
953 /* Enable UART instance interrupt in Cortex-M3 NVIC. */
\r
954 NVIC_EnableIRQ(this_uart->irqn);
\r
958 /***************************************************************************//**
\r
959 * See mss_uart.h for details of how to use this function.
\r
962 MSS_UART_set_linsync_handler
\r
964 mss_uart_instance_t * this_uart,
\r
965 mss_uart_irq_handler_t handler
\r
968 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
\r
969 ASSERT(handler != INVALID_IRQ_HANDLER);
\r
971 if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&
\r
972 (handler != INVALID_IRQ_HANDLER))
\r
974 this_uart->sync_handler = handler;
\r
976 /* Clear any previously pended interrupts */
\r
977 NVIC_ClearPendingIRQ( this_uart->irqn );
\r
979 /* Enable LIN sync detection interrupt. */
\r
980 set_bit_reg8(&this_uart->hw_reg->IEM,ELINSI);
\r
982 /* Enable UART instance interrupt in Cortex-M3 NVIC. */
\r
983 NVIC_EnableIRQ(this_uart->irqn);
\r
987 /***************************************************************************//**
\r
988 * See mss_uart.h for details of how to use this function.
\r
991 MSS_UART_set_nack_handler
\r
993 mss_uart_instance_t * this_uart,
\r
994 mss_uart_irq_handler_t handler
\r
997 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
\r
998 ASSERT(handler != INVALID_IRQ_HANDLER);
\r
1000 if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&
\r
1001 (handler != INVALID_IRQ_HANDLER))
\r
1003 this_uart->nack_handler = handler;
\r
1005 /* Clear any previously pended interrupts */
\r
1006 NVIC_ClearPendingIRQ( this_uart->irqn );
\r
1008 /* Enable LIN sync detection interrupt. */
\r
1009 set_bit_reg8(&this_uart->hw_reg->IEM,ENACKI);
\r
1011 /* Enable UART instance interrupt in Cortex-M3 NVIC. */
\r
1012 NVIC_EnableIRQ(this_uart->irqn);
\r
1016 /***************************************************************************//**
\r
1017 * See mss_uart.h for details of how to use this function.
\r
1020 MSS_UART_set_rx_timeout_handler
\r
1022 mss_uart_instance_t * this_uart,
\r
1023 mss_uart_irq_handler_t handler
\r
1026 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
\r
1027 ASSERT(handler != INVALID_IRQ_HANDLER);
\r
1029 if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&
\r
1030 (handler != INVALID_IRQ_HANDLER))
\r
1032 this_uart->rto_handler = handler;
\r
1034 /* Clear any previously pended interrupts */
\r
1035 NVIC_ClearPendingIRQ( this_uart->irqn );
\r
1037 /* Enable receiver timeout interrupt. */
\r
1038 set_bit_reg8(&this_uart->hw_reg->IEM,ERTOI);
\r
1040 /* Enable UART instance interrupt in Cortex-M3 NVIC. */
\r
1041 NVIC_EnableIRQ(this_uart->irqn);
\r
1045 /***************************************************************************//**
\r
1046 * See mss_uart.h for details of how to use this function.
\r
1049 MSS_UART_enable_half_duplex
\r
1051 mss_uart_instance_t * this_uart
\r
1054 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
\r
1055 if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))
\r
1057 /* enable single wire half-duplex mode */
\r
1058 set_bit_reg8(&this_uart->hw_reg->MM2,ESWM);
\r
1062 /***************************************************************************//**
\r
1063 * See mss_uart.h for details of how to use this function.
\r
1066 MSS_UART_disable_half_duplex
\r
1068 mss_uart_instance_t * this_uart
\r
1071 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
\r
1072 if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))
\r
1074 /* enable single wire half-duplex mode */
\r
1075 clear_bit_reg8(&this_uart->hw_reg->MM2,ESWM);
\r
1079 /***************************************************************************//**
\r
1080 * See mss_uart.h for details of how to use this function.
\r
1083 MSS_UART_set_rx_endian
\r
1085 mss_uart_instance_t * this_uart,
\r
1086 mss_uart_endian_t endian
\r
1089 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
\r
1090 ASSERT(MSS_UART_INVALID_ENDIAN > endian);
\r
1092 if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&
\r
1093 (MSS_UART_INVALID_ENDIAN > endian))
\r
1095 /* Configure MSB first / LSB first for receiver */
\r
1096 ((MSS_UART_LITTLEEND == endian) ? (clear_bit_reg8(&this_uart->hw_reg->MM1,E_MSB_RX)) :
\r
1097 (set_bit_reg8(&this_uart->hw_reg->MM1,E_MSB_RX)));
\r
1101 /***************************************************************************//**
\r
1102 * See mss_uart.h for details of how to use this function.
\r
1105 MSS_UART_set_tx_endian
\r
1107 mss_uart_instance_t * this_uart,
\r
1108 mss_uart_endian_t endian
\r
1111 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
\r
1112 ASSERT(MSS_UART_INVALID_ENDIAN > endian);
\r
1114 if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&
\r
1115 (MSS_UART_INVALID_ENDIAN > endian))
\r
1117 /* Configure MSB first / LSB first for transmitter */
\r
1118 ((MSS_UART_LITTLEEND == endian) ? (clear_bit_reg8(&this_uart->hw_reg->MM1,E_MSB_TX)) :
\r
1119 (set_bit_reg8(&this_uart->hw_reg->MM1,E_MSB_TX)) ) ;
\r
1123 /***************************************************************************//**
\r
1124 * See mss_uart.h for details of how to use this function.
\r
1127 MSS_UART_set_filter_length
\r
1129 mss_uart_instance_t * this_uart,
\r
1130 mss_uart_filter_length_t length
\r
1133 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
\r
1134 ASSERT(MSS_UART_INVALID_FILTER_LENGTH > length);
\r
1136 if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&
\r
1137 (MSS_UART_INVALID_FILTER_LENGTH > length))
\r
1139 /* Configure glitch filter length */
\r
1140 this_uart->hw_reg->GFR = (uint8_t)length;
\r
1144 /***************************************************************************//**
\r
1145 * See mss_uart.h for details of how to use this function.
\r
1148 MSS_UART_enable_afm
\r
1150 mss_uart_instance_t * this_uart
\r
1153 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
\r
1155 if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))
\r
1157 /* Disable RX FIFO till address flag with correct address is received */
\r
1158 set_bit_reg8(&this_uart->hw_reg->MM2,EAFM);
\r
1162 /***************************************************************************//**
\r
1163 * See mss_uart.h for details of how to use this function.
\r
1166 MSS_UART_disable_afm
\r
1168 mss_uart_instance_t * this_uart
\r
1171 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
\r
1173 if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))
\r
1175 /* Enable RX FIFO irrespective of address flag and
\r
1176 correct address is received */
\r
1177 clear_bit_reg8(&this_uart->hw_reg->MM2,EAFM);
\r
1181 /***************************************************************************//**
\r
1182 * See mss_uart.h for details of how to use this function.
\r
1185 MSS_UART_enable_afclear
\r
1187 mss_uart_instance_t * this_uart
\r
1190 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
\r
1192 if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))
\r
1194 /* Enable address flag clearing */
\r
1195 /* Disable RX FIFO till another address flag with
\r
1196 correct address is received */
\r
1197 set_bit_reg8(&this_uart->hw_reg->MM2,EAFC);
\r
1201 /***************************************************************************//**
\r
1202 * See mss_uart.h for details of how to use this function.
\r
1205 MSS_UART_disable_afclear
\r
1207 mss_uart_instance_t * this_uart
\r
1210 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
\r
1212 if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))
\r
1214 /* Disable address flag clearing */
\r
1215 clear_bit_reg8(&this_uart->hw_reg->MM2,EAFC);
\r
1219 /***************************************************************************//**
\r
1220 * See mss_uart.h for details of how to use this function.
\r
1223 MSS_UART_enable_rx_timeout
\r
1225 mss_uart_instance_t * this_uart,
\r
1229 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
\r
1231 if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))
\r
1233 /* Load the receive timeout value */
\r
1234 this_uart->hw_reg->RTO = timeout;
\r
1235 /*Enable receiver time-out */
\r
1236 set_bit_reg8(&this_uart->hw_reg->MM0,ERTO);
\r
1240 /***************************************************************************//**
\r
1241 * See mss_uart.h for details of how to use this function.
\r
1244 MSS_UART_disable_rx_timeout
\r
1246 mss_uart_instance_t * this_uart
\r
1249 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
\r
1251 if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))
\r
1253 /*Disable receiver time-out */
\r
1254 clear_bit_reg8(&this_uart->hw_reg->MM0,ERTO);
\r
1258 /***************************************************************************//**
\r
1259 * See mss_uart.h for details of how to use this function.
\r
1262 MSS_UART_enable_tx_time_guard
\r
1264 mss_uart_instance_t * this_uart,
\r
1268 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
\r
1270 if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))
\r
1272 /* Load the transmitter time guard value */
\r
1273 this_uart->hw_reg->TTG = timeguard;
\r
1274 /*Enable transmitter time guard */
\r
1275 set_bit_reg8(&this_uart->hw_reg->MM0,ETTG);
\r
1279 /***************************************************************************//**
\r
1280 * See mss_uart.h for details of how to use this function.
\r
1283 MSS_UART_disable_tx_time_guard
\r
1285 mss_uart_instance_t * this_uart
\r
1288 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
\r
1290 if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))
\r
1292 /*Disable transmitter time guard */
\r
1293 clear_bit_reg8(&this_uart->hw_reg->MM0,ETTG);
\r
1297 /***************************************************************************//**
\r
1298 * See mss_uart.h for details of how to use this function.
\r
1301 MSS_UART_set_address
\r
1303 mss_uart_instance_t * this_uart,
\r
1307 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
\r
1309 if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))
\r
1311 this_uart->hw_reg->ADR = address;
\r
1315 /***************************************************************************//**
\r
1316 * See mss_uart.h for details of how to use this function.
\r
1319 MSS_UART_set_ready_mode
\r
1321 mss_uart_instance_t * this_uart,
\r
1322 mss_uart_ready_mode_t mode
\r
1325 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
\r
1326 ASSERT(MSS_UART_INVALID_READY_MODE > mode);
\r
1328 if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&
\r
1329 (MSS_UART_INVALID_READY_MODE > mode ) )
\r
1331 /* Configure mode 0 or mode 1 for TXRDY and RXRDY */
\r
1332 ((MSS_UART_READY_MODE0 == mode) ? clear_bit_reg8(&this_uart->hw_reg->FCR,RDYMODE) :
\r
1333 set_bit_reg8(&this_uart->hw_reg->FCR,RDYMODE) );
\r
1337 /***************************************************************************//**
\r
1338 * Configure baud divisors using fractional baud rate if possible.
\r
1341 config_baud_divisors
\r
1343 mss_uart_instance_t * this_uart,
\r
1344 uint32_t baudrate
\r
1347 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
\r
1349 if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))
\r
1351 uint32_t baud_value;
\r
1352 uint32_t baud_value_by_64;
\r
1353 uint32_t baud_value_by_128;
\r
1354 uint32_t fractional_baud_value;
\r
1355 uint32_t pclk_freq;
\r
1357 this_uart->baudrate = baudrate;
\r
1359 /* Force the value of the CMSIS global variables holding the various system
\r
1360 * clock frequencies to be updated. */
\r
1361 SystemCoreClockUpdate();
\r
1362 if(this_uart == &g_mss_uart0)
\r
1364 pclk_freq = g_FrequencyPCLK0;
\r
1368 pclk_freq = g_FrequencyPCLK1;
\r
1372 * Compute baud value based on requested baud rate and PCLK frequency.
\r
1373 * The baud value is computed using the following equation:
\r
1374 * baud_value = PCLK_Frequency / (baud_rate * 16)
\r
1376 baud_value_by_128 = (8u * pclk_freq) / baudrate;
\r
1377 baud_value_by_64 = baud_value_by_128 / 2u;
\r
1378 baud_value = baud_value_by_64 / 64u;
\r
1379 fractional_baud_value = baud_value_by_64 - (baud_value * 64u);
\r
1380 fractional_baud_value += (baud_value_by_128 - (baud_value * 128u)) - (fractional_baud_value * 2u);
\r
1382 /* Assert if integer baud value fits in 16-bit. */
\r
1383 ASSERT(baud_value <= UINT16_MAX);
\r
1385 if(baud_value <= (uint32_t)UINT16_MAX)
\r
1387 if(baud_value > 1u)
\r
1390 * Use Frational baud rate divisors
\r
1392 /* set divisor latch */
\r
1393 set_bit_reg8(&this_uart->hw_reg->LCR,DLAB);
\r
1395 /* msb of baud value */
\r
1396 this_uart->hw_reg->DMR = (uint8_t)(baud_value >> 8);
\r
1397 /* lsb of baud value */
\r
1398 this_uart->hw_reg->DLR = (uint8_t)baud_value;
\r
1400 /* reset divisor latch */
\r
1401 clear_bit_reg8(&this_uart->hw_reg->LCR,DLAB);
\r
1403 /* Enable Fractional baud rate */
\r
1404 set_bit_reg8(&this_uart->hw_reg->MM0,EFBR);
\r
1406 /* Load the fractional baud rate register */
\r
1407 ASSERT(fractional_baud_value <= (uint32_t)UINT8_MAX);
\r
1408 this_uart->hw_reg->DFR = (uint8_t)fractional_baud_value;
\r
1413 * Do NOT use Frational baud rate divisors.
\r
1415 /* set divisor latch */
\r
1416 set_bit_reg8(&this_uart->hw_reg->LCR,DLAB);
\r
1418 /* msb of baud value */
\r
1419 this_uart->hw_reg->DMR = (uint8_t)(baud_value >> 8u);
\r
1420 /* lsb of baud value */
\r
1421 this_uart->hw_reg->DLR = (uint8_t)baud_value;
\r
1423 /* reset divisor latch */
\r
1424 clear_bit_reg8(&this_uart->hw_reg->LCR,DLAB);
\r
1426 /* Disable Fractional baud rate */
\r
1427 clear_bit_reg8(&this_uart->hw_reg->MM0,EFBR);
\r
1433 /***************************************************************************//**
\r
1434 * See mss_uart.h for details of how to use this function.
\r
1437 MSS_UART_set_usart_mode
\r
1439 mss_uart_instance_t * this_uart,
\r
1440 mss_uart_usart_mode_t mode
\r
1443 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
\r
1444 ASSERT(MSS_UART_INVALID_SYNC_MODE > mode);
\r
1446 if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&
\r
1447 (MSS_UART_INVALID_SYNC_MODE > mode))
\r
1449 /* Nothing to do for the baudrate: operates at PCLK / 2 + glitch filter length */
\r
1450 /* Clear the ESYN bits 2:0 */
\r
1451 this_uart->hw_reg->MM0 &= ~SYNC_ASYNC_MODE_MASK;
\r
1452 this_uart->hw_reg->MM0 |= (uint8_t)mode;
\r
1456 /*******************************************************************************
\r
1458 *******************************************************************************/
\r
1459 /*******************************************************************************
\r
1460 * Global initialization for all modes
\r
1462 static void global_init
\r
1464 mss_uart_instance_t * this_uart,
\r
1465 uint32_t baud_rate,
\r
1466 uint8_t line_config
\r
1469 /* The driver expects g_mss_uart0 and g_mss_uart1 to be the only
\r
1470 * mss_uart_instance_t instances used to identify UART0 and UART1. */
\r
1471 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
\r
1473 if(this_uart == &g_mss_uart0)
\r
1475 this_uart->hw_reg = UART0;
\r
1476 this_uart->irqn = UART0_IRQn;
\r
1478 SYSREG->SOFT_RST_CR |= SYSREG_MMUART0_SOFTRESET_MASK;
\r
1479 /* Clear any previously pended UART0 interrupt */
\r
1480 NVIC_ClearPendingIRQ(UART0_IRQn);
\r
1481 /* Take UART0 out of reset. */
\r
1482 SYSREG->SOFT_RST_CR &= ~SYSREG_MMUART0_SOFTRESET_MASK;
\r
1486 this_uart->hw_reg = UART1;
\r
1487 this_uart->irqn = UART1_IRQn;
\r
1489 SYSREG->SOFT_RST_CR |= SYSREG_MMUART1_SOFTRESET_MASK;
\r
1490 /* Clear any previously pended UART1 interrupt */
\r
1491 NVIC_ClearPendingIRQ(UART1_IRQn);
\r
1492 /* Take UART1 out of reset. */
\r
1493 SYSREG->SOFT_RST_CR &= ~SYSREG_MMUART1_SOFTRESET_MASK;
\r
1496 /* disable interrupts */
\r
1497 this_uart->hw_reg->IER = 0u;
\r
1499 /* FIFO configuration */
\r
1500 this_uart->hw_reg->FCR = (uint8_t)MSS_UART_FIFO_SINGLE_BYTE;
\r
1501 /* clear receiver FIFO */
\r
1502 set_bit_reg8(&this_uart->hw_reg->FCR,CLEAR_RX_FIFO);
\r
1503 /* clear transmitter FIFO */
\r
1504 set_bit_reg8(&this_uart->hw_reg->FCR,CLEAR_TX_FIFO);
\r
1506 /* set default READY mode : Mode 0*/
\r
1507 /* enable RXRDYN and TXRDYN pins. The earlier FCR write to set the TX FIFO
\r
1508 * trigger level inadvertently disabled the FCR_RXRDY_TXRDYN_EN bit. */
\r
1509 set_bit_reg8(&this_uart->hw_reg->FCR,RXRDY_TXRDYN_EN);
\r
1511 /* disable loopback : local * remote */
\r
1512 clear_bit_reg8(&this_uart->hw_reg->MCR,LOOP);
\r
1513 clear_bit_reg8(&this_uart->hw_reg->MCR,RLOOP);
\r
1515 /* set default TX endian */
\r
1516 clear_bit_reg8(&this_uart->hw_reg->MM1,E_MSB_TX);
\r
1517 /* set default RX endian */
\r
1518 clear_bit_reg8(&this_uart->hw_reg->MM1,E_MSB_RX);
\r
1520 /* default AFM : disabled */
\r
1521 clear_bit_reg8(&this_uart->hw_reg->MM2,EAFM);
\r
1523 /* disable TX time gaurd */
\r
1524 clear_bit_reg8(&this_uart->hw_reg->MM0,ETTG);
\r
1526 /* set default RX timeout */
\r
1527 clear_bit_reg8(&this_uart->hw_reg->MM0,ERTO);
\r
1529 /* disable fractional baud-rate */
\r
1530 clear_bit_reg8(&this_uart->hw_reg->MM0,EFBR);
\r
1532 /* disable single wire mode */
\r
1533 clear_bit_reg8(&this_uart->hw_reg->MM2,ESWM);
\r
1535 /* set filter to minimum value */
\r
1536 this_uart->hw_reg->GFR = 0u;
\r
1537 /* set default TX time gaurd */
\r
1538 this_uart->hw_reg->TTG = 0u;
\r
1539 /* set default RX timeout */
\r
1540 this_uart->hw_reg->RTO = 0u;
\r
1543 * Configure baud rate divisors. This uses the frational baud rate divisor
\r
1544 * where possible to provide the most accurate baud rat possible.
\r
1546 config_baud_divisors(this_uart, baud_rate);
\r
1548 /* set the line control register (bit length, stop bits, parity) */
\r
1549 this_uart->hw_reg->LCR = line_config;
\r
1551 /* Instance setup */
\r
1552 this_uart->baudrate = baud_rate;
\r
1553 this_uart->lineconfig = line_config;
\r
1554 this_uart->tx_buff_size = TX_COMPLETE;
\r
1555 this_uart->tx_buffer = (const uint8_t *)0;
\r
1556 this_uart->tx_idx = 0u;
\r
1558 /* Default handlers for MSS UART interrupts */
\r
1559 this_uart->rx_handler = NULL_HANDLER;
\r
1560 this_uart->tx_handler = NULL_HANDLER;
\r
1561 this_uart->linests_handler = NULL_HANDLER;
\r
1562 this_uart->modemsts_handler = NULL_HANDLER;
\r
1563 this_uart->rto_handler = NULL_HANDLER;
\r
1564 this_uart->nack_handler = NULL_HANDLER;
\r
1565 this_uart->pid_pei_handler = NULL_HANDLER;
\r
1566 this_uart->break_handler = NULL_HANDLER;
\r
1567 this_uart->sync_handler = NULL_HANDLER;
\r
1569 /* Initialize the sticky status */
\r
1570 this_uart->status = 0u;
\r
1573 /***************************************************************************//**
\r
1574 * Interrupt service routine triggered by any MSS UART interrupt. This routine
\r
1575 * will call the handler function appropriate to the interrupt from the
\r
1576 * handlers previously registered with the driver through calls to the
\r
1577 * MSS_UART_set_*_handler() functions, or it will call the default_tx_handler()
\r
1578 * function in response to transmit interrupts if MSS_UART_irq_tx() is used to
\r
1584 mss_uart_instance_t * this_uart
\r
1589 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
\r
1591 if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))
\r
1593 iirf = this_uart->hw_reg->IIR & IIRF_MASK;
\r
1597 case IIRF_MODEM_STATUS: /* Modem status interrupt */
\r
1599 ASSERT(NULL_HANDLER != this_uart->modemsts_handler);
\r
1600 if(NULL_HANDLER != this_uart->modemsts_handler)
\r
1602 (*(this_uart->modemsts_handler))(this_uart);
\r
1607 case IIRF_THRE: /* Transmitter Holding Register Empty */
\r
1609 ASSERT(NULL_HANDLER != this_uart->tx_handler);
\r
1610 if(NULL_HANDLER != this_uart->tx_handler)
\r
1612 (*(this_uart->tx_handler))(this_uart);
\r
1617 case IIRF_RX_DATA: /* Received Data Available */
\r
1618 case IIRF_DATA_TIMEOUT: /* Received Data Timed-out */
\r
1620 ASSERT(NULL_HANDLER != this_uart->rx_handler);
\r
1621 if(NULL_HANDLER != this_uart->rx_handler)
\r
1623 (*(this_uart->rx_handler))(this_uart);
\r
1628 case IIRF_RX_LINE_STATUS: /* Line Status Interrupt */
\r
1630 ASSERT(NULL_HANDLER != this_uart->linests_handler);
\r
1631 if(NULL_HANDLER != this_uart->linests_handler)
\r
1633 (*(this_uart->linests_handler))(this_uart);
\r
1640 /* Identify multimode interrupts and handle */
\r
1642 /* Receiver time-out interrupt */
\r
1643 if(read_bit_reg8(&this_uart->hw_reg->IIM,ERTOI))
\r
1645 ASSERT(NULL_HANDLER != this_uart->rto_handler);
\r
1646 if(NULL_HANDLER != this_uart->rto_handler)
\r
1648 (*(this_uart->rto_handler))(this_uart);
\r
1651 /* NACK interrupt */
\r
1652 if(read_bit_reg8(&this_uart->hw_reg->IIM,ENACKI))
\r
1654 ASSERT(NULL_HANDLER != this_uart->nack_handler);
\r
1655 if(NULL_HANDLER != this_uart->nack_handler)
\r
1657 (*(this_uart->nack_handler))(this_uart);
\r
1661 /* PID parity error interrupt */
\r
1662 if(read_bit_reg8(&this_uart->hw_reg->IIM,EPID_PEI))
\r
1664 ASSERT(NULL_HANDLER != this_uart->pid_pei_handler);
\r
1665 if(NULL_HANDLER != this_uart->pid_pei_handler)
\r
1667 (*(this_uart->pid_pei_handler))(this_uart);
\r
1671 /* LIN break detection interrupt */
\r
1672 if(read_bit_reg8(&this_uart->hw_reg->IIM,ELINBI))
\r
1674 ASSERT(NULL_HANDLER != this_uart->break_handler);
\r
1675 if(NULL_HANDLER != this_uart->break_handler)
\r
1677 (*(this_uart->break_handler))(this_uart);
\r
1681 /* LIN Sync detection interrupt */
\r
1682 if(read_bit_reg8(&this_uart->hw_reg->IIM,ELINSI))
\r
1684 ASSERT(NULL_HANDLER != this_uart->sync_handler);
\r
1685 if(NULL_HANDLER != this_uart->sync_handler)
\r
1687 (*(this_uart->sync_handler))(this_uart);
\r
1695 ASSERT(INVALID_INTERRUPT);
\r
1702 /***************************************************************************//**
\r
1703 * See mss_uart.h for details of how to use this function.
\r
1706 default_tx_handler
\r
1708 mss_uart_instance_t * this_uart
\r
1713 ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
\r
1714 ASSERT(( (uint8_t *)0 ) != this_uart->tx_buffer);
\r
1715 ASSERT(0u < this_uart->tx_buff_size);
\r
1717 if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&
\r
1718 (((uint8_t *)0 ) != this_uart->tx_buffer) &&
\r
1719 (0u < this_uart->tx_buff_size))
\r
1721 /* Read the Line Status Register and update the sticky record. */
\r
1722 status = this_uart->hw_reg->LSR;
\r
1723 this_uart->status |= status;
\r
1726 * This function should only be called as a result of a THRE interrupt.
\r
1727 * Verify that this is true before proceeding to transmit data.
\r
1729 if(status & MSS_UART_THRE)
\r
1732 uint32_t fill_size = TX_FIFO_SIZE;
\r
1733 uint32_t tx_remain = this_uart->tx_buff_size - this_uart->tx_idx;
\r
1735 /* Calculate the number of bytes to transmit. */
\r
1736 if(tx_remain < TX_FIFO_SIZE)
\r
1738 fill_size = tx_remain;
\r
1741 /* Fill the TX FIFO with the calculated the number of bytes. */
\r
1742 for(i = 0u; i < fill_size; ++i)
\r
1744 /* Send next character in the buffer. */
\r
1745 this_uart->hw_reg->THR = this_uart->tx_buffer[this_uart->tx_idx];
\r
1746 ++this_uart->tx_idx;
\r
1750 /* Flag Tx as complete if all data has been pushed into the Tx FIFO. */
\r
1751 if(this_uart->tx_idx == this_uart->tx_buff_size)
\r
1753 this_uart->tx_buff_size = TX_COMPLETE;
\r
1754 /* disables TX interrupt */
\r
1755 clear_bit_reg8(&this_uart->hw_reg->IER,ETBEI);
\r
1760 #ifdef __cplusplus
\r