Import Mbed OS hard-float snapshot
This commit is contained in:
344
targets/TARGET_Samsung/TARGET_SIDK_S5JS100/serial_usi_api.c
Normal file
344
targets/TARGET_Samsung/TARGET_SIDK_S5JS100/serial_usi_api.c
Normal file
@@ -0,0 +1,344 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* 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 "s5js100.h"
|
||||
#include "mbed_wait_api.h"
|
||||
#include "mbed_thread.h"
|
||||
|
||||
#define USI_PTR(ptr) ((S5JS100_USI_UART_TypeDef *)(ptr))
|
||||
static uart_irq_handler irq_handler[USI_MAX_PORTS];
|
||||
static uint32_t serial_irq_id[USI_MAX_PORTS] = {0};
|
||||
|
||||
|
||||
|
||||
|
||||
/****************** Internal code ************************/
|
||||
static inline void uart_irq(uint32_t intstatus, uint32_t index,
|
||||
UARTName uart)
|
||||
{
|
||||
|
||||
if (intstatus & (1 << 0)) {
|
||||
(irq_handler[index])(serial_irq_id[index], RxIrq);
|
||||
} else if (intstatus & (1 << 1)) {
|
||||
// RTS Int
|
||||
} else if (intstatus & (1 << 2)) {
|
||||
(irq_handler[index])(serial_irq_id[index], TxIrq);
|
||||
} else if (intstatus & (1 << 3)) {
|
||||
// CTS Int
|
||||
} else {
|
||||
}
|
||||
|
||||
USI_PTR(uart)->UINTP = intstatus;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static void uart0_irq()
|
||||
{
|
||||
uart_irq(S5JS100_USI0_UART->UINTP & 0xF, 0, UART_0);
|
||||
}
|
||||
|
||||
static void uart1_irq()
|
||||
{
|
||||
uart_irq(S5JS100_USI1_UART->UINTP & 0xF, 1, UART_1);
|
||||
}
|
||||
|
||||
|
||||
/*********************** API ******************************/
|
||||
|
||||
// serial_baud
|
||||
// set the baud rate, taking in to account the current SystemFrequency
|
||||
static void usi_serial_baud(void *obj, int baudrate)
|
||||
{
|
||||
struct serial_s *priv = (struct serial_s *)obj;
|
||||
int32_t sclk = 0;
|
||||
float div, frac;
|
||||
S5JS100_USI_UART_TypeDef *p_USI_UART = USI_PTR(priv->uart);
|
||||
switch ((int)priv->uart) {
|
||||
case UART_0:
|
||||
/* UBRDIV and UFRACVAL */
|
||||
sclk = cal_clk_getrate(d1_usi0);
|
||||
break;
|
||||
|
||||
case UART_1:
|
||||
/* UBRDIV and UFRACVAL */
|
||||
sclk = cal_clk_getrate(d1_usi1);
|
||||
break;
|
||||
|
||||
default:
|
||||
MBED_ASSERT(false);
|
||||
}
|
||||
|
||||
|
||||
div = ((float)sclk / (float)(baudrate * 16)) - 1.0;
|
||||
frac = (uint32_t)(((div - (int32_t)div) * 16));
|
||||
p_USI_UART->UBRDIV = (uint32_t)div;
|
||||
p_USI_UART->UFRACVAL = (uint32_t)frac;
|
||||
}
|
||||
|
||||
|
||||
static void usi_serial_format(void *obj, int data_bits,
|
||||
SerialParity parity, int stop_bits)
|
||||
{
|
||||
struct serial_s *priv = (struct serial_s *)obj;
|
||||
S5JS100_USI_UART_TypeDef *p_USI_UART = USI_PTR(priv->uart);
|
||||
uint32_t reg;
|
||||
|
||||
switch (data_bits) {
|
||||
case 5:
|
||||
reg = UART_ULCON_DATABITS_5BITS;
|
||||
break;
|
||||
case 6:
|
||||
reg = UART_ULCON_DATABITS_6BITS;
|
||||
break;
|
||||
case 7:
|
||||
reg = UART_ULCON_DATABITS_7BITS;
|
||||
break;
|
||||
default:
|
||||
reg = UART_ULCON_DATABITS_8BITS;
|
||||
}
|
||||
|
||||
switch (parity) {
|
||||
case ParityNone:
|
||||
reg |= UART_ULCON_PARITY_NONE;
|
||||
break;
|
||||
case ParityOdd:
|
||||
reg |= UART_ULCON_PARITY_ODD;
|
||||
break;
|
||||
case ParityEven:
|
||||
reg |= UART_ULCON_PARITY_EVEN;
|
||||
break;
|
||||
case ParityForced1:
|
||||
reg |= UART_ULCON_PARITY_FORCE1;
|
||||
break;
|
||||
case ParityForced0:
|
||||
reg |= UART_ULCON_PARITY_FORCE0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (stop_bits == 2) {
|
||||
reg |= UART_ULCON_STOPBITS_2BITS;
|
||||
}
|
||||
|
||||
p_USI_UART->ULCON = reg;
|
||||
}
|
||||
|
||||
|
||||
static void usi_serial_irq_handler(void *obj, uart_irq_handler handler, uint32_t id)
|
||||
{
|
||||
struct serial_s *priv = (struct serial_s *)obj;
|
||||
|
||||
irq_handler[priv->index] = handler;
|
||||
serial_irq_id[priv->index] = id;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void usi_serial_irq_set(void *obj, SerialIrq irq, uint32_t enable)
|
||||
{
|
||||
struct serial_s *priv = (struct serial_s *)obj;
|
||||
S5JS100_USI_UART_TypeDef *p_USI_UART = USI_PTR(priv->uart);
|
||||
|
||||
switch (irq) {
|
||||
case RxIrq:
|
||||
if (enable) {
|
||||
p_USI_UART->UINTM &= ~(UART_UINTM_RXD_MASK);
|
||||
} else {
|
||||
p_USI_UART->UINTM |= UART_UINTM_RXD_MASK;
|
||||
p_USI_UART->UINTP = UART_UINTP_RXD;
|
||||
}
|
||||
break;
|
||||
case TxIrq:
|
||||
if (enable) {
|
||||
p_USI_UART->UINTM &= ~(UART_UINTM_TXD_MASK);
|
||||
} else {
|
||||
p_USI_UART->UINTM |= UART_UINTM_TXD_MASK;
|
||||
p_USI_UART->UINTP = UART_UINTP_TXD;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int usi_serial_writable(void *obj)
|
||||
{
|
||||
struct serial_s *priv = (struct serial_s *)obj;
|
||||
S5JS100_USI_UART_TypeDef *p_USI_UART = USI_PTR(priv->uart);
|
||||
|
||||
return !(p_USI_UART->UFSTAT & UART_UFSTAT_TX_FIFO_FULL);
|
||||
}
|
||||
|
||||
|
||||
static void usi_serial_putc(void *obj, int c)
|
||||
{
|
||||
struct serial_s *priv = (struct serial_s *)obj;
|
||||
S5JS100_USI_UART_TypeDef *p_USI_UART = USI_PTR(priv->uart);
|
||||
while (!serial_writable(obj));
|
||||
p_USI_UART->UTXH = c;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int usi_serial_readable(void *obj)
|
||||
{
|
||||
struct serial_s *priv = (struct serial_s *)obj;
|
||||
S5JS100_USI_UART_TypeDef *p_USI_UART = USI_PTR(priv->uart);
|
||||
return (p_USI_UART->UFSTAT & (UART_UFSTAT_RX_FIFO_COUNT_MASK | UART_UFSTAT_RX_FIFO_FULL));
|
||||
}
|
||||
|
||||
static int usi_serial_getc(void *obj)
|
||||
{
|
||||
struct serial_s *priv = (struct serial_s *)obj;
|
||||
S5JS100_USI_UART_TypeDef *p_USI_UART = USI_PTR(priv->uart);
|
||||
int data;
|
||||
while (!serial_readable(obj));
|
||||
data = p_USI_UART->URXH & 0xFF;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
#if DEVICE_SERIAL_FC
|
||||
static void usi_serial_set_flow_control(struct serial_s *obj, FlowControl type,
|
||||
PinName rxflow, PinName txflow)
|
||||
{
|
||||
struct serial_s *priv = (struct serial_s *)obj;
|
||||
S5JS100_USI_UART_TypeDef *p_USI_UART = USI_PTR(priv->uart);
|
||||
// Checked used UART name (UART_1, UART_2, ...)
|
||||
if (type == FlowControlRTSCTS) {
|
||||
p_USI_UART->UMCON = UART_UMCON_RTS_TRIG_14BYTES | UART_UMCON_AFC_ENABLE;
|
||||
} else {
|
||||
p_USI_UART->UMCON = UART_UMCON_AFC_DISABLE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void usi_serial_init(void *obj, PinName tx, PinName rx)
|
||||
{
|
||||
struct serial_s *priv = (struct serial_s *)obj;
|
||||
S5JS100_USI_UART_TypeDef *p_USI_UART = USI_PTR(priv->uart);
|
||||
|
||||
IRQn_Type irq_n = (IRQn_Type)0;
|
||||
uint32_t vector = 0;
|
||||
|
||||
|
||||
p_USI_UART->UINTM = 0xF;
|
||||
p_USI_UART->UINTP = 0xF;
|
||||
|
||||
switch ((int)priv->uart) {
|
||||
case UART_0:
|
||||
if (! USI_VERSION_UART(S5JS100_USI0_REG->VERSION)) {
|
||||
/* UART NOT SUPPORTED */
|
||||
MBED_ASSERT(false);
|
||||
}
|
||||
|
||||
S5JS100_USI0_REG->CON = USI_CON_RST;
|
||||
S5JS100_SYSCFG_USI0_CONF = USI_CONFIG_UART;
|
||||
S5JS100_USI0_REG->CON &= ~USI_CON_RST;
|
||||
|
||||
priv->index = USI0_PORT_ID;
|
||||
priv->rx_fifo_depth = USI_RXFIFO(S5JS100_USI0_REG->FIFO_DEPTH);
|
||||
priv->tx_fifo_depth = USI_TXFIFO(S5JS100_USI0_REG->FIFO_DEPTH);
|
||||
|
||||
irq_n = S5JS100_IRQ_USI0;
|
||||
vector = (uint32_t)&uart0_irq;
|
||||
|
||||
break;
|
||||
|
||||
case UART_1:
|
||||
if (! USI_VERSION_UART(S5JS100_USI1_REG->VERSION)) {
|
||||
/* UART NOT SUPPORTED */
|
||||
while (1);
|
||||
}
|
||||
|
||||
S5JS100_USI1_REG->CON = USI_CON_RST;
|
||||
S5JS100_SYSCFG_USI1_CONF = USI_CONFIG_UART;
|
||||
S5JS100_USI1_REG->CON &= ~USI_CON_RST;
|
||||
|
||||
priv->index = USI1_PORT_ID;
|
||||
priv-> rx_fifo_depth = USI_RXFIFO(S5JS100_USI1_REG->FIFO_DEPTH);
|
||||
priv-> tx_fifo_depth = USI_TXFIFO(S5JS100_USI1_REG->FIFO_DEPTH);
|
||||
irq_n = S5JS100_IRQ_USI1;
|
||||
vector = (uint32_t)&uart1_irq;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Disable all interrupts and clear pendings
|
||||
p_USI_UART->UINTM = UART_UINTM_MODEM_MASK | UART_UINTM_TXD_MASK |
|
||||
UART_UINTM_RXD_MASK | UART_UINTM_ERROR_MASK;
|
||||
p_USI_UART->UINTP = UART_UINTP_MODEM | UART_UINTP_TXD |
|
||||
UART_UINTP_ERROR | UART_UINTP_RXD;
|
||||
|
||||
// reset FIFO and set interrupt trigger level
|
||||
p_USI_UART->UFCON = UART_UFCON_TX_FIFO_TRIG_14BYTES | UART_UFCON_RX_FIFO_TRIG_14BYTES |
|
||||
UART_UFCON_TX_FIFO_RESET | UART_UFCON_RX_FIFO_RESET |
|
||||
UART_UFCON_FIFO_ENABLE ;
|
||||
|
||||
//wait_ms(10);
|
||||
thread_sleep_for(10);
|
||||
|
||||
//Enable TX/RX fifo int/poll mode with RX timeout of 32 bits duration
|
||||
p_USI_UART->UCON = UART_UCON_RX_TOUT_32FRAMES | UART_UCON_RX_TOUTINT_ENABLE |
|
||||
UART_UCON_TX_INTTYPE_LEVEL | UART_UCON_RX_INTTYPE_LEVEL |
|
||||
UART_UCON_TX_MODE_IRQPOLL | UART_UCON_RX_MODE_IRQPOLL;
|
||||
|
||||
priv->ops.serial_baud = usi_serial_baud;
|
||||
priv->ops.serial_format = usi_serial_format;
|
||||
priv->ops.serial_irq_handler = usi_serial_irq_handler;
|
||||
priv->ops.serial_irq_set = usi_serial_irq_set;
|
||||
priv->ops.serial_putc = usi_serial_putc;
|
||||
priv->ops.serial_writable = usi_serial_writable;
|
||||
priv->ops.serial_getc = usi_serial_getc;
|
||||
priv->ops.serial_readable = usi_serial_readable;
|
||||
|
||||
#if DEVICE_SERIAL_FC
|
||||
priv->ops.serial_set_flow_control = usi_serial_set_flow_control;
|
||||
#endif
|
||||
/* Assign IRQ in advance and enable, all are masked anyways */
|
||||
NVIC_SetVector(irq_n, vector);
|
||||
#if defined (__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U)
|
||||
SCB_InvalidateICache();
|
||||
#endif
|
||||
NVIC_EnableIRQ(irq_n);
|
||||
|
||||
/* dissable IRQ by this if needed:
|
||||
NVIC_DisableIRQ(irq_n);
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
#endif // DEVICE_SERIAL
|
||||
Reference in New Issue
Block a user