1 /*******************************************************************************
2 * Copyright (C) 2015 Maxim Integrated Products, Inc., All Rights Reserved.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
18 * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
22 * Except as contained in this notice, the name of Maxim Integrated
23 * Products, Inc. shall not be used except as stated in the Maxim Integrated
24 * Products, Inc. Branding Policy.
26 * The mere transfer of this software does not imply any licenses
27 * of trade secrets, proprietary technology, copyrights, patents,
28 * trademarks, maskwork rights, or any other form of intellectual
29 * property whatsoever. Maxim Integrated Products, Inc. retains all
31 *******************************************************************************
35 #include "mbed_assert.h"
37 #include "serial_api.h"
38 #include "uart_regs.h"
39 #include "PeripheralPins.h"
42 #define DEFAULT_BAUD 9600
43 #define DEFAULT_STOP 1
44 #define DEFAULT_PARITY ParityNone
46 #define UART_ERRORS (MXC_F_UART_INTFL_RX_FRAME_ERROR | \
47 MXC_F_UART_INTFL_RX_PARITY_ERROR | \
48 MXC_F_UART_INTFL_RX_OVERRUN)
50 // Variables for managing the stdio UART
51 int stdio_uart_inited
;
54 // Variables for interrupt driven
55 static uart_irq_handler irq_handler
;
56 static uint32_t serial_irq_ids
[UART_NUM
];
58 //******************************************************************************
59 void serial_init(serial_t
*obj
, PinName tx
, PinName rx
)
61 // Determine which uart is associated with each pin
62 UARTName uart_tx
= (UARTName
)pinmap_peripheral(tx
, PinMap_UART_TX
);
63 UARTName uart_rx
= (UARTName
)pinmap_peripheral(rx
, PinMap_UART_RX
);
64 UARTName uart
= (UARTName
)pinmap_merge(uart_tx
, uart_rx
);
66 // Make sure that both pins are pointing to the same uart
67 MBED_ASSERT(uart
!= (UARTName
)NC
);
69 // Set the obj pointer to the proper uart
70 obj
->uart
= (mxc_uart_regs_t
*)uart
;
73 obj
->index
= MXC_UART_BASE_TO_INSTANCE(obj
->uart
);
76 pinmap_pinout(tx
, PinMap_UART_TX
);
77 pinmap_pinout(rx
, PinMap_UART_RX
);
79 // Flush the RX and TX FIFOs, clear the settings
80 obj
->uart
->ctrl
= ( MXC_F_UART_CTRL_TX_FIFO_FLUSH
| MXC_F_UART_CTRL_RX_FIFO_FLUSH
);
86 // Configure to default settings
87 serial_baud(obj
, DEFAULT_BAUD
);
88 serial_format(obj
, 8, ParityNone
, 1);
91 if(uart
== STDIO_UART
) {
92 stdio_uart_inited
= 1;
93 memcpy(&stdio_uart
, obj
, sizeof(serial_t
));
97 //******************************************************************************
98 void serial_baud(serial_t
*obj
, int baudrate
)
100 uint32_t idiv
= 0, ddiv
= 0, div
= 0;
102 // Calculate the integer and decimal portions
103 div
= SystemCoreClock
/ ((baudrate
/ 100) * 128);
105 ddiv
= (div
- idiv
* 100) * 128 / 100;
107 obj
->uart
->baud_int
= idiv
;
108 obj
->uart
->baud_div_128
= ddiv
;
110 // Enable the baud clock
111 obj
->uart
->ctrl
|= MXC_F_UART_CTRL_BAUD_CLK_EN
;
114 //******************************************************************************
115 void serial_format(serial_t
*obj
, int data_bits
, SerialParity parity
, int stop_bits
)
118 // Check the validity of the inputs
119 MBED_ASSERT((data_bits
> 4) && (data_bits
< 9));
120 MBED_ASSERT((parity
== ParityNone
) || (parity
== ParityOdd
) ||
121 (parity
== ParityEven
) || (parity
== ParityForced1
) ||
122 (parity
== ParityForced0
));
123 MBED_ASSERT((stop_bits
== 1) || (stop_bits
== 2));
125 // Adjust the stop and data bits
129 // Adjust the parity setting
130 int paren
= 0, mode
= 0;
145 // Hardware does not support forced parity
149 // Hardware does not support forced parity
158 obj
->uart
->ctrl
|= ((data_bits
<< MXC_F_UART_CTRL_CHAR_LENGTH_POS
) |
159 (stop_bits
<< MXC_F_UART_CTRL_STOP_BIT_MODE_POS
) |
160 (paren
<< MXC_F_UART_CTRL_PARITY_ENABLE_POS
) |
161 (mode
<< MXC_F_UART_CTRL_PARITY_MODE_POS
));
164 //******************************************************************************
165 void uart_handler(mxc_uart_regs_t
* uart
, int id
)
167 // Check for errors or RX Threshold
168 if(uart
->intfl
& (MXC_F_UART_INTFL_RX_OVER_THRESHOLD
| UART_ERRORS
)) {
169 irq_handler(serial_irq_ids
[id
], RxIrq
);
170 uart
->intfl
&= ~(MXC_F_UART_INTFL_RX_OVER_THRESHOLD
| UART_ERRORS
);
173 // Check for TX Threshold
174 if(uart
->intfl
& MXC_F_UART_INTFL_TX_ALMOST_EMPTY
) {
175 irq_handler(serial_irq_ids
[id
], TxIrq
);
176 uart
->intfl
&= ~(MXC_F_UART_INTFL_TX_ALMOST_EMPTY
);
180 void uart0_handler(void)
182 uart_handler(MXC_UART0
, 0);
184 void uart1_handler(void)
186 uart_handler(MXC_UART1
, 1);
189 //******************************************************************************
190 void serial_irq_handler(serial_t
*obj
, uart_irq_handler handler
, uint32_t id
)
192 irq_handler
= handler
;
193 serial_irq_ids
[obj
->index
] = id
;
196 //******************************************************************************
197 void serial_irq_set(serial_t
*obj
, SerialIrq irq
, uint32_t enable
)
199 if(obj
->index
== 0) {
200 NVIC_SetVector(UART0_IRQn
, (uint32_t)uart0_handler
);
201 NVIC_EnableIRQ(UART0_IRQn
);
203 NVIC_SetVector(UART1_IRQn
, (uint32_t)uart1_handler
);
204 NVIC_EnableIRQ(UART1_IRQn
);
208 // Set the RX FIFO Threshold to 1
209 obj
->uart
->ctrl
&= ~MXC_F_UART_CTRL_RX_THRESHOLD
;
210 obj
->uart
->ctrl
|= 0x1;
211 // Enable RX FIFO Threshold Interrupt
213 // Clear pending interrupts
214 obj
->uart
->intfl
= 0;
215 obj
->uart
->inten
|= (MXC_F_UART_INTFL_RX_OVER_THRESHOLD
|
218 // Clear pending interrupts
219 obj
->uart
->intfl
= 0;
220 obj
->uart
->inten
&= ~(MXC_F_UART_INTFL_RX_OVER_THRESHOLD
|
224 } else if (irq
== TxIrq
) {
225 // Enable TX Almost empty Interrupt
227 // Clear pending interrupts
228 obj
->uart
->intfl
= 0;
229 obj
->uart
->inten
|= MXC_F_UART_INTFL_TX_ALMOST_EMPTY
;
231 // Clear pending interrupts
232 obj
->uart
->intfl
= 0;
233 obj
->uart
->inten
&= ~MXC_F_UART_INTFL_TX_ALMOST_EMPTY
;
242 //******************************************************************************
243 int serial_getc(serial_t
*obj
)
247 // Wait for data to be available
248 while(obj
->uart
->status
& MXC_F_UART_STATUS_RX_FIFO_EMPTY
) {}
249 c
= obj
->uart
->tx_rx_fifo
& 0xFF;
251 // Echo characters for stdio
252 if (obj
->uart
== (mxc_uart_regs_t
*)STDIO_UART
) {
253 obj
->uart
->tx_rx_fifo
= c
;
259 //******************************************************************************
260 void serial_putc(serial_t
*obj
, int c
)
262 // Append a carriage return for stdio
263 if ((c
== (int)'\n') && (obj
->uart
== (mxc_uart_regs_t
*)STDIO_UART
)) {
264 while(obj
->uart
->status
& MXC_F_UART_STATUS_TX_FIFO_FULL
) {}
265 obj
->uart
->tx_rx_fifo
= '\r';
268 // Wait for TXFIFO to not be full
269 while(obj
->uart
->status
& MXC_F_UART_STATUS_TX_FIFO_FULL
) {}
270 obj
->uart
->tx_rx_fifo
= c
;
274 //******************************************************************************
275 int serial_readable(serial_t
*obj
)
277 return (!(obj
->uart
->status
& MXC_F_UART_STATUS_RX_FIFO_EMPTY
));
280 //******************************************************************************
281 int serial_writable(serial_t
*obj
)
283 return (!(obj
->uart
->status
& MXC_F_UART_STATUS_TX_FIFO_FULL
));
286 //******************************************************************************
287 void serial_clear(serial_t
*obj
)
289 // Clear the rx and tx fifos
290 obj
->uart
->ctrl
|= (MXC_F_UART_CTRL_TX_FIFO_FLUSH
| MXC_F_UART_CTRL_RX_FIFO_FLUSH
);
294 //******************************************************************************
295 void serial_break_set(serial_t
*obj
)
297 // Make sure that nothing is being sent
298 while(obj
->uart
->status
& MXC_F_UART_STATUS_RX_BUSY
) {}
300 // Disable the clock to pause any transmission
301 obj
->uart
->ctrl
&= ~MXC_F_UART_CTRL_BAUD_CLK_EN
;
304 //******************************************************************************
305 void serial_break_clear(serial_t
*obj
)
307 obj
->uart
->ctrl
|= MXC_F_UART_CTRL_BAUD_CLK_EN
;
311 //******************************************************************************
312 void serial_pinout_tx(PinName tx
)
314 pinmap_pinout(tx
, PinMap_UART_TX
);
318 //******************************************************************************
319 void serial_set_flow_control(serial_t
*obj
, FlowControl type
, PinName rxflow
, PinName txflow
)
321 if(FlowControlNone
== type
) {
322 // Disable hardware flow control
323 obj
->uart
->ctrl
&= ~(MXC_F_UART_CTRL_HW_FLOW_CTRL_EN
);
327 // Check to see if we can use HW flow control
328 UARTName uart_cts
= (UARTName
)pinmap_peripheral(txflow
, PinMap_UART_CTS
);
329 UARTName uart_rts
= (UARTName
)pinmap_peripheral(rxflow
, PinMap_UART_RTS
);
330 UARTName uart
= (UARTName
)pinmap_merge(uart_cts
, uart_rts
);
332 if((FlowControlCTS
== type
) || (FlowControlRTSCTS
== type
)) {
333 // Make sure pin is in the PinMap
334 MBED_ASSERT(uart_cts
!= (UARTName
)NC
);
336 // Enable the pin for CTS function
337 pinmap_pinout(txflow
, PinMap_UART_CTS
);
340 if((FlowControlRTS
== type
) || (FlowControlRTSCTS
== type
)) {
341 // Make sure pin is in the PinMap
342 MBED_ASSERT(uart_rts
!= (UARTName
)NC
);
344 // Enable the pin for RTS function
345 pinmap_pinout(rxflow
, PinMap_UART_RTS
);
348 if(FlowControlRTSCTS
== type
){
349 // Make sure that the pins are pointing to the same UART
350 MBED_ASSERT(uart
!= (UARTName
)NC
);
353 // Enable hardware flow control
354 obj
->uart
->ctrl
|= MXC_F_UART_CTRL_HW_FLOW_CTRL_EN
;