]> git.donarmstrong.com Git - qmk_firmware.git/blob - tool/mbed/mbed-sdk/libraries/mbed/targets/hal/TARGET_Maxim/TARGET_MAX32610/serial_api.c
Squashed 'tmk_core/' changes from 7967731..b9e0ea0
[qmk_firmware.git] / tool / mbed / mbed-sdk / libraries / mbed / targets / hal / TARGET_Maxim / TARGET_MAX32610 / serial_api.c
1 /*******************************************************************************
2  * Copyright (C) 2015 Maxim Integrated Products, Inc., All Rights Reserved.
3  *
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:
10  *
11  * The above copyright notice and this permission notice shall be included
12  * in all copies or substantial portions of the Software.
13  *
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.
21  *
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.
25  *
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
30  * ownership rights.
31  *******************************************************************************
32  */
33
34 #include <string.h>
35 #include "mbed_assert.h"
36 #include "cmsis.h"
37 #include "serial_api.h"
38 #include "uart_regs.h"
39 #include "PeripheralPins.h"
40
41 #define UART_NUM 2
42 #define DEFAULT_BAUD 9600
43 #define DEFAULT_STOP 1
44 #define DEFAULT_PARITY ParityNone
45
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)
49
50 // Variables for managing the stdio UART
51 int stdio_uart_inited;
52 serial_t stdio_uart;
53
54 // Variables for interrupt driven
55 static uart_irq_handler irq_handler;
56 static uint32_t serial_irq_ids[UART_NUM];
57
58 //******************************************************************************
59 void serial_init(serial_t *obj, PinName tx, PinName rx)
60 {
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);
65
66     // Make sure that both pins are pointing to the same uart
67     MBED_ASSERT(uart != (UARTName)NC);
68
69     // Set the obj pointer to the proper uart
70     obj->uart = (mxc_uart_regs_t*)uart;
71
72     // Set the uart index
73     obj->index = MXC_UART_BASE_TO_INSTANCE(obj->uart);
74
75     // Configure the pins
76     pinmap_pinout(tx, PinMap_UART_TX);
77     pinmap_pinout(rx, PinMap_UART_RX);
78
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);
81
82     // Disable interrupts
83     obj->uart->inten = 0;
84     obj->uart->intfl = 0;
85
86     // Configure to default settings
87     serial_baud(obj, DEFAULT_BAUD);
88     serial_format(obj, 8, ParityNone, 1);
89
90     // Manage stdio UART
91     if(uart == STDIO_UART) {
92         stdio_uart_inited = 1;
93         memcpy(&stdio_uart, obj, sizeof(serial_t));
94     }
95 }
96
97 //******************************************************************************
98 void serial_baud(serial_t *obj, int baudrate)
99 {
100     uint32_t idiv = 0, ddiv = 0, div = 0;
101
102     // Calculate the integer and decimal portions
103     div = SystemCoreClock / ((baudrate / 100) * 128);
104     idiv = (div / 100);
105     ddiv = (div - idiv * 100) * 128 / 100;
106
107     obj->uart->baud_int = idiv;
108     obj->uart->baud_div_128 = ddiv;
109
110     // Enable the baud clock
111     obj->uart->ctrl |= MXC_F_UART_CTRL_BAUD_CLK_EN;
112 }
113
114 //******************************************************************************
115 void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_bits)
116 {
117
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));
124
125     // Adjust the stop and data bits
126     stop_bits -= 1;
127     data_bits -= 5;
128
129     // Adjust the parity setting
130     int paren = 0, mode = 0;
131     switch (parity) {
132         case ParityNone:
133             paren = 0;
134             mode = 0;
135             break;
136         case ParityOdd :
137             paren = 1;
138             mode = 0;
139             break;
140         case ParityEven:
141             paren = 1;
142             mode = 1;
143             break;
144         case ParityForced1:
145             // Hardware does not support forced parity
146             MBED_ASSERT(0);
147             break;
148         case ParityForced0:
149             // Hardware does not support forced parity
150             MBED_ASSERT(0);
151             break;
152         default:
153             paren = 1;
154             mode = 0;
155             break;
156     }
157
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));
162 }
163
164 //******************************************************************************
165 void uart_handler(mxc_uart_regs_t* uart, int id)
166 {
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);
171     }
172
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);
177     }
178 }
179
180 void uart0_handler(void)
181 {
182     uart_handler(MXC_UART0, 0);
183 }
184 void uart1_handler(void)
185 {
186     uart_handler(MXC_UART1, 1);
187 }
188
189 //******************************************************************************
190 void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id)
191 {
192     irq_handler = handler;
193     serial_irq_ids[obj->index] = id;
194 }
195
196 //******************************************************************************
197 void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable)
198 {
199     if(obj->index == 0) {
200         NVIC_SetVector(UART0_IRQn, (uint32_t)uart0_handler);
201         NVIC_EnableIRQ(UART0_IRQn);
202     } else {
203         NVIC_SetVector(UART1_IRQn, (uint32_t)uart1_handler);
204         NVIC_EnableIRQ(UART1_IRQn);
205     }
206
207     if(irq == RxIrq) {
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
212         if(enable) {
213             // Clear pending interrupts
214             obj->uart->intfl = 0;
215             obj->uart->inten |= (MXC_F_UART_INTFL_RX_OVER_THRESHOLD |
216                                  UART_ERRORS);
217         } else {
218             // Clear pending interrupts
219             obj->uart->intfl = 0;
220             obj->uart->inten &= ~(MXC_F_UART_INTFL_RX_OVER_THRESHOLD |
221                                   UART_ERRORS);
222         }
223
224     } else if (irq == TxIrq) {
225         // Enable TX Almost empty Interrupt
226         if(enable) {
227             // Clear pending interrupts
228             obj->uart->intfl = 0;
229             obj->uart->inten |= MXC_F_UART_INTFL_TX_ALMOST_EMPTY;
230         } else {
231             // Clear pending interrupts
232             obj->uart->intfl = 0;
233             obj->uart->inten &= ~MXC_F_UART_INTFL_TX_ALMOST_EMPTY;
234         }
235
236     } else {
237         MBED_ASSERT(0);
238     }
239 }
240
241
242 //******************************************************************************
243 int serial_getc(serial_t *obj)
244 {
245     int c;
246
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;
250
251     // Echo characters for stdio
252     if (obj->uart == (mxc_uart_regs_t*)STDIO_UART) {
253         obj->uart->tx_rx_fifo = c;
254     }
255     
256     return c;
257 }
258
259 //******************************************************************************
260 void serial_putc(serial_t *obj, int c)
261 {
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';
266     }
267
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;
271
272 }
273
274 //******************************************************************************
275 int serial_readable(serial_t *obj)
276 {
277     return (!(obj->uart->status & MXC_F_UART_STATUS_RX_FIFO_EMPTY));
278 }
279
280 //******************************************************************************
281 int serial_writable(serial_t *obj)
282 {
283     return (!(obj->uart->status & MXC_F_UART_STATUS_TX_FIFO_FULL));
284 }
285
286 //******************************************************************************
287 void serial_clear(serial_t *obj)
288 {
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 );
291 }
292
293
294 //******************************************************************************
295 void serial_break_set(serial_t *obj)
296 {
297     // Make sure that nothing is being sent
298     while(obj->uart->status & MXC_F_UART_STATUS_RX_BUSY) {}
299
300     // Disable the clock to pause any transmission
301     obj->uart->ctrl &= ~MXC_F_UART_CTRL_BAUD_CLK_EN ;
302 }
303
304 //******************************************************************************
305 void serial_break_clear(serial_t *obj)
306 {
307     obj->uart->ctrl |= MXC_F_UART_CTRL_BAUD_CLK_EN;
308 }
309
310
311 //******************************************************************************
312 void serial_pinout_tx(PinName tx)
313 {
314     pinmap_pinout(tx, PinMap_UART_TX);
315 }
316
317
318 //******************************************************************************
319 void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, PinName txflow)
320 {
321     if(FlowControlNone == type) {
322         // Disable hardware flow control
323         obj->uart->ctrl &= ~(MXC_F_UART_CTRL_HW_FLOW_CTRL_EN);
324         return;
325     }
326
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);
331
332     if((FlowControlCTS == type) || (FlowControlRTSCTS== type)) {
333         // Make sure pin is in the PinMap
334         MBED_ASSERT(uart_cts != (UARTName)NC);
335
336         // Enable the pin for CTS function
337         pinmap_pinout(txflow, PinMap_UART_CTS);
338     }
339
340     if((FlowControlRTS == type) || (FlowControlRTSCTS== type))  {
341         // Make sure pin is in the PinMap
342         MBED_ASSERT(uart_rts != (UARTName)NC);
343
344         // Enable the pin for RTS function
345         pinmap_pinout(rxflow, PinMap_UART_RTS);
346     }
347
348     if(FlowControlRTSCTS == type){ 
349         // Make sure that the pins are pointing to the same UART
350         MBED_ASSERT(uart != (UARTName)NC);
351     }
352
353     // Enable hardware flow control
354     obj->uart->ctrl |= MXC_F_UART_CTRL_HW_FLOW_CTRL_EN;
355 }