Created ADUCM UARTv1 unifier header

git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@13495 27425a3e-05d8-49a3-a47f-9c15f0e5edd8
This commit is contained in:
Rocco Marco Guglielmi 2020-04-01 08:45:01 +00:00
parent f18973f964
commit 5395751f6c
3 changed files with 371 additions and 56 deletions

View File

@ -0,0 +1,210 @@
/*
ChibiOS - Copyright (C) 2006..2020 Rocco Marco Guglielmi
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 UARTv1/aducm_uart.h
* @brief ADUCM UART units common header.
* @note This file requires definitions from the ADI ADUCM header file.
*
* @{
*/
#ifndef ADUCM_UART_H
#define ADUCM_UART_H
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
/* Discarded definitions from the ADI headers, the Serial/UART drivers use its
own definitions in order to have an unified handling for all devices.
Unfortunately the ADI headers have no uniform definitions for the same
objects across the various sub-families.*/
#if !defined(pADI_UART0)
#define pADI_UART0 pADI_UART
#endif
/**
* @name UART ports definitions
* @{
*/
#define UART0 ((aducm_uart_t *)pADI_UART0)
#define UART1 ((aducm_uart_t *)pADI_UART1)
/** @} */
/**
* @name UART Data register bits definitions
* @{
*/
#define ADUCM_UART_DATA_MASK 0x00FFU
/** @} */
/**
* @name UART Interrupt Enable register bits definitions
* @{
*/
#define ADUCM_UART_IEN_MASK 0x003FU
#define ADUCM_UART_IEN_ERBFI (1U << 0)
#define ADUCM_UART_IEN_ETBEI (1U << 1)
#define ADUCM_UART_IEN_ELSI (1U << 2)
#define ADUCM_UART_IEN_EDSSI (1U << 3)
#define ADUCM_UART_IEN_EDMAT (1U << 4)
#define ADUCM_UART_IEN_EDMAR (1U << 5)
/** @} */
/**
* @name UART Interrupt Identification register bits definitions
* @{
*/
#define ADUCM_UART_IIR_MASK 0x0007U
#define ADUCM_UART_IIR_NINT (1U << 0)
#define ADUCM_UART_IIR_STA_MODEM (0U << 1)
#define ADUCM_UART_IIR_STA_TX_EMPTY (1U << 1)
#define ADUCM_UART_IIR_STA_RX_FULL (2U << 1)
#define ADUCM_UART_IIR_STA_LINE (3U << 1)
/** @} */
/**
* @name UART Line Control register bits definitions
* @{
*/
#define ADUCM_UART_LCR_MASK 0x007FU
#define ADUCM_UART_LCR_WLS_5_BITS (0U << 0)
#define ADUCM_UART_LCR_WLS_6_BITS (1U << 0)
#define ADUCM_UART_LCR_WLS_7_BITS (2U << 0)
#define ADUCM_UART_LCR_WLS_8_BITS (3U << 0)
#define ADUCM_UART_LCR_STOP (1U << 2)
#define ADUCM_UART_LCR_PEN (1U << 3)
#define ADUCM_UART_LCR_EPS (1U << 4)
#define ADUCM_UART_LCR_SP (1U << 5)
#define ADUCM_UART_LCR_BRK (1U << 6)
/** @} */
/**
* @name UART Modem Control register bits definitions
* @{
*/
#define ADUCM_UART_MCR_MASK 0x0013U
#define ADUCM_UART_MCR_DTR (1U << 0)
#define ADUCM_UART_MCR_RTS (1U << 1)
#define ADUCM_UART_MCR_LOOPBACK (1U << 4)
/** @} */
/**
* @name UART Line Status register bits definitions
* @{
*/
#define ADUCM_UART_LSR_MASK 0x007FU
#define ADUCM_UART_LSR_DR (1U << 0)
#define ADUCM_UART_LSR_OE (1U << 1)
#define ADUCM_UART_LSR_PE (1U << 2)
#define ADUCM_UART_LSR_FE (1U << 3)
#define ADUCM_UART_LSR_BI (1U << 4)
#define ADUCM_UART_LSR_THRE (1U << 5)
#define ADUCM_UART_LSR_TEMT (1U << 6)
/** @} */
/**
* @name UART Modem Status register bits definitions
* @{
*/
#define ADUCM_UART_MSR_MASK 0x00FFU
#define ADUCM_UART_MSR_DCTS (1U << 0)
#define ADUCM_UART_MSR_DDSR (1U << 1)
#define ADUCM_UART_MSR_TERI (1U << 2)
#define ADUCM_UART_MSR_DDCD (1U << 3)
#define ADUCM_UART_MSR_CTS (1U << 4)
#define ADUCM_UART_MSR_DSR (1U << 5)
#define ADUCM_UART_MSR_RI (1U << 6)
#define ADUCM_UART_MSR_DCD (1U << 7)
/** @} */
/**
* @name UART Fractional Baud Rate Divider register bits definitions
* @{
*/
#define ADUCM_UART_FBR_MASK 0x9FFFU
#define ADUCM_UART_FBR_DIVN_MASK 0x07FFU
#define ADUCM_UART_FBR_DIVN(n) ((n) << 0)
#define ADUCM_UART_FBR_DIVM_MASK 0x1800U
#define ADUCM_UART_FBR_DIVM(m) ((m) << 11)
#define ADUCM_UART_FBR_ENABLE (1U << 15)
/** @} */
/**
* @name UART Divider register bits definitions
* @{
*/
#define ADUCM_UART_DIV_MASK 0xFFFFU
/** @} */
/**
* @name UART Control register bits definitions
* @{
*/
#define ADUCM_UART_CTL_MASK 0x0001U
#define ADUCM_UART_CTL_DISABLE (1U << 0)
#define ADUCM_UART_CTL_ENABLE (0U << 0)
/** @} */
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/**
* @brief ADUCM UARTv1 registers block.
*/
typedef struct {
volatile uint32_t DATA;
volatile uint32_t IEN;
volatile uint32_t IIR;
volatile uint32_t LCR;
volatile uint32_t MCR;
volatile uint32_t LSR;
volatile uint32_t MSR;
volatile uint32_t SCR;
volatile uint32_t FCR;
volatile uint32_t FBR;
volatile uint32_t DIV;
volatile uint32_t LCR2;
volatile uint32_t CTL;
volatile uint32_t RFC;
volatile uint32_t TFC;
volatile uint32_t RSC;
volatile uint32_t ACR;
volatile uint32_t ASRL;
volatile uint32_t ASRH;
} aducm_uart_t;
/*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#endif /* ADUCM_UART_H */
/** @} */

