mirror of https://github.com/ARMmbed/mbed-os.git
CM3DS: update UART implementation
This commit adds the UART driver and updates the UART HAL implementation to use this driver. It also removes legacy definitions. Change-Id: Ie8e7a7bb64c763a2d97bc66d949fab3596736bbc Signed-off-by: Avinash Mehta <avinash.mehta@arm.com>pull/6170/head
parent
37cf802a7a
commit
a79a670575
|
@ -23,11 +23,11 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
typedef enum {
|
||||
UART_0 = (int)CMSDK_UART0_BASE, /* MCC UART */
|
||||
UART_1 = (int)CMSDK_UART1_BASE, /* MPS2+ UART */
|
||||
UART_2 = (int)CMSDK_UART2_BASE, /* Shield 0 UART */
|
||||
UART_3 = (int)CMSDK_UART3_BASE, /* Shield 1 UART */
|
||||
UART_4 = (int)CMSDK_UART4_BASE /* Shield BT UART */
|
||||
UART_0 = 0, /* MCC UART */
|
||||
UART_1, /* MPS2+ UART */
|
||||
UART_2, /* Shield 0 UART */
|
||||
UART_3, /* Shield 1 UART */
|
||||
UART_4 /* Shield BT UART */
|
||||
} UARTName;
|
||||
|
||||
typedef enum {
|
||||
|
|
|
@ -135,73 +135,6 @@ typedef enum IRQn
|
|||
#warning Not supported compiler type
|
||||
#endif
|
||||
|
||||
/*------------- Universal Asynchronous Receiver Transmitter (UART) -----------*/
|
||||
typedef struct
|
||||
{
|
||||
__IO uint32_t DATA; /* Offset: 0x000 (R/W) Data Register */
|
||||
__IO uint32_t STATE; /* Offset: 0x004 (R/W) Status Register */
|
||||
__IO uint32_t CTRL; /* Offset: 0x008 (R/W) Control Register */
|
||||
union {
|
||||
__I uint32_t INTSTATUS; /* Offset: 0x00C (R/ ) Interrupt Status Register */
|
||||
__O uint32_t INTCLEAR; /* Offset: 0x00C ( /W) Interrupt Clear Register */
|
||||
};
|
||||
__IO uint32_t BAUDDIV; /* Offset: 0x010 (R/W) Baudrate Divider Register */
|
||||
|
||||
} CMSDK_UART_TypeDef;
|
||||
|
||||
/* CMSDK_UART DATA Register Definitions */
|
||||
|
||||
#define CMSDK_UART_DATA_Pos 0 /* CMSDK_UART_DATA_Pos: DATA Position */
|
||||
#define CMSDK_UART_DATA_Msk (0xFFul << CMSDK_UART_DATA_Pos) /* CMSDK_UART DATA: DATA Mask */
|
||||
|
||||
#define CMSDK_UART_STATE_RXOR_Pos 3 /* CMSDK_UART STATE: RXOR Position */
|
||||
#define CMSDK_UART_STATE_RXOR_Msk (0x1ul << CMSDK_UART_STATE_RXOR_Pos) /* CMSDK_UART STATE: RXOR Mask */
|
||||
|
||||
#define CMSDK_UART_STATE_TXOR_Pos 2 /* CMSDK_UART STATE: TXOR Position */
|
||||
#define CMSDK_UART_STATE_TXOR_Msk (0x1ul << CMSDK_UART_STATE_TXOR_Pos) /* CMSDK_UART STATE: TXOR Mask */
|
||||
|
||||
#define CMSDK_UART_STATE_RXBF_Pos 1 /* CMSDK_UART STATE: RXBF Position */
|
||||
#define CMSDK_UART_STATE_RXBF_Msk (0x1ul << CMSDK_UART_STATE_RXBF_Pos) /* CMSDK_UART STATE: RXBF Mask */
|
||||
|
||||
#define CMSDK_UART_STATE_TXBF_Pos 0 /* CMSDK_UART STATE: TXBF Position */
|
||||
#define CMSDK_UART_STATE_TXBF_Msk (0x1ul << CMSDK_UART_STATE_TXBF_Pos ) /* CMSDK_UART STATE: TXBF Mask */
|
||||
|
||||
#define CMSDK_UART_CTRL_HSTM_Pos 6 /* CMSDK_UART CTRL: HSTM Position */
|
||||
#define CMSDK_UART_CTRL_HSTM_Msk (0x01ul << CMSDK_UART_CTRL_HSTM_Pos) /* CMSDK_UART CTRL: HSTM Mask */
|
||||
|
||||
#define CMSDK_UART_CTRL_RXORIRQEN_Pos 5 /* CMSDK_UART CTRL: RXORIRQEN Position */
|
||||
#define CMSDK_UART_CTRL_RXORIRQEN_Msk (0x01ul << CMSDK_UART_CTRL_RXORIRQEN_Pos) /* CMSDK_UART CTRL: RXORIRQEN Mask */
|
||||
|
||||
#define CMSDK_UART_CTRL_TXORIRQEN_Pos 4 /* CMSDK_UART CTRL: TXORIRQEN Position */
|
||||
#define CMSDK_UART_CTRL_TXORIRQEN_Msk (0x01ul << CMSDK_UART_CTRL_TXORIRQEN_Pos) /* CMSDK_UART CTRL: TXORIRQEN Mask */
|
||||
|
||||
#define CMSDK_UART_CTRL_RXIRQEN_Pos 3 /* CMSDK_UART CTRL: RXIRQEN Position */
|
||||
#define CMSDK_UART_CTRL_RXIRQEN_Msk (0x01ul << CMSDK_UART_CTRL_RXIRQEN_Pos) /* CMSDK_UART CTRL: RXIRQEN Mask */
|
||||
|
||||
#define CMSDK_UART_CTRL_TXIRQEN_Pos 2 /* CMSDK_UART CTRL: TXIRQEN Position */
|
||||
#define CMSDK_UART_CTRL_TXIRQEN_Msk (0x01ul << CMSDK_UART_CTRL_TXIRQEN_Pos) /* CMSDK_UART CTRL: TXIRQEN Mask */
|
||||
|
||||
#define CMSDK_UART_CTRL_RXEN_Pos 1 /* CMSDK_UART CTRL: RXEN Position */
|
||||
#define CMSDK_UART_CTRL_RXEN_Msk (0x01ul << CMSDK_UART_CTRL_RXEN_Pos) /* CMSDK_UART CTRL: RXEN Mask */
|
||||
|
||||
#define CMSDK_UART_CTRL_TXEN_Pos 0 /* CMSDK_UART CTRL: TXEN Position */
|
||||
#define CMSDK_UART_CTRL_TXEN_Msk (0x01ul << CMSDK_UART_CTRL_TXEN_Pos) /* CMSDK_UART CTRL: TXEN Mask */
|
||||
|
||||
#define CMSDK_UART_INTSTATUS_RXORIRQ_Pos 3 /* CMSDK_UART CTRL: RXORIRQ Position */
|
||||
#define CMSDK_UART_INTSTATUS_RXORIRQ_Msk (0x01ul << CMSDK_UART_INTSTATUS_RXORIRQ_Pos) /* CMSDK_UART CTRL: RXORIRQ Mask */
|
||||
|
||||
#define CMSDK_UART_INTSTATUS_TXORIRQ_Pos 2 /* CMSDK_UART CTRL: TXORIRQ Position */
|
||||
#define CMSDK_UART_INTSTATUS_TXORIRQ_Msk (0x01ul << CMSDK_UART_INTSTATUS_TXORIRQ_Pos) /* CMSDK_UART CTRL: TXORIRQ Mask */
|
||||
|
||||
#define CMSDK_UART_INTSTATUS_RXIRQ_Pos 1 /* CMSDK_UART CTRL: RXIRQ Position */
|
||||
#define CMSDK_UART_INTSTATUS_RXIRQ_Msk (0x01ul << CMSDK_UART_INTSTATUS_RXIRQ_Pos) /* CMSDK_UART CTRL: RXIRQ Mask */
|
||||
|
||||
#define CMSDK_UART_INTSTATUS_TXIRQ_Pos 0 /* CMSDK_UART CTRL: TXIRQ Position */
|
||||
#define CMSDK_UART_INTSTATUS_TXIRQ_Msk (0x01ul << CMSDK_UART_INTSTATUS_TXIRQ_Pos) /* CMSDK_UART CTRL: TXIRQ Mask */
|
||||
|
||||
#define CMSDK_UART_BAUDDIV_Pos 0 /* CMSDK_UART BAUDDIV: BAUDDIV Position */
|
||||
#define CMSDK_UART_BAUDDIV_Msk (0xFFFFFul << CMSDK_UART_BAUDDIV_Pos) /* CMSDK_UART BAUDDIV: BAUDDIV Mask */
|
||||
|
||||
/*------------- System Control (SYSCON) --------------------------------------*/
|
||||
typedef struct
|
||||
{
|
||||
|
@ -408,11 +341,6 @@ typedef struct
|
|||
/* ================ Peripheral declaration ================ */
|
||||
/* ================================================================================ */
|
||||
|
||||
#define CMSDK_UART0 ((CMSDK_UART_TypeDef *) CMSDK_UART0_BASE )
|
||||
#define CMSDK_UART1 ((CMSDK_UART_TypeDef *) CMSDK_UART1_BASE )
|
||||
#define CMSDK_UART2 ((CMSDK_UART_TypeDef *) CMSDK_UART2_BASE )
|
||||
#define CMSDK_UART3 ((CMSDK_UART_TypeDef *) CMSDK_UART3_BASE )
|
||||
#define CMSDK_UART4 ((CMSDK_UART_TypeDef *) CMSDK_UART4_BASE )
|
||||
#define CMSDK_RTC ((CMSDK_RTC_TypeDef *) CMSDK_RTC_BASE )
|
||||
#define CMSDK_WATCHDOG ((CMSDK_WATCHDOG_TypeDef *) CMSDK_WATCHDOG_BASE )
|
||||
#define CMSDK_SYSCON ((CMSDK_SYSCON_TypeDef *) CMSDK_SYSCTRL_BASE )
|
||||
|
@ -421,4 +349,4 @@ typedef struct
|
|||
}
|
||||
#endif
|
||||
|
||||
#endif /* CMSDK_BEETLE_H */
|
||||
#endif /* CMSDK_CM3DS_H */
|
||||
|
|
|
@ -50,4 +50,12 @@
|
|||
#define ARM_SPI3
|
||||
#define ARM_SPI4
|
||||
|
||||
/* ARM UART */
|
||||
#define DEFAULT_UART_BAUDRATE 9600
|
||||
#define ARM_UART0
|
||||
#define ARM_UART1
|
||||
#define ARM_UART2
|
||||
#define ARM_UART3
|
||||
#define ARM_UART4
|
||||
|
||||
#endif /* __ARM_LTD_DEVICE_CFG_H__ */
|
||||
|
|
|
@ -0,0 +1,283 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2018 ARM Limited
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "arm_uart_drv.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
/* UART register map structure */
|
||||
struct _arm_uart_reg_map_t {
|
||||
volatile uint32_t data; /* Offset: 0x000 (R/W) data register */
|
||||
volatile uint32_t state; /* Offset: 0x004 (R/W) status register */
|
||||
volatile uint32_t ctrl; /* Offset: 0x008 (R/W) control register */
|
||||
union {
|
||||
volatile uint32_t intrstatus; /* Offset: 0x00c (R/ ) interrupt status
|
||||
* register */
|
||||
volatile uint32_t intrclear; /* Offset: 0x00c ( /W) interrupt clear
|
||||
* register */
|
||||
}intr_reg;
|
||||
volatile uint32_t bauddiv; /* Offset: 0x010 (R/W) Baudrate divider
|
||||
* register */
|
||||
};
|
||||
|
||||
/* CTRL Register */
|
||||
#define ARM_UART_TX_EN (1ul << 0)
|
||||
#define ARM_UART_RX_EN (1ul << 1)
|
||||
#define ARM_UART_TX_INTR_EN (1ul << 2)
|
||||
#define ARM_UART_RX_INTR_EN (1ul << 3)
|
||||
|
||||
/* STATE Register */
|
||||
#define ARM_UART_TX_BF (1ul << 0)
|
||||
#define ARM_UART_RX_BF (1ul << 1)
|
||||
|
||||
/* INTSTATUS Register */
|
||||
#define ARM_UART_TX_INTR (1ul << 0)
|
||||
#define ARM_UART_RX_INTR (1ul << 1)
|
||||
|
||||
/* UART state definitions */
|
||||
#define ARM_UART_INITIALIZED (1ul << 0)
|
||||
|
||||
enum arm_uart_error_t arm_uart_init(struct arm_uart_dev_t* dev,
|
||||
uint32_t system_clk)
|
||||
{
|
||||
struct _arm_uart_reg_map_t* p_uart =
|
||||
(struct _arm_uart_reg_map_t*)dev->cfg->base;
|
||||
if(system_clk == 0) {
|
||||
return ARM_UART_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
/* Sets baudrate and system clock */
|
||||
dev->data->system_clk = system_clk;
|
||||
dev->data->baudrate = dev->cfg->default_baudrate;
|
||||
|
||||
/* Sets baudrate */
|
||||
p_uart->bauddiv = (dev->data->system_clk / dev->cfg->default_baudrate);
|
||||
|
||||
/* Enables receiver and transmitter */
|
||||
p_uart->ctrl = ARM_UART_RX_EN | ARM_UART_TX_EN;
|
||||
|
||||
dev->data->state = ARM_UART_INITIALIZED;
|
||||
|
||||
return ARM_UART_ERR_NONE;
|
||||
}
|
||||
|
||||
enum arm_uart_error_t arm_uart_set_baudrate(struct arm_uart_dev_t* dev,
|
||||
uint32_t baudrate)
|
||||
{
|
||||
uint32_t bauddiv;
|
||||
struct _arm_uart_reg_map_t* p_uart =
|
||||
(struct _arm_uart_reg_map_t*)dev->cfg->base;
|
||||
|
||||
if(baudrate == 0) {
|
||||
return ARM_UART_ERR_INVALID_BAUD;
|
||||
}
|
||||
|
||||
if(!(dev->data->state & ARM_UART_INITIALIZED)) {
|
||||
return ARM_UART_ERR_NOT_INIT;
|
||||
}
|
||||
|
||||
/* Sets baudrate */
|
||||
bauddiv = (dev->data->system_clk / baudrate);
|
||||
dev->data->baudrate = baudrate;
|
||||
|
||||
/* Minimum bauddiv value */
|
||||
if(bauddiv < 16) {
|
||||
return ARM_UART_ERR_INVALID_BAUD;
|
||||
}
|
||||
|
||||
p_uart->bauddiv = bauddiv;
|
||||
|
||||
return ARM_UART_ERR_NONE;
|
||||
}
|
||||
|
||||
uint32_t arm_uart_get_baudrate(struct arm_uart_dev_t* dev)
|
||||
{
|
||||
return dev->data->baudrate;
|
||||
}
|
||||
|
||||
enum arm_uart_error_t arm_uart_set_clock(struct arm_uart_dev_t* dev,
|
||||
uint32_t system_clk)
|
||||
{
|
||||
struct _arm_uart_reg_map_t* p_uart =
|
||||
(struct _arm_uart_reg_map_t*)dev->cfg->base;
|
||||
|
||||
if(system_clk == 0) {
|
||||
return ARM_UART_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if(!(dev->data->state & ARM_UART_INITIALIZED)) {
|
||||
return ARM_UART_ERR_NOT_INIT;
|
||||
}
|
||||
|
||||
/* Sets system clock */
|
||||
dev->data->system_clk = system_clk;
|
||||
|
||||
/* Updates baudrate divider */
|
||||
p_uart->bauddiv = (dev->data->system_clk / dev->data->baudrate);
|
||||
|
||||
/* Enables receiver and transmitter */
|
||||
return ARM_UART_ERR_NONE;
|
||||
}
|
||||
|
||||
enum arm_uart_error_t arm_uart_read(struct arm_uart_dev_t* dev, uint8_t* byte)
|
||||
{
|
||||
struct _arm_uart_reg_map_t* p_uart =
|
||||
(struct _arm_uart_reg_map_t*)dev->cfg->base;
|
||||
|
||||
if(!(p_uart->state & ARM_UART_RX_BF)) {
|
||||
return ARM_UART_ERR_NOT_READY;
|
||||
}
|
||||
|
||||
/* Reads data */
|
||||
*byte = (uint8_t)p_uart->data;
|
||||
|
||||
return ARM_UART_ERR_NONE;
|
||||
}
|
||||
|
||||
enum arm_uart_error_t arm_uart_write(struct arm_uart_dev_t* dev, uint8_t byte)
|
||||
{
|
||||
struct _arm_uart_reg_map_t* p_uart =
|
||||
(struct _arm_uart_reg_map_t*)dev->cfg->base;
|
||||
|
||||
if(p_uart->state & ARM_UART_TX_BF) {
|
||||
return ARM_UART_ERR_NOT_READY;
|
||||
}
|
||||
|
||||
/* Sends data */
|
||||
p_uart->data = byte;
|
||||
|
||||
return ARM_UART_ERR_NONE;
|
||||
}
|
||||
|
||||
enum arm_uart_error_t arm_uart_irq_tx_enable(struct arm_uart_dev_t* dev)
|
||||
{
|
||||
struct _arm_uart_reg_map_t* p_uart =
|
||||
(struct _arm_uart_reg_map_t*)dev->cfg->base;
|
||||
|
||||
if(!(dev->data->state & ARM_UART_INITIALIZED)) {
|
||||
return ARM_UART_ERR_NOT_INIT;
|
||||
}
|
||||
|
||||
p_uart->ctrl |= ARM_UART_TX_INTR_EN;
|
||||
|
||||
return ARM_UART_ERR_NONE;
|
||||
}
|
||||
|
||||
void arm_uart_irq_tx_disable(struct arm_uart_dev_t* dev)
|
||||
{
|
||||
struct _arm_uart_reg_map_t* p_uart =
|
||||
(struct _arm_uart_reg_map_t*)dev->cfg->base;
|
||||
|
||||
if(dev->data->state & ARM_UART_INITIALIZED ) {
|
||||
p_uart->ctrl &= ~ARM_UART_TX_INTR_EN;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t arm_uart_tx_ready(struct arm_uart_dev_t* dev)
|
||||
{
|
||||
struct _arm_uart_reg_map_t* p_uart =
|
||||
(struct _arm_uart_reg_map_t*)dev->cfg->base;
|
||||
|
||||
if(!(dev->data->state & ARM_UART_INITIALIZED)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return !(p_uart->state & ARM_UART_TX_BF);
|
||||
}
|
||||
|
||||
enum arm_uart_error_t arm_uart_irq_rx_enable(struct arm_uart_dev_t* dev)
|
||||
{
|
||||
struct _arm_uart_reg_map_t* p_uart =
|
||||
(struct _arm_uart_reg_map_t*)dev->cfg->base;
|
||||
|
||||
if(!(dev->data->state & ARM_UART_INITIALIZED)) {
|
||||
return ARM_UART_ERR_NOT_INIT;
|
||||
}
|
||||
|
||||
p_uart->ctrl |= ARM_UART_RX_INTR_EN;
|
||||
|
||||
return ARM_UART_ERR_NONE;
|
||||
}
|
||||
|
||||
void arm_uart_irq_rx_disable(struct arm_uart_dev_t* dev)
|
||||
{
|
||||
struct _arm_uart_reg_map_t* p_uart =
|
||||
(struct _arm_uart_reg_map_t*)dev->cfg->base;
|
||||
|
||||
if(dev->data->state & ARM_UART_INITIALIZED) {
|
||||
p_uart->ctrl &= ~ARM_UART_RX_INTR_EN;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t arm_uart_rx_ready(struct arm_uart_dev_t* dev)
|
||||
{
|
||||
struct _arm_uart_reg_map_t* p_uart =
|
||||
(struct _arm_uart_reg_map_t*)dev->cfg->base;
|
||||
|
||||
if(!(dev->data->state & ARM_UART_INITIALIZED)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (p_uart->state & ARM_UART_RX_BF);
|
||||
}
|
||||
|
||||
void arm_uart_clear_interrupt(struct arm_uart_dev_t* dev,
|
||||
enum arm_uart_irq_t irq)
|
||||
{
|
||||
struct _arm_uart_reg_map_t* p_uart =
|
||||
(struct _arm_uart_reg_map_t*)dev->cfg->base;
|
||||
|
||||
if(dev->data->state & ARM_UART_INITIALIZED) {
|
||||
/* Clears pending interrupts */
|
||||
switch(irq) {
|
||||
case ARM_UART_IRQ_RX:
|
||||
p_uart->intr_reg.intrclear = ARM_UART_RX_INTR;
|
||||
break;
|
||||
case ARM_UART_IRQ_TX:
|
||||
p_uart->intr_reg.intrclear = ARM_UART_TX_INTR;
|
||||
break;
|
||||
case ARM_UART_IRQ_COMBINED:
|
||||
p_uart->intr_reg.intrclear = (ARM_UART_RX_INTR | ARM_UART_TX_INTR);
|
||||
break;
|
||||
case ARM_UART_IRQ_NONE:
|
||||
break;
|
||||
/* default: not defined to force all cases to be handled */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum arm_uart_irq_t arm_uart_get_interrupt_status(struct arm_uart_dev_t* dev)
|
||||
{
|
||||
struct _arm_uart_reg_map_t* p_uart =
|
||||
(struct _arm_uart_reg_map_t*)dev->cfg->base;
|
||||
|
||||
|
||||
if(dev->data->state & ARM_UART_INITIALIZED) {
|
||||
switch(p_uart->intr_reg.intrstatus) {
|
||||
case ARM_UART_TX_INTR:
|
||||
return ARM_UART_IRQ_TX;
|
||||
break;
|
||||
case ARM_UART_RX_INTR:
|
||||
return ARM_UART_IRQ_RX;
|
||||
break;
|
||||
case ARM_UART_TX_INTR | ARM_UART_RX_INTR:
|
||||
return ARM_UART_IRQ_COMBINED;
|
||||
break;
|
||||
/* default: not defined to force all cases to be handled */
|
||||
}
|
||||
}
|
||||
return ARM_UART_IRQ_NONE;
|
||||
}
|
|
@ -0,0 +1,230 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2018 ARM Limited
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file arm_uart_drv.h
|
||||
* \brief Generic driver for ARM UART.
|
||||
*/
|
||||
|
||||
#ifndef __ARM_UART_DRV_H__
|
||||
#define __ARM_UART_DRV_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* ARM UART device configuration structure */
|
||||
struct arm_uart_dev_cfg_t {
|
||||
const uint32_t base; /*!< UART base address */
|
||||
const uint32_t default_baudrate; /*!< Default baudrate */
|
||||
};
|
||||
|
||||
/* ARM UART device data structure */
|
||||
struct arm_uart_dev_data_t {
|
||||
uint32_t state; /*!< Indicates if the uart driver
|
||||
is initialized and enabled */
|
||||
uint32_t system_clk; /*!< System clock */
|
||||
uint32_t baudrate; /*!< Baudrate */
|
||||
};
|
||||
|
||||
/* ARM UART device structure */
|
||||
struct arm_uart_dev_t {
|
||||
const struct arm_uart_dev_cfg_t* const cfg; /*!< UART configuration */
|
||||
struct arm_uart_dev_data_t* const data; /*!< UART data */
|
||||
};
|
||||
|
||||
/* ARM UART enumeration types */
|
||||
enum arm_uart_error_t {
|
||||
ARM_UART_ERR_NONE = 0, /*!< No error */
|
||||
ARM_UART_ERR_INVALID_ARG, /*!< Error invalid input argument */
|
||||
ARM_UART_ERR_INVALID_BAUD, /*!< Invalid baudrate */
|
||||
ARM_UART_ERR_NOT_INIT, /*!< Error UART not initialized */
|
||||
ARM_UART_ERR_NOT_READY, /*!< Error UART not ready */
|
||||
};
|
||||
|
||||
enum arm_uart_irq_t {
|
||||
ARM_UART_IRQ_RX, /*!< RX interrupt source */
|
||||
ARM_UART_IRQ_TX, /*!< TX interrupt source */
|
||||
ARM_UART_IRQ_COMBINED, /*!< RX-TX combined interrupt source */
|
||||
ARM_UART_IRQ_NONE = 0xFF /*!< RX-TX combined interrupt source */
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Initializes UART. It uses the default baudrate to configure
|
||||
* the peripheral at this point.
|
||||
*
|
||||
* \param[in] dev UART device struct \ref arm_uart_dev_t
|
||||
* \param[in] system_clk System clock used by the device.
|
||||
*
|
||||
* \return Returns error code as specified in \ref arm_uart_error_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
enum arm_uart_error_t arm_uart_init(struct arm_uart_dev_t* dev,
|
||||
uint32_t system_clk);
|
||||
|
||||
/**
|
||||
* \brief Sets the UART baudrate.
|
||||
*
|
||||
* \param[in] dev UART device struct \ref arm_uart_dev_t
|
||||
* \param[in] baudrate New baudrate.
|
||||
*
|
||||
* \return Returns error code as specified in \ref arm_uart_error_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
enum arm_uart_error_t arm_uart_set_baudrate(struct arm_uart_dev_t* dev,
|
||||
uint32_t baudrate);
|
||||
|
||||
/**
|
||||
* \brief Gets the UART baudrate.
|
||||
*
|
||||
* \param[in] dev UART device struct \ref arm_uart_dev_t
|
||||
*
|
||||
* \return Returns the UART baudrate.
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
uint32_t arm_uart_get_baudrate(struct arm_uart_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Sets system clock.
|
||||
*
|
||||
* \param[in] dev UART device struct \ref arm_uart_dev_t
|
||||
* \param[in] system_clk System clock used by the device.
|
||||
*
|
||||
* \return Returns error code as specified in \ref arm_uart_error_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
enum arm_uart_error_t arm_uart_set_clock(struct arm_uart_dev_t* dev,
|
||||
uint32_t system_clk);
|
||||
/**
|
||||
* \brief Reads one byte from UART dev.
|
||||
*
|
||||
* \param[in] dev UART device struct \ref arm_uart_dev_t
|
||||
* \param[in] byte Pointer to byte.
|
||||
*
|
||||
* \return Returns error code as specified in \ref arm_uart_error_t
|
||||
*
|
||||
* \note For better performance, this function doesn't check if dev and byte
|
||||
* pointer are NULL, and if the driver is initialized.
|
||||
*/
|
||||
enum arm_uart_error_t arm_uart_read(struct arm_uart_dev_t* dev, uint8_t* byte);
|
||||
|
||||
/**
|
||||
* \brief Writes a byte to UART dev.
|
||||
*
|
||||
* \param[in] dev UART device struct \ref arm_uart_dev_t
|
||||
* \param[in] byte Byte to write.
|
||||
*
|
||||
* \return Returns error code as specified in \ref arm_uart_error_t
|
||||
*
|
||||
* \note For better performance, this function doesn't check if dev is NULL and
|
||||
* if the driver is initialized to have better performance.
|
||||
*/
|
||||
enum arm_uart_error_t arm_uart_write(struct arm_uart_dev_t* dev, uint8_t byte);
|
||||
|
||||
/**
|
||||
* \brief Enables TX interrupt.
|
||||
*
|
||||
* \param[in] dev UART device struct \ref arm_uart_dev_t
|
||||
*
|
||||
* \return Returns error code as specified in \ref arm_uart_error_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
enum arm_uart_error_t arm_uart_irq_tx_enable(struct arm_uart_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Disables TX interrupt.
|
||||
*
|
||||
* \param[in] dev UART device struct \ref arm_uart_dev_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
void arm_uart_irq_tx_disable(struct arm_uart_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Verifies if Tx is ready to send more data.
|
||||
*
|
||||
* \param[in] dev UART device struct \ref arm_uart_dev_t
|
||||
*
|
||||
* \return 1 if TX is ready, 0 otherwise.
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
uint32_t arm_uart_tx_ready(struct arm_uart_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Enables RX interrupt.
|
||||
*
|
||||
* \param[in] dev UART device struct \ref arm_uart_dev_t
|
||||
*
|
||||
* \return Returns error code as specified in \ref arm_uart_error_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
enum arm_uart_error_t arm_uart_irq_rx_enable(struct arm_uart_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Disables RX interrupt
|
||||
*
|
||||
* \param[in] dev UART device struct \ref arm_uart_dev_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
void arm_uart_irq_rx_disable(struct arm_uart_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Verifies if Rx has data.
|
||||
*
|
||||
* \param[in] dev UART device struct \ref arm_uart_dev_t
|
||||
*
|
||||
* \return 1 if RX has data, 0 otherwise.
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
uint32_t arm_uart_rx_ready(struct arm_uart_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Clears UART interrupt.
|
||||
*
|
||||
* \param[in] dev UART device struct \ref arm_uart_dev_t
|
||||
* \param[in] irq IRQ source to clean \ref arm_uart_irq_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
void arm_uart_clear_interrupt(struct arm_uart_dev_t* dev,
|
||||
enum arm_uart_irq_t irq);
|
||||
|
||||
/**
|
||||
* \brief Returns UART interrupt status.
|
||||
*
|
||||
* \param[in] dev UART device struct \ref arm_uart_dev_t
|
||||
*
|
||||
* \return IRQ status \ref arm_uart_irq_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
enum arm_uart_irq_t arm_uart_get_interrupt_status(struct arm_uart_dev_t* dev);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* __ARM_UART_DRV_H__ */
|
|
@ -208,3 +208,64 @@ static struct spi_pl022_dev_data_t SPI4_PL022_DEV_DATA = {
|
|||
struct spi_pl022_dev_t SPI4_PL022_DEV = {&(SPI4_PL022_DEV_CFG),
|
||||
&(SPI4_PL022_DEV_DATA)};
|
||||
#endif /* ARM_SPI4 */
|
||||
|
||||
/* ARM UART driver structures */
|
||||
#ifdef ARM_UART0
|
||||
static const struct arm_uart_dev_cfg_t ARM_UART0_DEV_CFG = {
|
||||
.base = CMSDK_UART0_BASE,
|
||||
.default_baudrate = DEFAULT_UART_BAUDRATE};
|
||||
static struct arm_uart_dev_data_t ARM_UART0_DEV_DATA = {
|
||||
.state = 0,
|
||||
.system_clk = 0,
|
||||
.baudrate = 0};
|
||||
struct arm_uart_dev_t ARM_UART0_DEV = {&(ARM_UART0_DEV_CFG),
|
||||
&(ARM_UART0_DEV_DATA)};
|
||||
#endif /* ARM_UART0 */
|
||||
|
||||
#ifdef ARM_UART1
|
||||
static const struct arm_uart_dev_cfg_t ARM_UART1_DEV_CFG = {
|
||||
.base = CMSDK_UART1_BASE,
|
||||
.default_baudrate = DEFAULT_UART_BAUDRATE};
|
||||
static struct arm_uart_dev_data_t ARM_UART1_DEV_DATA = {
|
||||
.state = 0,
|
||||
.system_clk = 0,
|
||||
.baudrate = 0};
|
||||
struct arm_uart_dev_t ARM_UART1_DEV = {&(ARM_UART1_DEV_CFG),
|
||||
&(ARM_UART1_DEV_DATA)};
|
||||
#endif /* ARM_UART1 */
|
||||
|
||||
#ifdef ARM_UART2
|
||||
static const struct arm_uart_dev_cfg_t ARM_UART2_DEV_CFG = {
|
||||
.base = CMSDK_UART2_BASE,
|
||||
.default_baudrate = DEFAULT_UART_BAUDRATE};
|
||||
static struct arm_uart_dev_data_t ARM_UART2_DEV_DATA = {
|
||||
.state = 0,
|
||||
.system_clk = 0,
|
||||
.baudrate = 0};
|
||||
struct arm_uart_dev_t ARM_UART2_DEV = {&(ARM_UART2_DEV_CFG),
|
||||
&(ARM_UART2_DEV_DATA)};
|
||||
#endif /* ARM_UART2 */
|
||||
|
||||
#ifdef ARM_UART3
|
||||
static const struct arm_uart_dev_cfg_t ARM_UART3_DEV_CFG = {
|
||||
.base = CMSDK_UART3_BASE,
|
||||
.default_baudrate = DEFAULT_UART_BAUDRATE};
|
||||
static struct arm_uart_dev_data_t ARM_UART3_DEV_DATA = {
|
||||
.state = 0,
|
||||
.system_clk = 0,
|
||||
.baudrate = 0};
|
||||
struct arm_uart_dev_t ARM_UART3_DEV = {&(ARM_UART3_DEV_CFG),
|
||||
&(ARM_UART3_DEV_DATA)};
|
||||
#endif /* ARM_UART3 */
|
||||
|
||||
#ifdef ARM_UART4
|
||||
static const struct arm_uart_dev_cfg_t ARM_UART4_DEV_CFG = {
|
||||
.base = CMSDK_UART4_BASE,
|
||||
.default_baudrate = DEFAULT_UART_BAUDRATE};
|
||||
static struct arm_uart_dev_data_t ARM_UART4_DEV_DATA = {
|
||||
.state = 0,
|
||||
.system_clk = 0,
|
||||
.baudrate = 0};
|
||||
struct arm_uart_dev_t ARM_UART4_DEV = {&(ARM_UART4_DEV_CFG),
|
||||
&(ARM_UART4_DEV_DATA)};
|
||||
#endif /* ARM_UART4 */
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "arm_gpio_drv.h"
|
||||
#include "arm_mps2_io_drv.h"
|
||||
#include "spi_pl022_drv.h"
|
||||
#include "arm_uart_drv.h"
|
||||
|
||||
/* ======= Defines peripheral configuration structures ======= */
|
||||
|
||||
|
@ -77,4 +78,21 @@ extern struct spi_pl022_dev_t SPI3_PL022_DEV;
|
|||
extern struct spi_pl022_dev_t SPI4_PL022_DEV;
|
||||
#endif
|
||||
|
||||
/* ARM UART driver structures */
|
||||
#ifdef ARM_UART0
|
||||
extern struct arm_uart_dev_t ARM_UART0_DEV;
|
||||
#endif
|
||||
#ifdef ARM_UART1
|
||||
extern struct arm_uart_dev_t ARM_UART1_DEV;
|
||||
#endif
|
||||
#ifdef ARM_UART2
|
||||
extern struct arm_uart_dev_t ARM_UART2_DEV;
|
||||
#endif
|
||||
#ifdef ARM_UART3
|
||||
extern struct arm_uart_dev_t ARM_UART3_DEV;
|
||||
#endif
|
||||
#ifdef ARM_UART4
|
||||
extern struct arm_uart_dev_t ARM_UART4_DEV;
|
||||
#endif
|
||||
|
||||
#endif /* __ARM_LTD_PLATFORM_DEVICES_H__ */
|
||||
|
|
|
@ -47,8 +47,10 @@ struct port_s {
|
|||
};
|
||||
|
||||
struct serial_s {
|
||||
CMSDK_UART_TypeDef *uart;
|
||||
int index;
|
||||
struct arm_uart_dev_t *uart;
|
||||
UARTName index;
|
||||
IRQn_Type irq_number; /* IRQ number of the RX interrupt for
|
||||
this UART device */
|
||||
};
|
||||
|
||||
struct i2c_s {
|
||||
|
|
|
@ -20,174 +20,138 @@
|
|||
#include <stdlib.h>
|
||||
|
||||
#include "serial_api.h"
|
||||
#include "cmsis.h"
|
||||
#include "pinmap.h"
|
||||
#include "mbed_error.h"
|
||||
#include "gpio_api.h"
|
||||
#include "platform_devices.h"
|
||||
|
||||
/******************************************************************************
|
||||
* INITIALIZATION
|
||||
******************************************************************************/
|
||||
|
||||
#define STDIO_UART_NOT_INITED 0
|
||||
#define STDIO_UART_INITED 1
|
||||
#define UART_NUMBER 5
|
||||
|
||||
struct uart_irq_t {
|
||||
uart_irq_handler handler;
|
||||
uint32_t id;
|
||||
};
|
||||
|
||||
static const PinMap PinMap_UART_TX[] = {
|
||||
{MCC_TX , UART_0, 0},
|
||||
{USBTX , UART_1, 0},
|
||||
{SH0_TX , UART_2, ALTERNATE_FUNC},
|
||||
{SH1_TX , UART_3, ALTERNATE_FUNC},
|
||||
{XB_TX , UART_4, ALTERNATE_FUNC},
|
||||
{NC , NC , 0}
|
||||
{MCC_TX, UART_0, 0},
|
||||
{USBTX, UART_1, 0},
|
||||
{SH0_TX, UART_2, ALTERNATE_FUNC},
|
||||
{SH1_TX, UART_3, ALTERNATE_FUNC},
|
||||
{XB_TX, UART_4, ALTERNATE_FUNC},
|
||||
{NC, NC, 0}
|
||||
};
|
||||
|
||||
static const PinMap PinMap_UART_RX[] = {
|
||||
{MCC_RX , UART_0, 0},
|
||||
{USBRX , UART_1, 0},
|
||||
{SH0_RX , UART_2, ALTERNATE_FUNC},
|
||||
{SH1_RX , UART_3, ALTERNATE_FUNC},
|
||||
{XB_RX , UART_4, ALTERNATE_FUNC},
|
||||
{NC , NC , 0}
|
||||
{MCC_RX, UART_0, 0},
|
||||
{USBRX, UART_1, 0},
|
||||
{SH0_RX, UART_2, ALTERNATE_FUNC},
|
||||
{SH1_RX, UART_3, ALTERNATE_FUNC},
|
||||
{XB_RX, UART_4, ALTERNATE_FUNC},
|
||||
{NC, NC, 0}
|
||||
};
|
||||
|
||||
#define UART_NUM 5
|
||||
/* Handlers registered */
|
||||
static struct uart_irq_t uart_irq[UART_NUMBER];
|
||||
|
||||
static uart_irq_handler irq_handler;
|
||||
|
||||
int stdio_uart_inited = 0;
|
||||
/* Global variables needed for mbed */
|
||||
int stdio_uart_inited = STDIO_UART_NOT_INITED;
|
||||
serial_t stdio_uart;
|
||||
|
||||
struct serial_global_data_s {
|
||||
uint32_t serial_irq_id;
|
||||
gpio_t sw_rts, sw_cts;
|
||||
uint8_t count, rx_irq_set_flow, rx_irq_set_api;
|
||||
};
|
||||
/*
|
||||
* Fill the serial_obj structure with good elements.
|
||||
*/
|
||||
static uint32_t fill_serial_object(struct serial_s *serial_obj, PinName tx,
|
||||
PinName rx)
|
||||
{
|
||||
UARTName uart_peripheral;
|
||||
|
||||
static struct serial_global_data_s uart_data[UART_NUM];
|
||||
if (serial_obj == NULL) {
|
||||
error("serial_s structure is NULL");
|
||||
return 1;
|
||||
}
|
||||
|
||||
uart_peripheral = pinmap_merge(pinmap_peripheral(tx, PinMap_UART_TX),
|
||||
pinmap_peripheral(rx, PinMap_UART_RX));
|
||||
|
||||
switch (uart_peripheral) {
|
||||
#ifdef ARM_UART0
|
||||
case UART_0:
|
||||
serial_obj->uart = &ARM_UART0_DEV;
|
||||
serial_obj->index = UART_0;
|
||||
serial_obj->irq_number = UART0_IRQn;
|
||||
/* Fill stdio_uart global variable with these settings */
|
||||
memcpy(&stdio_uart, serial_obj, sizeof(struct serial_s));
|
||||
stdio_uart_inited = STDIO_UART_INITED;
|
||||
return 0;
|
||||
#endif /* ARM_UART0 */
|
||||
#ifdef ARM_UART1
|
||||
case UART_1:
|
||||
serial_obj->uart = &ARM_UART1_DEV;
|
||||
serial_obj->index = UART_1;
|
||||
serial_obj->irq_number = UART1_IRQn;
|
||||
return 0;
|
||||
#endif /* ARM_UART1 */
|
||||
#ifdef ARM_UART2
|
||||
case UART_2:
|
||||
serial_obj->uart = &ARM_UART2_DEV;
|
||||
serial_obj->index = UART_2;
|
||||
serial_obj->irq_number = UART2_IRQn;
|
||||
return 0;
|
||||
#endif /* ARM_UART2 */
|
||||
#ifdef ARM_UART3
|
||||
case UART_3:
|
||||
serial_obj->uart = &ARM_UART3_DEV;
|
||||
serial_obj->index = UART_3;
|
||||
serial_obj->irq_number = UART3_IRQn;
|
||||
return 0;
|
||||
#endif /* ARM_UART3 */
|
||||
#ifdef ARM_UART4
|
||||
case UART_4:
|
||||
serial_obj->uart = &ARM_UART4_DEV;
|
||||
serial_obj->index = UART_4;
|
||||
serial_obj->irq_number = UART4_IRQn;
|
||||
return 0;
|
||||
#endif /* ARM_UART4 */
|
||||
default:
|
||||
error("can not assign a valid UART peripheral to TX and RX pins given");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
void serial_init(serial_t *obj, PinName tx, PinName rx)
|
||||
{
|
||||
uint32_t uart_ctrl = 0;
|
||||
|
||||
/* Determine the UART to use */
|
||||
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 ((int)uart == NC) {
|
||||
error("Serial pinout mapping failed");
|
||||
if (fill_serial_object(obj, tx, rx) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
obj->uart = (CMSDK_UART_TypeDef *)uart;
|
||||
|
||||
if (tx != NC) {
|
||||
uart_ctrl = 0x01; /* TX enable */
|
||||
}
|
||||
if (rx != NC) {
|
||||
uart_ctrl |= 0x02; /* RX enable */
|
||||
}
|
||||
|
||||
switch (uart) {
|
||||
case UART_0:
|
||||
CMSDK_UART0->CTRL = uart_ctrl;
|
||||
obj->index = 0;
|
||||
break;
|
||||
case UART_1:
|
||||
CMSDK_UART1->CTRL = uart_ctrl;
|
||||
obj->index = 1;
|
||||
break;
|
||||
case UART_2:
|
||||
CMSDK_UART2->CTRL = 0;
|
||||
obj->index = 2;
|
||||
pin_function(tx, ALTERNATE_FUNC);
|
||||
pin_function(rx, ALTERNATE_FUNC);
|
||||
CMSDK_UART2->CTRL = uart_ctrl;
|
||||
break;
|
||||
case UART_3:
|
||||
CMSDK_UART3->CTRL = 0;
|
||||
obj->index = 3;
|
||||
pin_function(tx, ALTERNATE_FUNC);
|
||||
pin_function(rx, ALTERNATE_FUNC);
|
||||
CMSDK_UART3->CTRL = uart_ctrl;
|
||||
break;
|
||||
case UART_4:
|
||||
CMSDK_UART4->CTRL = 0;
|
||||
obj->index = 4;
|
||||
pin_function(tx, ALTERNATE_FUNC);
|
||||
pin_function(rx, ALTERNATE_FUNC);
|
||||
CMSDK_UART4->CTRL = uart_ctrl;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Set default baud rate and format */
|
||||
serial_baud(obj, 9600);
|
||||
(void)arm_uart_init(obj->uart, SystemCoreClock);
|
||||
|
||||
/*
|
||||
* The CMSDK APB UART doesn't have support for flow control.
|
||||
* Ref. DDI0479C_cortex_m_system_design_kit_r1p0_trm.pdf
|
||||
* If tx and rx pins are not linked to a GPIO (like for UART0),
|
||||
* pin_function will have no effect.
|
||||
*/
|
||||
uart_data[obj->index].sw_rts.pin_number = NC;
|
||||
uart_data[obj->index].sw_cts.pin_number = NC;
|
||||
|
||||
if (uart == STDIO_UART) {
|
||||
stdio_uart_inited = 1;
|
||||
memcpy(&stdio_uart, obj, sizeof(serial_t));
|
||||
}
|
||||
|
||||
/* Clear UART */
|
||||
serial_clear(obj);
|
||||
pin_function(tx, pinmap_function(tx, PinMap_UART_TX));
|
||||
pin_function(rx, pinmap_function(rx, PinMap_UART_RX));
|
||||
}
|
||||
|
||||
void serial_free(serial_t *obj)
|
||||
{
|
||||
uart_data[obj->index].serial_irq_id = 0;
|
||||
uart_irq[obj->index].id = 0;
|
||||
uart_irq[obj->index].handler = 0;
|
||||
}
|
||||
|
||||
void serial_baud(serial_t *obj, int baudrate)
|
||||
{
|
||||
/*
|
||||
* The MPS2 has a simple divider to control the baud rate.
|
||||
* The formula is:
|
||||
* Baudrate = PCLK / BAUDDIV where PCLK = SystemCoreClock and
|
||||
* BAUDDIV is the desire baudrate
|
||||
*
|
||||
* So, if the desired baud rate is 9600 the calculation will be:
|
||||
* Baudrate = SystemCoreClock / 9600;
|
||||
*/
|
||||
|
||||
/* Check to see if minimum baud value entered */
|
||||
int baudrate_div = 0;
|
||||
|
||||
if (baudrate == 0) {
|
||||
error("Invalid baudrate value");
|
||||
return;
|
||||
if (arm_uart_set_baudrate(obj->uart, (uint32_t)baudrate) !=
|
||||
ARM_UART_ERR_NONE) {
|
||||
error("Invalid baudrate value or uart not initialized");
|
||||
}
|
||||
|
||||
baudrate_div = SystemCoreClock / baudrate;
|
||||
|
||||
if (baudrate >= 16) {
|
||||
switch ((int)obj->uart) {
|
||||
case UART_0:
|
||||
CMSDK_UART0->BAUDDIV = baudrate_div;
|
||||
break;
|
||||
case UART_1:
|
||||
CMSDK_UART1->BAUDDIV = baudrate_div;
|
||||
break;
|
||||
case UART_2:
|
||||
CMSDK_UART2->BAUDDIV = baudrate_div;
|
||||
break;
|
||||
case UART_3:
|
||||
CMSDK_UART3->BAUDDIV = baudrate_div;
|
||||
break;
|
||||
case UART_4:
|
||||
CMSDK_UART4->BAUDDIV = baudrate_div;
|
||||
break;
|
||||
default:
|
||||
error("Invalid uart object");
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
error("Invalid baudrate value");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void serial_format(serial_t *obj, int data_bits,
|
||||
|
@ -204,138 +168,160 @@ void serial_format(serial_t *obj, int data_bits,
|
|||
/******************************************************************************
|
||||
* INTERRUPTS HANDLING
|
||||
******************************************************************************/
|
||||
static inline void uart_irq(uint32_t intstatus, uint32_t index,
|
||||
CMSDK_UART_TypeDef *puart)
|
||||
#ifdef ARM_UART0
|
||||
void UART0_IRQHandler()
|
||||
{
|
||||
SerialIrq irq_type;
|
||||
|
||||
switch (intstatus) {
|
||||
case 1:
|
||||
irq_type = TxIrq;
|
||||
enum arm_uart_irq_t irq = arm_uart_get_interrupt_status(&ARM_UART0_DEV);
|
||||
arm_uart_clear_interrupt(&ARM_UART0_DEV, irq);
|
||||
if(uart_irq[UART_0].handler) {
|
||||
switch(irq) {
|
||||
case ARM_UART_IRQ_RX:
|
||||
uart_irq[UART_0].handler(uart_irq[UART_0].id, RxIrq);
|
||||
break;
|
||||
case 2:
|
||||
irq_type = RxIrq;
|
||||
case ARM_UART_IRQ_TX:
|
||||
uart_irq[UART_0].handler(uart_irq[UART_0].id, TxIrq);
|
||||
break;
|
||||
case ARM_UART_IRQ_COMBINED:
|
||||
uart_irq[UART_0].handler(uart_irq[UART_0].id, RxIrq);
|
||||
uart_irq[UART_0].handler(uart_irq[UART_0].id, TxIrq);
|
||||
break;
|
||||
case ARM_UART_IRQ_NONE:
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if ((RxIrq == irq_type) && (NC != uart_data[index].sw_rts.pin_number)) {
|
||||
gpio_write(&uart_data[index].sw_rts, 1);
|
||||
/* Disable interrupt if it wasn't enabled by the application */
|
||||
if (!uart_data[index].rx_irq_set_api) {
|
||||
/* Disable Rx interrupt */
|
||||
puart->CTRL &= ~(CMSDK_UART_CTRL_RXIRQEN_Msk);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* ARM_UART0 */
|
||||
|
||||
if (uart_data[index].serial_irq_id != 0) {
|
||||
if ((irq_type != RxIrq) || (uart_data[index].rx_irq_set_api)) {
|
||||
irq_handler(uart_data[index].serial_irq_id, irq_type);
|
||||
#ifdef ARM_UART1
|
||||
void UART1_IRQHandler()
|
||||
{
|
||||
enum arm_uart_irq_t irq = arm_uart_get_interrupt_status(&ARM_UART1_DEV);
|
||||
arm_uart_clear_interrupt(&ARM_UART1_DEV, irq);
|
||||
if(uart_irq[UART_1].handler) {
|
||||
switch(irq) {
|
||||
case ARM_UART_IRQ_RX:
|
||||
uart_irq[UART_1].handler(uart_irq[UART_1].id, RxIrq);
|
||||
break;
|
||||
case ARM_UART_IRQ_TX:
|
||||
uart_irq[UART_1].handler(uart_irq[UART_1].id, TxIrq);
|
||||
break;
|
||||
case ARM_UART_IRQ_COMBINED:
|
||||
uart_irq[UART_1].handler(uart_irq[UART_1].id, RxIrq);
|
||||
uart_irq[UART_1].handler(uart_irq[UART_1].id, TxIrq);
|
||||
break;
|
||||
case ARM_UART_IRQ_NONE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* ARM_UART1 */
|
||||
|
||||
if (irq_type == TxIrq) {
|
||||
/* Clear the TX interrupt Flag */
|
||||
puart->INTCLEAR |= 0x01;
|
||||
} else {
|
||||
/* Clear the Rx interupt Flag */
|
||||
puart->INTCLEAR |= 0x02;
|
||||
#ifdef ARM_UART2
|
||||
void UART2_IRQHandler()
|
||||
{
|
||||
enum arm_uart_irq_t irq = arm_uart_get_interrupt_status(&ARM_UART2_DEV);
|
||||
arm_uart_clear_interrupt(&ARM_UART2_DEV, irq);
|
||||
if(uart_irq[UART_2].handler) {
|
||||
switch(irq) {
|
||||
case ARM_UART_IRQ_RX:
|
||||
uart_irq[UART_2].handler(uart_irq[UART_2].id, RxIrq);
|
||||
break;
|
||||
case ARM_UART_IRQ_TX:
|
||||
uart_irq[UART_2].handler(uart_irq[UART_2].id, TxIrq);
|
||||
break;
|
||||
case ARM_UART_IRQ_COMBINED:
|
||||
uart_irq[UART_2].handler(uart_irq[UART_2].id, RxIrq);
|
||||
uart_irq[UART_2].handler(uart_irq[UART_2].id, TxIrq);
|
||||
break;
|
||||
case ARM_UART_IRQ_NONE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* ARM_UART2 */
|
||||
|
||||
void uart0_irq()
|
||||
#ifdef ARM_UART3
|
||||
void UART3_IRQHandler()
|
||||
{
|
||||
uart_irq(CMSDK_UART0->INTSTATUS & 0x3, 0, (CMSDK_UART_TypeDef*)CMSDK_UART0);
|
||||
enum arm_uart_irq_t irq = arm_uart_get_interrupt_status(&ARM_UART3_DEV);
|
||||
arm_uart_clear_interrupt(&ARM_UART3_DEV, irq);
|
||||
if(uart_irq[UART_3].handler) {
|
||||
switch(irq) {
|
||||
case ARM_UART_IRQ_RX:
|
||||
uart_irq[UART_3].handler(uart_irq[UART_3].id, RxIrq);
|
||||
break;
|
||||
case ARM_UART_IRQ_TX:
|
||||
uart_irq[UART_3].handler(uart_irq[UART_3].id, TxIrq);
|
||||
break;
|
||||
case ARM_UART_IRQ_COMBINED:
|
||||
uart_irq[UART_3].handler(uart_irq[UART_3].id, RxIrq);
|
||||
uart_irq[UART_3].handler(uart_irq[UART_3].id, TxIrq);
|
||||
break;
|
||||
case ARM_UART_IRQ_NONE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* ARM_UART3 */
|
||||
|
||||
void uart1_irq()
|
||||
#ifdef ARM_UART4
|
||||
void UART4_IRQHandler()
|
||||
{
|
||||
uart_irq(CMSDK_UART1->INTSTATUS & 0x3, 1, (CMSDK_UART_TypeDef*)CMSDK_UART1);
|
||||
}
|
||||
|
||||
void uart2_irq()
|
||||
{
|
||||
uart_irq(CMSDK_UART2->INTSTATUS & 0x3, 2, (CMSDK_UART_TypeDef*)CMSDK_UART2);
|
||||
}
|
||||
|
||||
void uart3_irq() {
|
||||
uart_irq(CMSDK_UART3->INTSTATUS & 0x3, 3, (CMSDK_UART_TypeDef*)CMSDK_UART3);
|
||||
}
|
||||
|
||||
void uart4_irq() {
|
||||
uart_irq(CMSDK_UART4->INTSTATUS & 0x3, 4, (CMSDK_UART_TypeDef*)CMSDK_UART4);
|
||||
enum arm_uart_irq_t irq = arm_uart_get_interrupt_status(&ARM_UART4_DEV);
|
||||
arm_uart_clear_interrupt(&ARM_UART4_DEV, irq);
|
||||
if(uart_irq[UART_4].handler) {
|
||||
switch(irq) {
|
||||
case ARM_UART_IRQ_RX:
|
||||
uart_irq[UART_4].handler(uart_irq[UART_4].id, RxIrq);
|
||||
break;
|
||||
case ARM_UART_IRQ_TX:
|
||||
uart_irq[UART_4].handler(uart_irq[UART_4].id, TxIrq);
|
||||
break;
|
||||
case ARM_UART_IRQ_COMBINED:
|
||||
uart_irq[UART_4].handler(uart_irq[UART_4].id, RxIrq);
|
||||
uart_irq[UART_4].handler(uart_irq[UART_4].id, TxIrq);
|
||||
break;
|
||||
case ARM_UART_IRQ_NONE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* ARM_UART4 */
|
||||
|
||||
void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id)
|
||||
{
|
||||
irq_handler = handler;
|
||||
uart_data[obj->index].serial_irq_id = id;
|
||||
}
|
||||
|
||||
static void serial_irq_set_internal(serial_t *obj, SerialIrq irq, uint32_t enable)
|
||||
{
|
||||
|
||||
IRQn_Type irq_n = (IRQn_Type)0;
|
||||
uint32_t vector = 0;
|
||||
|
||||
switch ((int)obj->uart) {
|
||||
case UART_0:
|
||||
irq_n = UART0_IRQn;
|
||||
vector = (uint32_t)&uart0_irq;
|
||||
break;
|
||||
case UART_1:
|
||||
irq_n = UART1_IRQn;
|
||||
vector = (uint32_t)&uart1_irq;
|
||||
break;
|
||||
case UART_2:
|
||||
irq_n = UART2_IRQn;
|
||||
vector = (uint32_t)&uart2_irq;
|
||||
break;
|
||||
case UART_3:
|
||||
irq_n = UART3_IRQn;
|
||||
vector = (uint32_t)&uart3_irq;
|
||||
break;
|
||||
case UART_4:
|
||||
irq_n = UART4_IRQn;
|
||||
vector = (uint32_t)&uart4_irq;
|
||||
break;
|
||||
}
|
||||
|
||||
if (enable) {
|
||||
if (irq == TxIrq) {
|
||||
/* Set TX interrupt enable in CTRL REG */
|
||||
obj->uart->CTRL |= CMSDK_UART_CTRL_TXIRQEN_Msk;
|
||||
} else {
|
||||
/* Set Rx interrupt on in CTRL REG */
|
||||
obj->uart->CTRL |= CMSDK_UART_CTRL_RXIRQEN_Msk;
|
||||
}
|
||||
NVIC_SetVector(irq_n, vector);
|
||||
NVIC_EnableIRQ(irq_n);
|
||||
} else if ((irq == TxIrq) ||
|
||||
(uart_data[obj->index].rx_irq_set_api
|
||||
+ uart_data[obj->index].rx_irq_set_flow == 0)) {
|
||||
/* Disable IRQ */
|
||||
int all_disabled = 0;
|
||||
SerialIrq other_irq = (irq == RxIrq) ? (TxIrq) : (RxIrq);
|
||||
|
||||
obj->uart->CTRL &= ~(1 << (irq + 2));
|
||||
|
||||
all_disabled = (obj->uart->CTRL & (1 << (other_irq + 2))) == 0;
|
||||
|
||||
if (all_disabled) {
|
||||
NVIC_DisableIRQ(irq_n);
|
||||
}
|
||||
}
|
||||
uart_irq[obj->index].handler = handler;
|
||||
uart_irq[obj->index].id = id;
|
||||
}
|
||||
|
||||
void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable)
|
||||
{
|
||||
if (RxIrq == irq) {
|
||||
uart_data[obj->index].rx_irq_set_api = enable;
|
||||
switch (irq) {
|
||||
case RxIrq:
|
||||
if (enable) {
|
||||
NVIC_EnableIRQ(obj->irq_number);
|
||||
(void)arm_uart_irq_rx_enable(obj->uart);
|
||||
} else {
|
||||
arm_uart_irq_rx_disable(obj->uart);
|
||||
NVIC_DisableIRQ(obj->irq_number);
|
||||
}
|
||||
break;
|
||||
case TxIrq:
|
||||
if (enable) {
|
||||
NVIC_EnableIRQ(obj->irq_number);
|
||||
(void)arm_uart_irq_tx_enable(obj->uart);
|
||||
} else {
|
||||
arm_uart_irq_tx_disable(obj->uart);
|
||||
NVIC_DisableIRQ(obj->irq_number);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
serial_irq_set_internal(obj, irq, enable);
|
||||
/* default: not added to force to cover all enumeration cases */
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
|
@ -343,34 +329,33 @@ void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable)
|
|||
******************************************************************************/
|
||||
int serial_getc(serial_t *obj)
|
||||
{
|
||||
while (serial_readable(obj) == 0) {
|
||||
/* NOP */
|
||||
}
|
||||
uint8_t byte = 0;
|
||||
|
||||
return obj->uart->DATA;
|
||||
while (!serial_readable(obj)){};
|
||||
(void)arm_uart_read(obj->uart, &byte);
|
||||
|
||||
return (int)byte;
|
||||
}
|
||||
|
||||
void serial_putc(serial_t *obj, int c)
|
||||
{
|
||||
while (serial_writable(obj)) {
|
||||
/* NOP */
|
||||
}
|
||||
obj->uart->DATA = c;
|
||||
while (!serial_writable(obj)){};
|
||||
(void)arm_uart_write(obj->uart, (int)c);
|
||||
}
|
||||
|
||||
int serial_readable(serial_t *obj)
|
||||
{
|
||||
return obj->uart->STATE & 0x2;
|
||||
return arm_uart_rx_ready(obj->uart);
|
||||
}
|
||||
|
||||
int serial_writable(serial_t *obj)
|
||||
{
|
||||
return obj->uart->STATE & 0x1;
|
||||
return arm_uart_tx_ready(obj->uart);
|
||||
}
|
||||
|
||||
void serial_clear(serial_t *obj)
|
||||
{
|
||||
obj->uart->DATA = 0x00;
|
||||
(void)arm_uart_write(obj->uart, 0x00);
|
||||
}
|
||||
|
||||
void serial_pinout_tx(PinName tx)
|
||||
|
@ -395,7 +380,8 @@ void serial_break_clear(serial_t *obj)
|
|||
*/
|
||||
error("serial_break_clear function not supported");
|
||||
}
|
||||
void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, PinName txflow)
|
||||
void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow,
|
||||
PinName txflow)
|
||||
{
|
||||
/*
|
||||
* The CMSDK APB UART doesn't have support for flow control.
|
||||
|
|
Loading…
Reference in New Issue