/**************************************************************************** * * Copyright 2020 Samsung Electronics All Rights Reserved. * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. See the License for the specific * language governing permissions and limitations under the License. * ****************************************************************************/ #if DEVICE_SERIAL // math.h required for floating point operations for baud rate calculation #include <math.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include "device.h" #include "serial_api.h" #include "cmsis.h" #include "pinmap.h" #include "PinNames.h" #include "mbed_error.h" #include "gpio_api.h" #include "mbed_assert.h" void usi_serial_init(void *obj, PinName tx, PinName rx); void pl011_serial_init(void *obj, PinName tx, PinName rx); void dummy_serial_init(void *obj, PinName tx, PinName rx); /****************************************************************************** * INITIALIZATION ******************************************************************************/ static const PinMap PinMap_UART_TX[] = { {UART_TX0, UART_0, UART_TX0}, {UART_TX1, UART_1, UART_TX1}, {UART_TX2, UART_2, UART_TX2}, {UART_TX3, UART_3, UART_TX3}, {UART_TX4, UART_4, UART_TX4}, {UART_TX5, UART_5, UART_TX5}, {NC, NC, NC} }; static const PinMap PinMap_UART_RX[] = { {UART_RX0, UART_0, UART_RX0}, {UART_RX1, UART_1, UART_RX1}, {UART_RX2, UART_2, UART_RX2}, {UART_RX3, UART_3, UART_RX3}, {UART_RX4, UART_4, UART_RX4}, {UART_RX5, UART_5, UART_RX5}, {NC, NC, NC} }; /* static const PinMap PinMap_UART_CTS[] = { {UART0_CTS, UART_0, UART0_CTS}, {UART1_CTS, UART_1, UART1_CTS}, {UART2_CTS, UART_2, UART2_CTS}, {UART3_CTS, UART_3, UART3_CTS}, {NC, NC, NC} }; static const PinMap PinMap_UART_RTS[] = { {UART0_RTS, UART_0, UART0_RTS}, {UART1_RTS, UART_1, UART1_RTS}, {UART2_RTS, UART_2, UART2_RTS}, {UART3_RTS, UART_3, UART3_RTS}, {NC, NC, NC} }; */ /* Used in platform/mbed_retarget.cpp */ /* What shall I do with it??? What is it for? */ int stdio_uart_inited = 0; serial_t stdio_uart; void serial_init(serial_t *obj, PinName tx, PinName rx) { struct serial_s *priv = (struct serial_s *)obj; // determine the UART to use ??? // Shall we check if it is already allocated ??? UARTName uart_tx = (UARTName)pinmap_peripheral(tx, PinMap_UART_TX); UARTName uart_rx = (UARTName)pinmap_peripheral(rx, PinMap_UART_RX); UARTName uart = (UARTName)pinmap_merge(uart_tx, uart_rx); if ((PinName)uart == NC) { error("Serial pinout mapping failed"); } if ((PinName)uart_tx != NC) { s5js100_configgpio(pinmap_find_function(tx, PinMap_UART_TX)); } if ((PinName)uart_rx != NC) { s5js100_configgpio(pinmap_find_function(rx, PinMap_UART_RX)); } /* BAD Pointer assignment!!! Better to redesign*/ priv->uart = (void *)uart; switch (uart) { case UART_0: case UART_1: usi_serial_init(obj, tx, rx); break; case UART_2: case UART_3: pl011_serial_init(obj, tx, rx); break; case UART_4: case UART_5: dummy_serial_init(obj, tx, rx); break; } // set default baud rate and format obj->ops.serial_baud(obj, 115200); obj->ops.serial_format(obj, 8, ParityNone, 1); if (uart == STDIO_UART) { stdio_uart_inited = 1; memcpy(&stdio_uart, obj, sizeof(serial_t)); } } void serial_free(serial_t *obj) { //needs release serial } // serial_baud // set the baud rate, taking in to account the current SystemFrequency void serial_baud(serial_t *obj, int baudrate) { obj->ops.serial_baud(obj, baudrate); } void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_bits) { obj->ops.serial_format(obj, data_bits, parity, stop_bits); } void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id) { obj->ops.serial_irq_handler(obj, handler, id); } void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable) { obj->ops.serial_irq_set(obj, irq, enable); } #if DEVICE_SERIAL_FC void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, PinName txflow) { struct serial_s *priv = (struct serial_s *)obj; UARTName uart_rts = (UARTName)pinmap_peripheral(rxflow, PinMap_UART_RTS); UARTName uart_cts = (UARTName)pinmap_peripheral(txflow, PinMap_UART_CTS); UARTName uart = (UARTName)pinmap_merge(uart_rts, uart_cts); if ((PinName)uart == NC) { error("Serial pinout mapping failed"); } if ((int)uart != (int)priv->uart) { error("Serial pinout mapping failed"); } if (type == FlowControlRTS) { // Enable RTS MBED_ASSERT(uart_rts != (UARTName)NC); // Enable the pin for RTS function s5js100_configgpio(pinmap_find_function(rxflow, PinMap_UART_RTS)); } if (type == FlowControlCTS) { // Enable CTS MBED_ASSERT(uart_cts != (UARTName)NC); // Enable the pin for CTS function s5js100_configgpio(pinmap_find_function(txflow, PinMap_UART_CTS)); } if (type == FlowControlRTSCTS) { // Enable CTS & RTS MBED_ASSERT(uart_rts != (UARTName)NC); MBED_ASSERT(uart_cts != (UARTName)NC); // Enable the pin for CTS function s5js100_configgpio(pinmap_find_function(txflow, PinMap_UART_CTS)); // Enable the pin for RTS function s5js100_configgpio(pinmap_find_function(rxflow, PinMap_UART_RTS)); } obj->ops.serial_set_flow_control(obj, type, rxflow, txflow); } #endif /****************************************************************************** * READ/WRITE ******************************************************************************/ int serial_getc(serial_t *obj) { return obj->ops.serial_getc(obj); } void serial_putc(serial_t *obj, int c) { obj->ops.serial_putc(obj, c); } int serial_readable(serial_t *obj) { return obj->ops.serial_readable(obj); } int serial_writable(serial_t *obj) { return obj->ops.serial_writable(obj); } /* Shall it be ever used ??? void serial_clear(serial_t *obj) { if (obj->index < 2) { USI_PTR(obj->uart)->URXH = 0x00; while ((getreg32(0x83015018) & UART_UFSTAT_TX_FIFO_FULL)); while ((getreg32(0x83015018) & UART_UFSTAT_TX_FIFO_COUNT_MASK)); putreg8('C', 0x83015020); while ((getreg32(0x83015018) & UART_UFSTAT_TX_FIFO_FULL)); while ((getreg32(0x83015018) & UART_UFSTAT_TX_FIFO_COUNT_MASK)); putreg8('C', 0x83015020); putreg8('C', 0x83015020); putreg8('C', 0x83015020); putreg8('C', 0x83015020); putreg8('C', 0x83015020); putreg8('C', 0x83015020); } else { UART_PTR(obj->uart)->DR = 0x00; while (UART_PTR(obj->uart)->FR & (1u << 5)); while (UART_PTR(obj->uart)->FR & (1u << 7)); UART_PTR(obj->uart)->DR = 'C'; while (UART_PTR(obj->uart)->FR & (1u << 5)); while (UART_PTR(obj->uart)->FR & (1u << 7)); UART_PTR(obj->uart)->DR = 'C'; UART_PTR(obj->uart)->DR = 'C'; UART_PTR(obj->uart)->DR = 'C'; UART_PTR(obj->uart)->DR = 'C'; UART_PTR(obj->uart)->DR = 'C'; UART_PTR(obj->uart)->DR = 'C'; } } */ /* Used in * features/unsupported/tests/libs/SerialHalfDuplex/SerialHalfDuplex.cpp * What is it for? */ void serial_pinout_tx(PinName tx) { pinmap_pinout(tx, PinMap_UART_TX); } /* Serial break may never be used. * In general set TX to "0". * However - shall we? */ void serial_break_set(serial_t *obj) { } void serial_break_clear(serial_t *obj) { } /* pinmap test entry */ const PinMap *serial_tx_pinmap() { return PinMap_UART_TX; } const PinMap *serial_rx_pinmap() { return PinMap_UART_RX; } #endif // DEVICE_SERIAL