View File

@ -30,23 +30,20 @@
/* Driver local definitions. */
/*===========================================================================*/
/**
* @name ADUCM UART Fractional BR Divider register's bitfields.
* @{
*/
#define ADUCM_COMFBR_ENABLE COMFBR_ENABLE_EN
#define ADUCM_COMFBR_DIVM(m) ((m) << 11U)
#define ADUCM_COMFBR_DIVN(n) ((n) << 0U)
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
/** @brief USART1 serial driver identifier.*/
#if (ADUCM_SERIAL_USE_UART0 == TRUE) || defined(__DOXYGEN__)
/** @brief UART0 serial driver identifier.*/
#if ADUCM_SERIAL_USE_UART0 || defined(__DOXYGEN__)
SerialDriver SD0;
#endif
/** @brief UART0 serial driver identifier.*/
#if ADUCM_SERIAL_USE_UART1 || defined(__DOXYGEN__)
SerialDriver SD1;
#endif
/*===========================================================================*/
/* Driver local variables and types. */
/*===========================================================================*/
@ -56,7 +53,7 @@ SerialDriver SD0;
*/
static const SerialConfig default_config = {
SERIAL_DEFAULT_BITRATE,
COMLCR_WLS_8BITS
ADUCM_UART_LCR_WLS_8_BITS
};
#if ADUCM_SERIAL_USE_UART0 || defined(__DOXYGEN__)
@ -67,6 +64,14 @@ static uint8_t sd_in_buf0[ADUCM_SERIAL_UART0_IN_BUF_SIZE];
static uint8_t sd_out_buf0[ADUCM_SERIAL_UART0_OUT_BUF_SIZE];
#endif
#if ADUCM_SERIAL_USE_UART1 || defined(__DOXYGEN__)
/** @brief Input buffer for SD1.*/
static uint8_t sd_in_buf1[ADUCM_SERIAL_UART1_IN_BUF_SIZE];
/** @brief Output buffer for SD1.*/
static uint8_t sd_out_buf1[ADUCM_SERIAL_UART1_OUT_BUF_SIZE];
#endif
/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/
@ -83,7 +88,7 @@ static void uart_init(SerialDriver *sdp, const SerialConfig *config) {
uint32_t comdiv, divn, divm;
/* Resetting the UART state machine. */
sdp->uart->COMCON = COMCON_DISABLE_EN;
sdp->uart->CTL = ADUCM_UART_CTL_DISABLE;
/* Baud rate setting.*/
osalDbgAssert(((sdp->clock / 32U) > config->speed),
@ -120,17 +125,17 @@ static void uart_init(SerialDriver *sdp, const SerialConfig *config) {
osalDbgAssert((divn <= 2047), "invalid divn value");
sdp->uart->COMFBR = ADUCM_COMFBR_ENABLE | ADUCM_COMFBR_DIVM(divm) |
ADUCM_COMFBR_DIVN(divn);
sdp->uart->FBR = ADUCM_UART_FBR_ENABLE | ADUCM_UART_FBR_DIVM(divm) |
ADUCM_UART_FBR_DIVN(divn);
sdp->uart->COMDIV = comdiv;
sdp->uart->DIV = comdiv;
/* Line and modem configurations*/
sdp->uart->COMLCR = config->lcr;
sdp->uart->LCR = config->lcr;
sdp->uart->COMIEN = COMIEN_EDMAR_DIS | COMIEN_EDMAT_DIS | COMIEN_EDSSI_EN |
COMIEN_ELSI_EN | COMIEN_ETBEI_EN | COMIEN_ERBFI_EN;
sdp->uart->COMCON = COMCON_DISABLE_DIS;
sdp->uart->IEN = ADUCM_UART_IEN_EDSSI | ADUCM_UART_IEN_ELSI |
ADUCM_UART_IEN_ETBEI | ADUCM_UART_IEN_ERBFI;
sdp->uart->CTL = ADUCM_UART_CTL_ENABLE;
}
/**
@ -141,8 +146,8 @@ static void uart_init(SerialDriver *sdp, const SerialConfig *config) {
*/
static void uart_deinit(SerialDriver *sdp) {
sdp->uart->COMIEN = 0;
sdp->uart->COMCON = COMCON_DISABLE_EN;
sdp->uart->IEN = 0;
sdp->uart->CTL = ADUCM_UART_CTL_DISABLE;
}
/**
@ -154,11 +159,11 @@ static void uart_deinit(SerialDriver *sdp) {
static void set_error(SerialDriver *sdp, uint32_t lsr) {
eventflags_t sts = 0;
if (lsr & COMLSR_OE)
if (lsr & ADUCM_UART_LSR_OE)
sts |= SD_OVERRUN_ERROR;
if (lsr & COMLSR_PE)
if (lsr & ADUCM_UART_LSR_PE)
sts |= SD_PARITY_ERROR;
if (lsr & COMLSR_FE)
if (lsr & ADUCM_UART_LSR_FE)
sts |= SD_FRAMING_ERROR;
osalSysLockFromISR();
chnAddFlagsI(sdp, sts);
@ -169,7 +174,15 @@ static void set_error(SerialDriver *sdp, uint32_t lsr) {
static void notify0(io_queue_t *qp) {
(void)qp;
pADI_UART->COMIEN |= COMIEN_ETBEI_EN;
UART0->IEN |= ADUCM_UART_IEN_ETBEI;
}
#endif
#if ADUCM_SERIAL_USE_UART1 || defined(__DOXYGEN__)
static void notify1(io_queue_t *qp) {
(void)qp;
UART1->IEN |= ADUCM_UART_IEN_ETBEI;
}
#endif
@ -196,6 +209,24 @@ OSAL_IRQ_HANDLER(ADUCM_UART0_HANDLER) {
}
#endif
#if ADUCM_SERIAL_USE_UART1 || defined(__DOXYGEN__)
#if !defined(ADUCM_UART1_HANDLER)
#error "ADUCM_UART1_HANDLER not defined"
#endif
/**
* @brief UART1 interrupt handler.
*
* @isr
*/
OSAL_IRQ_HANDLER(ADUCM_UART1_HANDLER) {
OSAL_IRQ_PROLOGUE();
sd_lld_serve_interrupt(&SD1);
OSAL_IRQ_EPILOGUE();
}
#endif
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
@ -207,15 +238,27 @@ OSAL_IRQ_HANDLER(ADUCM_UART0_HANDLER) {
*/
void sd_lld_init(void) {
#if ADUCM_SERIAL_USE_UART0 == TRUE
#if ADUCM_SERIAL_USE_UART0
sdObjectInit(&SD0);
iqObjectInit(&SD0.iqueue, sd_in_buf0, sizeof sd_in_buf0, NULL, &SD0);
oqObjectInit(&SD0.oqueue, sd_out_buf0, sizeof sd_out_buf0, notify0, &SD0);
SD0.uart = pADI_UART;
SD0.clock = ADUCM_UARTCLK;
SD0.uart = UART0;
SD0.clock = ADUCM_UART0CLK;
#if defined(ADUCM_SERIAL_UART0_PRIORITY)
nvicEnableVector(ADUCM_UART0_NUMBER, ADUCM_SERIAL_UART0_PRIORITY);
#endif
#endif
#if ADUCM_SERIAL_USE_UART1
sdObjectInit(&SD1);
iqObjectInit(&SD1.iqueue, sd_in_buf1, sizeof sd_in_buf1, NULL, &SD1);
oqObjectInit(&SD1.oqueue, sd_out_buf1, sizeof sd_out_buf1, notify1, &SD1);
SD1.uart = UART1;
SD1.clock = ADUCM_UART1CLK;
#if defined(ADUCM_SERIAL_UART1_PRIORITY)
nvicEnableVector(ADUCM_UART1_NUMBER, ADUCM_SERIAL_UART1_PRIORITY);
#endif
#endif
}
/**
@ -235,11 +278,17 @@ void sd_lld_start(SerialDriver *sdp, const SerialConfig *config) {
}
if (sdp->state == SD_STOP) {
#if ADUCM_SERIAL_USE_UART0 == TRUE
#if ADUCM_SERIAL_USE_UART0 && !ADUCM_HAS_CLK_AUTOGATE
if (&SD0 == sdp) {
ccEnableUART0();
}
#endif
#if ADUCM_SERIAL_USE_UART1 && !ADUCM_HAS_CLK_AUTOGATE
if (&SD1 == sdp) {
ccEnableUART1();
}
#endif
}
uart_init(sdp, config);
}
@ -259,12 +308,19 @@ void sd_lld_stop(SerialDriver *sdp) {
/* UART is de-initialized then clocks are disabled.*/
uart_deinit(sdp);
#if ADUCM_SERIAL_USE_UART0 == TRUE
#if ADUCM_SERIAL_USE_UART0 && !ADUCM_HAS_CLK_AUTOGATE
if (&SD0 == sdp) {
ccDisableUART0();
return;
}
#endif
#if ADUCM_SERIAL_USE_UART1 && !ADUCM_HAS_CLK_AUTOGATE
if (&SD1 == sdp) {
ccDisableUART1();
return;
}
#endif
}
}
@ -274,15 +330,15 @@ void sd_lld_stop(SerialDriver *sdp) {
* @param[in] sdp communication channel associated to the USART
*/
void sd_lld_serve_interrupt(SerialDriver *sdp) {
uint32_t irr = sdp->uart->COMIIR;
uint32_t ien = sdp->uart->COMIEN;
uint32_t irr = sdp->uart->IIR;
uint32_t ien = sdp->uart->IEN;
if(!(irr & COMIIR_NINT_MSK)) {
if(irr == COMIIR_STA_MODEMSTATUS) {
if(!(irr & ADUCM_UART_IIR_NINT)) {
if(irr == ADUCM_UART_IIR_STA_MODEM) {
volatile uint32_t msr;
/* Clearing the interrupt. */
msr = sdp->uart->COMMSR;
msr = sdp->uart->MSR;
(void) msr;
}
@ -292,12 +348,12 @@ void sd_lld_serve_interrupt(SerialDriver *sdp) {
an extra interrupt to serve.
2) FIFO mode is enabled on devices that support it, we need to empty
the FIFO.*/
while (irr & COMIIR_STA_RXBUFFULL) {
while (irr & ADUCM_UART_IIR_STA_RX_FULL) {
osalSysLockFromISR();
sdIncomingDataI(sdp, (uint8_t)sdp->uart->COMRX);
sdIncomingDataI(sdp, (uint8_t)sdp->uart->DATA);
osalSysUnlockFromISR();
irr = sdp->uart->COMIIR;
irr = sdp->uart->IIR;
}
/* Transmission buffer empty, note it is a while in order to handle two
@ -306,43 +362,38 @@ void sd_lld_serve_interrupt(SerialDriver *sdp) {
would cause an extra interrupt to serve.
2) FIFO mode is enabled on devices that support it, we need to fill
the FIFO.*/
if (ien & COMIEN_ETBEI) {
while (irr & COMIIR_STA_TXBUFEMPTY) {
if (ien & ADUCM_UART_IEN_ETBEI) {
while (irr & ADUCM_UART_IIR_STA_TX_EMPTY) {
msg_t b;
osalSysLockFromISR();
b = oqGetI(&sdp->oqueue);
if (b < MSG_OK) {
chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY);
sdp->uart->COMIEN = ien & ~COMIEN_ETBEI;
sdp->uart->IEN = ien & ~ADUCM_UART_IEN_ETBEI;
osalSysUnlockFromISR();
break;
}
sdp->uart->COMTX = b;
sdp->uart->DATA = b;
osalSysUnlockFromISR();
irr = sdp->uart->COMIIR;
irr = sdp->uart->IIR;
}
}
if(irr == COMIIR_STA_RXLINESTATUS) {
if(irr == ADUCM_UART_IIR_STA_LINE) {
uint32_t lsr;
/* Clearing the interrupt. */
lsr = sdp->uart->COMLSR;
lsr = sdp->uart->LSR;
/* Error handling. */
if(lsr & 0x0EU) {
set_error(sdp, lsr);
}
/* Error handling. */
if(lsr & COMLSR_TEMT) {
if(lsr & (ADUCM_UART_LSR_FE | ADUCM_UART_LSR_PE | ADUCM_UART_LSR_OE)) {
set_error(sdp, lsr);
}
/* Physical transmission end.*/
if (lsr & COMLSR_TEMT) {
if (lsr & ADUCM_UART_LSR_TEMT) {
osalSysLockFromISR();
if (oqIsEmptyI(&sdp->oqueue)) {
chnAddFlagsI(sdp, CHN_TRANSMISSION_END);

View File

@ -25,6 +25,8 @@
#ifndef HAL_SERIAL_LLD_H
#define HAL_SERIAL_LLD_H
#include "aducm_uart.h"
#if HAL_USE_SERIAL || defined(__DOXYGEN__)
/*===========================================================================*/
@ -57,6 +59,15 @@
#define ADUCM_SERIAL_USE_UART0 FALSE
#endif
/**
* @brief UART1 driver enable switch.
* @details If set to @p TRUE the support for UART1 is included.
* @note The default is @p FALSE.
*/
#if !defined(ADUCM_SERIAL_USE_UART1) || defined(__DOXYGEN__)
#define ADUCM_SERIAL_USE_UART1 FALSE
#endif
/**
* @brief UART0 interrupt priority level setting.
*/
@ -64,6 +75,13 @@
#define ADUCM_SERIAL_UART0_PRIORITY 12
#endif
/**
* @brief UART1 interrupt priority level setting.
*/
#if !defined(ADUCM_SERIAL_UART1_PRIORITY) || defined(__DOXYGEN__)
#define ADUCM_SERIAL_UART1_PRIORITY 12
#endif
/**
* @brief Input buffer size for UART0.
*/
@ -79,14 +97,47 @@
#endif
/** @} */
/**
* @brief Input buffer size for UART1.
*/
#if !defined(ADUCM_SERIAL_UART1_IN_BUF_SIZE) || defined(__DOXYGEN__)
#define ADUCM_SERIAL_UART1_IN_BUF_SIZE SERIAL_BUFFERS_SIZE
#endif
/**
* @brief Output buffer size for UART1.
*/
#if !defined(ADUCM_SERIAL_UART1_OUT_BUF_SIZE) || defined(__DOXYGEN__)
#define ADUCM_SERIAL_UART1_OUT_BUF_SIZE SERIAL_BUFFERS_SIZE
#endif
/** @} */
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
#if !ADUCM_SERIAL_USE_UART0
#if ADUCM_SERIAL_USE_UART0 && !ADUCM_HAS_UART0
#error "UART0 not present in the selected device"
#endif
#if ADUCM_SERIAL_USE_UART1 && !ADUCM_HAS_UART1
#error "UART1 not present in the selected device"
#endif
#if !ADUCM_SERIAL_USE_UART0 && !ADUCM_SERIAL_USE_UART1
#error "SERIAL driver activated but no UART peripheral assigned"
#endif
#if ADUCM_SERIAL_USE_UART0 && \
!OSAL_IRQ_IS_VALID_PRIORITY(ADUCM_SERIAL_UART0_PRIORITY)
#error "Invalid IRQ priority assigned to UART0"
#endif
#if ADUCM_SERIAL_USE_UART1 && \
!OSAL_IRQ_IS_VALID_PRIORITY(ADUCM_SERIAL_UART1_PRIORITY)
#error "Invalid IRQ priority assigned to UART1"
#endif
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
@ -124,7 +175,7 @@ typedef struct {
output_queue_t oqueue; \
/* End of the mandatory fields.*/ \
/* Pointer to the UART registers block.*/ \
ADI_UART_TypeDef *uart; \
aducm_uart_t *uart; \
/* Clock frequency for the associated UART.*/ \
uint32_t clock;
@ -136,9 +187,12 @@ typedef struct {
/* External declarations. */
/*===========================================================================*/
#if (ADUCM_SERIAL_USE_UART0 == TRUE) && !defined(__DOXYGEN__)
#if ADUCM_SERIAL_USE_UART0 && !defined(__DOXYGEN__)
extern SerialDriver SD0;
#endif
#if ADUCM_SERIAL_USE_UART1 && !defined(__DOXYGEN__)
extern SerialDriver SD1;
#endif
#ifdef __cplusplus
extern "C" {