1 /* mbed Microcontroller Library
2 * Copyright (c) 2006-2015 ARM Limited
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 // math.h required for floating point operations for baud rate calculation
17 #include "mbed_assert.h"
22 #include "serial_api.h"
27 #include "scif_iodefine.h"
28 #include "cpg_iodefine.h"
30 /******************************************************************************
32 ******************************************************************************/
33 #define PCLK (66666666) // Define the peripheral clock P1 frequency.
38 static void uart0_tx_irq(void);
39 static void uart1_tx_irq(void);
40 static void uart2_tx_irq(void);
41 static void uart3_tx_irq(void);
42 static void uart4_tx_irq(void);
43 static void uart5_tx_irq(void);
44 static void uart6_tx_irq(void);
45 static void uart7_tx_irq(void);
46 static void uart0_rx_irq(void);
47 static void uart1_rx_irq(void);
48 static void uart2_rx_irq(void);
49 static void uart3_rx_irq(void);
50 static void uart4_rx_irq(void);
51 static void uart5_rx_irq(void);
52 static void uart6_rx_irq(void);
53 static void uart7_rx_irq(void);
56 static const PinMap PinMap_UART_TX
[] = {
75 static const PinMap PinMap_UART_RX
[] = {
94 static const PinMap PinMap_UART_CTS
[] = {
100 static const PinMap PinMap_UART_RTS
[] = {
109 static const struct st_scif
*SCIF
[] = SCIF_ADDRESS_LIST
;
110 static uart_irq_handler irq_handler
;
112 int stdio_uart_inited
= 0;
115 struct serial_global_data_s
{
116 uint32_t serial_irq_id
;
117 gpio_t sw_rts
, sw_cts
;
118 uint8_t count
, rx_irq_set_flow
, rx_irq_set_api
;
121 static struct serial_global_data_s uart_data
[UART_NUM
];
123 static const IRQn_Type irq_set_tbl
[UART_NUM
][IRQ_NUM
] = {
124 {SCIFRXI0_IRQn
, SCIFTXI0_IRQn
},
125 {SCIFRXI1_IRQn
, SCIFTXI1_IRQn
},
126 {SCIFRXI2_IRQn
, SCIFTXI2_IRQn
},
127 {SCIFRXI3_IRQn
, SCIFTXI3_IRQn
},
128 {SCIFRXI4_IRQn
, SCIFTXI4_IRQn
},
129 {SCIFRXI5_IRQn
, SCIFTXI5_IRQn
},
130 {SCIFRXI6_IRQn
, SCIFTXI6_IRQn
},
131 {SCIFRXI7_IRQn
, SCIFTXI7_IRQn
}
134 static const IRQHandler hander_set_tbl
[UART_NUM
][IRQ_NUM
] = {
135 {uart0_rx_irq
, uart0_tx_irq
},
136 {uart1_rx_irq
, uart1_tx_irq
},
137 {uart2_rx_irq
, uart2_tx_irq
},
138 {uart3_rx_irq
, uart3_tx_irq
},
139 {uart4_rx_irq
, uart4_tx_irq
},
140 {uart5_rx_irq
, uart5_tx_irq
},
141 {uart6_rx_irq
, uart6_tx_irq
},
142 {uart7_rx_irq
, uart7_tx_irq
}
145 static __IO
uint16_t *SCSCR_MATCH
[] = {
156 static __IO
uint16_t *SCFSR_MATCH
[] = {
168 void serial_init(serial_t
*obj
, PinName tx
, PinName rx
) {
169 volatile uint8_t dummy
;
170 int is_stdio_uart
= 0;
171 // determine the UART to use
172 uint32_t uart_tx
= pinmap_peripheral(tx
, PinMap_UART_TX
);
173 uint32_t uart_rx
= pinmap_peripheral(rx
, PinMap_UART_RX
);
174 uint32_t uart
= pinmap_merge(uart_tx
, uart_rx
);
176 MBED_ASSERT((int)uart
!= NC
);
178 obj
->uart
= (struct st_scif
*)SCIF
[uart
];
182 CPG
.STBCR4
&= ~(1 << 7);
185 CPG
.STBCR4
&= ~(1 << 6);
188 CPG
.STBCR4
&= ~(1 << 5);
191 CPG
.STBCR4
&= ~(1 << 4);
194 CPG
.STBCR4
&= ~(1 << 3);
197 CPG
.STBCR4
&= ~(1 << 2);
200 CPG
.STBCR4
&= ~(1 << 1);
203 CPG
.STBCR4
&= ~(1 << 0);
208 /* ==== SCIF initial setting ==== */
209 /* ---- Serial control register (SCSCR) setting ---- */
210 /* B'00 : Internal CLK */
211 obj
->uart
->SCSCR
= 0x0000u
; /* SCIF transmitting and receiving operations stop */
213 /* ---- FIFO control register (SCFCR) setting ---- */
214 /* Transmit FIFO reset & Receive FIFO data register reset */
215 obj
->uart
->SCFCR
= 0x0006;
217 /* ---- Serial status register (SCFSR) setting ---- */
218 dummy
= obj
->uart
->SCFSR
;
219 obj
->uart
->SCFSR
= (dummy
& 0xFF6Cu
); /* ER,BRK,DR bit clear */
221 /* ---- Line status register (SCLSR) setting ---- */
223 obj
->uart
->SCLSR
= 0;
225 /* ---- Serial extension mode register (SCEMR) setting ----
226 b7 BGDM - Baud rate generator double-speed mode : Normal mode
227 b0 ABCS - Base clock select in asynchronous mode : Base clock is 16 times the bit rate */
228 obj
->uart
->SCEMR
= 0x0000u
;
230 /* ---- Bit rate register (SCBRR) setting ---- */
231 serial_baud (obj
, 9600);
232 serial_format(obj
, 8, ParityNone
, 1);
234 /* ---- FIFO control register (SCFCR) setting ---- */
235 obj
->uart
->SCFCR
= 0x0030u
;
237 /* ---- Serial port register (SCSPTR) setting ----
238 b1 SPB2IO - Serial port break output : disabled
239 b0 SPB2DT - Serial port break data : High-level */
240 obj
->uart
->SCSPTR
= 0x0003u
; // SPB2IO = 1, SPB2DT = 1
242 /* ---- Line status register (SCLSR) setting ----
243 b0 ORER - Overrun error detect : clear */
245 if (obj
->uart
->SCLSR
& 0x0001) {
246 obj
->uart
->SCLSR
= 0u; // ORER clear
249 // pinout the chosen uart
250 pinmap_pinout(tx
, PinMap_UART_TX
);
251 pinmap_pinout(rx
, PinMap_UART_RX
);
279 uart_data
[obj
->index
].sw_rts
.pin
= NC
;
280 uart_data
[obj
->index
].sw_cts
.pin
= NC
;
282 /* ---- Serial control register (SCSCR) setting ---- */
283 /* Setting the TE and RE bits enables the TxD and RxD pins to be used. */
284 obj
->uart
->SCSCR
= 0x00F0;
286 is_stdio_uart
= (uart
== STDIO_UART
) ? (1) : (0);
289 stdio_uart_inited
= 1;
290 memcpy(&stdio_uart
, obj
, sizeof(serial_t
));
294 void serial_free(serial_t
*obj
) {
295 uart_data
[obj
->index
].serial_irq_id
= 0;
299 // set the baud rate, taking in to account the current SystemFrequency
300 void serial_baud(serial_t
*obj
, int baudrate
) {
303 obj
->uart
->SCSMR
&= ~0x0003;
305 if (baudrate
> 32552) {
306 obj
->uart
->SCEMR
= 0x0081; // BGDM = 1, ABCS = 1
307 DL
= PCLK
/ (8 * baudrate
);
311 obj
->uart
->SCBRR
= (uint8_t)DL
;
312 } else if (baudrate
> 16276) {
313 obj
->uart
->SCEMR
= 0x0080; // BGDM = 1
314 obj
->uart
->SCBRR
= PCLK
/ (16 * baudrate
) - 1;
315 } else if (baudrate
> 8138) {
316 obj
->uart
->SCEMR
= 0x0000;
317 obj
->uart
->SCBRR
= PCLK
/ (32 * baudrate
) - 1;
318 } else if (baudrate
> 4169) {
319 obj
->uart
->SCSMR
|= 0x0001;
320 obj
->uart
->SCEMR
= 0x0080; // BGDM = 1
321 obj
->uart
->SCBRR
= PCLK
/ (64 * baudrate
) - 1;
322 } else if (baudrate
> 2034) {
323 obj
->uart
->SCSMR
|= 0x0001;
324 obj
->uart
->SCEMR
= 0x0000;
325 obj
->uart
->SCBRR
= PCLK
/ (128 * baudrate
) - 1;
326 } else if (baudrate
> 1017) {
327 obj
->uart
->SCSMR
|= 0x0002;
328 obj
->uart
->SCEMR
= 0x0080; // BGDM = 1
329 obj
->uart
->SCBRR
= PCLK
/ (256 * baudrate
) - 1;
330 } else if (baudrate
> 508) {
331 obj
->uart
->SCSMR
|= 0x0002;
332 obj
->uart
->SCEMR
= 0x0000;
333 obj
->uart
->SCBRR
= PCLK
/ (512 * baudrate
) - 1;
334 } else if (baudrate
> 254) {
335 obj
->uart
->SCSMR
|= 0x0003;
336 obj
->uart
->SCEMR
= 0x0080; // BGDM = 1
337 obj
->uart
->SCBRR
= PCLK
/ (1024 * baudrate
) - 1;
338 } else if (baudrate
> 127) {
339 obj
->uart
->SCSMR
|= 0x0003;
340 obj
->uart
->SCEMR
= 0x0000;
341 obj
->uart
->SCBRR
= PCLK
/ (2048 * baudrate
) - 1;
343 obj
->uart
->SCSMR
|= 0x0003;
344 obj
->uart
->SCEMR
= 0x0000;
345 obj
->uart
->SCBRR
= 0xFFu
;
349 void serial_format(serial_t
*obj
, int data_bits
, SerialParity parity
, int stop_bits
) {
353 MBED_ASSERT((stop_bits
== 1) || (stop_bits
== 2)); // 0: 1 stop bits, 1: 2 stop bits
354 MBED_ASSERT((data_bits
> 4) && (data_bits
< 9)); // 5: 5 data bits ... 3: 8 data bits
355 MBED_ASSERT((parity
== ParityNone
) || (parity
== ParityOdd
) || (parity
== ParityEven
) ||
356 (parity
== ParityForced1
) || (parity
== ParityForced0
));
358 stop_bits
= (stop_bits
== 1)? 0:
362 data_bits
= (data_bits
== 8)? 0:
387 obj
->uart
->SCSMR
= data_bits
<< 6
393 /******************************************************************************
394 * INTERRUPTS HANDLING
395 ******************************************************************************/
397 static void uart_tx_irq(IRQn_Type irq_num
, uint32_t index
) {
398 __IO
uint16_t *dmy_rd_scscr
;
399 __IO
uint16_t *dmy_rd_scfsr
;
401 dmy_rd_scscr
= SCSCR_MATCH
[index
];
402 *dmy_rd_scscr
&= 0x007B; // Clear TIE and Write to bit15~8,2 is always 0
403 dmy_rd_scfsr
= SCFSR_MATCH
[index
];
404 *dmy_rd_scfsr
= (*dmy_rd_scfsr
& ~0x0020); // Clear TDFE
406 irq_handler(uart_data
[index
].serial_irq_id
, TxIrq
);
409 static void uart_rx_irq(IRQn_Type irq_num
, uint32_t index
) {
410 __IO
uint16_t *dmy_rd_scscr
;
411 __IO
uint16_t *dmy_rd_scfsr
;
413 dmy_rd_scscr
= SCSCR_MATCH
[index
];
414 *dmy_rd_scscr
&= 0x00B3; // Clear RIE,REIE and Write to bit15~8,2 is always 0
415 dmy_rd_scfsr
= SCFSR_MATCH
[index
];
416 *dmy_rd_scfsr
= (*dmy_rd_scfsr
& ~0x0003); // Clear RDF,DR
418 irq_handler(uart_data
[index
].serial_irq_id
, RxIrq
);
422 static void uart0_tx_irq(void) {
423 uart_tx_irq(SCIFTXI0_IRQn
, 0);
425 static void uart1_tx_irq(void) {
426 uart_tx_irq(SCIFTXI1_IRQn
, 1);
428 static void uart2_tx_irq(void) {
429 uart_tx_irq(SCIFTXI2_IRQn
, 2);
431 static void uart3_tx_irq(void) {
432 uart_tx_irq(SCIFTXI3_IRQn
, 3);
434 static void uart4_tx_irq(void) {
435 uart_tx_irq(SCIFTXI4_IRQn
, 4);
437 static void uart5_tx_irq(void) {
438 uart_tx_irq(SCIFTXI5_IRQn
, 5);
440 static void uart6_tx_irq(void) {
441 uart_tx_irq(SCIFTXI6_IRQn
, 6);
443 static void uart7_tx_irq(void) {
444 uart_tx_irq(SCIFTXI7_IRQn
, 7);
447 static void uart0_rx_irq(void) {
448 uart_rx_irq(SCIFRXI0_IRQn
, 0);
450 static void uart1_rx_irq(void) {
451 uart_rx_irq(SCIFRXI1_IRQn
, 1);
453 static void uart2_rx_irq(void) {
454 uart_rx_irq(SCIFRXI2_IRQn
, 2);
456 static void uart3_rx_irq(void) {
457 uart_rx_irq(SCIFRXI3_IRQn
, 3);
459 static void uart4_rx_irq(void) {
460 uart_rx_irq(SCIFRXI4_IRQn
, 4);
462 static void uart5_rx_irq(void) {
463 uart_rx_irq(SCIFRXI5_IRQn
, 5);
465 static void uart6_rx_irq(void) {
466 uart_rx_irq(SCIFRXI6_IRQn
, 6);
468 static void uart7_rx_irq(void) {
469 uart_rx_irq(SCIFRXI7_IRQn
, 7);
472 void serial_irq_handler(serial_t
*obj
, uart_irq_handler handler
, uint32_t id
) {
473 irq_handler
= handler
;
474 uart_data
[obj
->index
].serial_irq_id
= id
;
477 static void serial_irq_set_internal(serial_t
*obj
, SerialIrq irq
, uint32_t enable
) {
481 IRQn
= irq_set_tbl
[obj
->index
][irq
];
482 handler
= hander_set_tbl
[obj
->index
][irq
];
484 if ((obj
->index
>= 0) && (obj
->index
<= 7)) {
486 InterruptHandlerRegister(IRQn
, (void (*)(uint32_t))handler
);
487 GIC_SetPriority(IRQn
, 5);
490 GIC_DisableIRQ(IRQn
);
495 void serial_irq_set(serial_t
*obj
, SerialIrq irq
, uint32_t enable
) {
497 uart_data
[obj
->index
].rx_irq_set_api
= enable
;
499 serial_irq_set_internal(obj
, irq
, enable
);
502 static void serial_flow_irq_set(serial_t
*obj
, uint32_t enable
) {
503 uart_data
[obj
->index
].rx_irq_set_flow
= enable
;
504 serial_irq_set_internal(obj
, RxIrq
, enable
);
507 /******************************************************************************
509 ******************************************************************************/
510 int serial_getc(serial_t
*obj
) {
515 was_masked
= __disable_irq();
516 if (obj
->uart
->SCFSR
& 0x93) {
517 err_read
= obj
->uart
->SCFSR
;
518 obj
->uart
->SCFSR
= (err_read
& ~0x93);
520 obj
->uart
->SCSCR
|= 0x0040; // Set RIE
525 if (obj
->uart
->SCLSR
& 0x0001) {
526 obj
->uart
->SCLSR
= 0u; // ORER clear
529 while (!serial_readable(obj
));
530 data
= obj
->uart
->SCFRDR
& 0xff;
532 was_masked
= __disable_irq();
533 err_read
= obj
->uart
->SCFSR
;
534 obj
->uart
->SCFSR
= (err_read
& 0xfffD); // Clear RDF
539 if (err_read
& 0x80) {
545 void serial_putc(serial_t
*obj
, int c
) {
549 was_masked
= __disable_irq();
550 obj
->uart
->SCSCR
|= 0x0080; // Set TIE
554 while (!serial_writable(obj
));
555 obj
->uart
->SCFTDR
= c
;
556 was_masked
= __disable_irq();
557 dummy_read
= obj
->uart
->SCFSR
;
558 obj
->uart
->SCFSR
= (dummy_read
& 0xff9f); // Clear TEND/TDFE
562 uart_data
[obj
->index
].count
++;
565 int serial_readable(serial_t
*obj
) {
566 return ((obj
->uart
->SCFSR
& 0x02) != 0); // RDF
569 int serial_writable(serial_t
*obj
) {
570 return ((obj
->uart
->SCFSR
& 0x20) != 0); // TDFE
573 void serial_clear(serial_t
*obj
) {
575 was_masked
= __disable_irq();
577 obj
->uart
->SCFCR
|= 0x06; // TFRST = 1, RFRST = 1
578 obj
->uart
->SCFCR
&= ~0x06; // TFRST = 0, RFRST = 0
579 obj
->uart
->SCFSR
&= ~0x0093u
; // ER, BRK, RDF, DR = 0
586 void serial_pinout_tx(PinName tx
) {
587 pinmap_pinout(tx
, PinMap_UART_TX
);
590 void serial_break_set(serial_t
*obj
) {
592 was_masked
= __disable_irq();
594 obj
->uart
->SCSPTR
&= ~0x0001u
; // SPB2DT = 0
595 obj
->uart
->SCSCR
&= ~0x0020u
; // TE = 0 (Output disable)
601 void serial_break_clear(serial_t
*obj
) {
603 was_masked
= __disable_irq();
604 obj
->uart
->SCSCR
|= 0x0020u
; // TE = 1 (Output enable)
605 obj
->uart
->SCSPTR
|= 0x0001u
; // SPB2DT = 1
611 void serial_set_flow_control(serial_t
*obj
, FlowControl type
, PinName rxflow
, PinName txflow
) {
612 // determine the UART to use
615 serial_flow_irq_set(obj
, 0);
617 if (type
== FlowControlRTSCTS
) {
618 was_masked
= __disable_irq();
619 obj
->uart
->SCFCR
= 0x0008u
; // CTS/RTS enable
623 pinmap_pinout(rxflow
, PinMap_UART_RTS
);
624 pinmap_pinout(txflow
, PinMap_UART_CTS
);
626 was_masked
= __disable_irq();
627 obj
->uart
->SCFCR
= 0x0000u
; // CTS/RTS diable