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