From 8a3422f837a923e1cf1247a708ab2f9382c9690f Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Mon, 20 Mar 2017 11:21:32 -0600 Subject: [PATCH] XMC4xxx: Complete lowputc logic --- arch/arm/src/xmc4/chip/xmc4_usic.h | 40 ++-- arch/arm/src/xmc4/xmc4_lowputc.c | 296 ++++++++++++++++++++------ arch/arm/src/xmc4/xmc4_lowputc.h | 32 +-- arch/arm/src/xmc4/xmc4_serial.c | 164 +++++++------- arch/arm/src/xmc4/xmc4_usic.h | 23 +- configs/xmc4500-relax/include/board.h | 11 + 6 files changed, 383 insertions(+), 183 deletions(-) diff --git a/arch/arm/src/xmc4/chip/xmc4_usic.h b/arch/arm/src/xmc4/chip/xmc4_usic.h index 12d4bda2bc..462ac44c95 100644 --- a/arch/arm/src/xmc4/chip/xmc4_usic.h +++ b/arch/arm/src/xmc4/chip/xmc4_usic.h @@ -515,15 +515,16 @@ */ #define USIC_DXCR_DSEL_SHIFT (0) /* Bits 0-2: Data Selection for Input Signal */ -#define USIC_DXCR_DSEL_MASK (7 << USIC_DX0CR_DSEL_SHIFT) -# define USIC_DXCR_DSEL_DXA (0 << USIC_DX0CR_DSEL_SHIFT) /* Data input DXnA selected */ -# define USIC_DXCR_DSEL_DXB (1 << USIC_DX0CR_DSEL_SHIFT) /* Data input DXnB selected */ -# define USIC_DXCR_DSEL_DXC (2 << USIC_DX0CR_DSEL_SHIFT) /* Data input DXnC selected */ -# define USIC_DXCR_DSEL_DXD (3 << USIC_DX0CR_DSEL_SHIFT) /* Data input DXnD selected */ -# define USIC_DXCR_DSEL_DXE (4 << USIC_DX0CR_DSEL_SHIFT) /* Data input DXnE selected */ -# define USIC_DXCR_DSEL_DXF (5 << USIC_DX0CR_DSEL_SHIFT) /* Data input DXnF selected */ -# define USIC_DXCR_DSEL_DXG (6 << USIC_DX0CR_DSEL_SHIFT) /* Data input DXnG selected */ -# define USIC_DXCR_DSEL_ONE (7 << USIC_DX0CR_DSEL_SHIFT) /* Data input is always 1 */ +#define USIC_DXCR_DSEL_MASK (7 << USIC_DXCR_DSEL_SHIFT) +# define USIC_DXCR_DSEL_DX(m) ((uint32_t)(m) << USIC_DXCR_DSEL_SHIFT) /* Data input DXnm selected */ +# define USIC_DXCR_DSEL_DXA (0 << USIC_DXCR_DSEL_SHIFT) /* Data input DXnA selected */ +# define USIC_DXCR_DSEL_DXB (1 << USIC_DXCR_DSEL_SHIFT) /* Data input DXnB selected */ +# define USIC_DXCR_DSEL_DXC (2 << USIC_DXCR_DSEL_SHIFT) /* Data input DXnC selected */ +# define USIC_DXCR_DSEL_DXD (3 << USIC_DXCR_DSEL_SHIFT) /* Data input DXnD selected */ +# define USIC_DXCR_DSEL_DXE (4 << USIC_DXCR_DSEL_SHIFT) /* Data input DXnE selected */ +# define USIC_DXCR_DSEL_DXF (5 << USIC_DXCR_DSEL_SHIFT) /* Data input DXnF selected */ +# define USIC_DXCR_DSEL_DXG (6 << USIC_DXCR_DSEL_SHIFT) /* Data input DXnG selected */ +# define USIC_DXCR_DSEL_ONE (7 << USIC_DXCR_DSEL_SHIFT) /* Data input is always 1 */ #define USIC_DX1CR_DCEN (1 << 3) /* Bit 3: Delay Compensation Enable (DX1CR only) */ #define USIC_DXCR_INSW (1 << 4) /* Bit 4: Input Switch */ #define USIC_DXCR_DFEN (1 << 5) /* Bit 5: Digital Filter Enable */ @@ -531,17 +532,19 @@ #define USIC_DXCR_DPOL (1 << 8) /* Bit 8: Data Polarity for DXn */ #define USIC_DXCR_SFSEL (1 << 9) /* Bit 9: Sampling Frequency Selection */ #define USIC_DXCR_CM_SHIFT (10) /* Bits 10-11: Combination Mode */ -#define USIC_DXCR_CM_MASK (3 << USIC_DX0CR_CM_SHIFT) -# define USIC_DXCR_CM_DISABLE (0 << USIC_DX0CR_CM_SHIFT) /* Trigger activation disabled */ -# define USIC_DXCR_CM_RISING (1 << USIC_DX0CR_CM_SHIFT) /* Rising edge activates DXnT */ -# define USIC_DXCR_CM_FALLING (2 << USIC_DX0CR_CM_SHIFT) /* Falling edge activates DXnT */ -# define USIC_DXCR_CM_BOTH (3 << USIC_DX0CR_CM_SHIFT) /* Both edges activate DXnT */ +#define USIC_DXCR_CM_MASK (3 << USIC_DXCR_CM_SHIFT) +# define USIC_DXCR_CM_DISABLE (0 << USIC_DXCR_CM_SHIFT) /* Trigger activation disabled */ +# define USIC_DXCR_CM_RISING (1 << USIC_DXCR_CM_SHIFT) /* Rising edge activates DXnT */ +# define USIC_DXCR_CM_FALLING (2 << USIC_DXCR_CM_SHIFT) /* Falling edge activates DXnT */ +# define USIC_DXCR_CM_BOTH (3 << USIC_DXCR_CM_SHIFT) /* Both edges activate DXnT */ #define USIC_DXCR_DXS (1 << 15) /* Bit 15: Synchronized Data Value */ /* Shift Control Register */ #define USIC_SCTR_SDIR (1 << 0) /* Bit 0: Shift Direction */ #define USIC_SCTR_PDL (1 << 1) /* Bit 1: Passive Data Level */ +# define USIC_SCTR_PDL0 (0) /* 0=Passive data level is 0 */ +# define USIC_SCTR_PDL1 (1 << 1) /* 1=Passive data level is 1 */ #define USIC_SCTR_DSM_SHIFT (2) /* Bits 2-3: Data Shift Mode */ #define USIC_SCTR_DSM_MASK (3 << USIC_SCTR_DSM_SHIFT) # define USIC_SCTR_DSM_1BIT (0 << USIC_SCTR_DSM_SHIFT) /* Data is shifted one bit at a time */ @@ -555,8 +558,8 @@ #define USIC_SCTR_TRM_SHIFT (8) /* Bits 8-9: Transmission Mode */ #define USIC_SCTR_TRM_MASK (3 << USIC_SCTR_TRM_SHIFT) # define USIC_SCTR_TRM_INACTIVE (0 << USIC_SCTR_TRM_SHIFT) /* Inactive */ -# define USIC_SCTR_TRM_0LEVEL (1 << USIC_SCTR_TRM_SHIFT) /* Active at 1-level */ -# define USIC_SCTR_TRM_1LEVEL (2 << USIC_SCTR_TRM_SHIFT) /* Active if it is at 0-level */ +# define USIC_SCTR_TRM_1LEVEL (1 << USIC_SCTR_TRM_SHIFT) /* Active at 1-level */ +# define USIC_SCTR_TRM_0LEVEL (2 << USIC_SCTR_TRM_SHIFT) /* Active at 0-level */ # define USIC_SCTR_TRM_ACTIVE (3 << USIC_SCTR_TRM_SHIFT) /* Active without regard to signal level */ #define USIC_SCTR_FLE_SHIFT (16) /* Bits 16-21: Frame Length */ #define USIC_SCTR_FLE_MASK (0x3f << USIC_SCTR_FLE_SHIFT) @@ -638,7 +641,8 @@ # define USIC_PCR_ASCMODE_SP(n) ((uint32_t)(n) << USIC_PCR_ASCMODE_SP_SHIFT) #define USIC_PCR_ASCMODE_PL_SHIFT (13) /* Bits 13-15: Pulse Length */ #define USIC_PCR_ASCMODE_PL_MASK (7 << USIC_PCR_ASCMODE_PL_SHIFT) - #define USIC_PCR_ASCMODE_PL(n) ((uint32_t)((n)-1) << USIC_PCR_ASCMODE_PL_SHIFT) + #define USIC_PCR_ASCMODE_PLBIT (0 << USIC_PCR_ASCMODE_PL_SHIFT) /* Pulse length = bit length */ + #define USIC_PCR_ASCMODE_PL(n) ((uint32_t)((n)-1) << USIC_PCR_ASCMODE_PL_SHIFT) /* Pulse length = n quanta */ #define USIC_PCR_ASCMODE_RSTEN (1 << 16) /* Bit 16: Receiver Status Enable */ #define USIC_PCR_ASCMODE_TSTEN (1 << 17) /* Bit 17: Transmitter Status Enable */ #define USIC_PCR_ASCMODE_MCLK (1 << 31) /* Bit 31: Master Clock Enable */ @@ -717,7 +721,7 @@ # define USIC_CCR_HPCEN_DX0_2 (3 << USIC_CCR_HPCEN_SHIFT) /* Port control enabled for DX0, DX[5:3] and DOUT[3:0] */ #define USIC_CCR_PM_SHIFT (8) /* Bits 8-9: Parity Mode */ #define USIC_CCR_PM_MASK (3 << USIC_CCR_PM_SHIFT) -# define USIC_CCR_PM_DISABLE (0 << USIC_CCR_PM_SHIFT) /* Parity generation is disabled */ +# define USIC_CCR_PM_NONE (0 << USIC_CCR_PM_SHIFT) /* Parity generation is disabled */ # define USIC_CCR_PM_EVEN (2 << USIC_CCR_PM_SHIFT) /* Even parity is selected */ # define USIC_CCR_PM_ODD (3 << USIC_CCR_PM_SHIFT) /* Odd parity is selected */ #define USIC_CCR_RSIEN (1 << 10) /* Bit 10: Receiver Start Interrupt Enable */ diff --git a/arch/arm/src/xmc4/xmc4_lowputc.c b/arch/arm/src/xmc4/xmc4_lowputc.c index 0c7a4fdc5e..b92e723e66 100644 --- a/arch/arm/src/xmc4/xmc4_lowputc.c +++ b/arch/arm/src/xmc4/xmc4_lowputc.c @@ -52,6 +52,7 @@ #include "chip/xmc4_usic.h" #include "chip/xmc4_pinmux.h" #include "xmc4_usic.h" +#include "xmc4_gpio.h" #include "xmc4_lowputc.h" /**************************************************************************** @@ -64,6 +65,7 @@ # if defined(CONFIG_UART0_SERIAL_CONSOLE) # define CONSOLE_CHAN USIC0_CHAN0 # define CONSOLE_FREQ BOARD_CORECLK_FREQ +# define CONSOLE_DX BOARD_UART0_DX # define CONSOLE_BAUD CONFIG_UART0_BAUD # define CONSOLE_BITS CONFIG_UART0_BITS # define CONSOLE_2STOP CONFIG_UART0_2STOP @@ -71,6 +73,7 @@ # elif defined(CONFIG_UART1_SERIAL_CONSOLE) # define CONSOLE_CHAN USIC0_CHAN1 # define CONSOLE_FREQ BOARD_CORECLK_FREQ +# define CONSOLE_DX BOARD_UART1_DX # define CONSOLE_BAUD CONFIG_UART1_BAUD # define CONSOLE_BITS CONFIG_UART1_BITS # define CONSOLE_2STOP CONFIG_UART1_2STOP @@ -78,6 +81,7 @@ # elif defined(CONFIG_UART2_SERIAL_CONSOLE) # define CONSOLE_CHAN USIC1_CHAN0 # define CONSOLE_FREQ BOARD_BUS_FREQ +# define CONSOLE_DX BOARD_UART2_DX # define CONSOLE_BAUD CONFIG_UART2_BAUD # define CONSOLE_BITS CONFIG_UART2_BITS # define CONSOLE_2STOP CONFIG_UART2_2STOP @@ -85,6 +89,7 @@ # elif defined(CONFIG_UART3_SERIAL_CONSOLE) # define CONSOLE_CHAN USIC1_CHAN1 # define CONSOLE_FREQ BOARD_BUS_FREQ +# define CONSOLE_DX BOARD_UART3_DX # define CONSOLE_BAUD CONFIG_UART3_BAUD # define CONSOLE_BITS CONFIG_UART3_BITS # define CONSOLE_2STOP CONFIG_UART3_2STOP @@ -92,6 +97,7 @@ # elif defined(CONFIG_UART4_SERIAL_CONSOLE) # define CONSOLE_CHAN USIC2_CHAN0 # define CONSOLE_FREQ BOARD_BUS_FREQ +# define CONSOLE_DX BOARD_UART4_DX # define CONSOLE_BAUD CONFIG_UART4_BAUD # define CONSOLE_BITS CONFIG_UART4_BITS # define CONSOLE_2STOP CONFIG_UART4_2STOP @@ -99,6 +105,7 @@ # elif defined(CONFIG_UART5_SERIAL_CONSOLE) # define CONSOLE_CHAN USIC2_CHAN1 # define CONSOLE_FREQ BOARD_BUS_FREQ +# define CONSOLE_DX BOARD_UART5_DX # define CONSOLE_BAUD CONFIG_UART5_BAUD # define CONSOLE_BITS CONFIG_UART5_BITS # define CONSOLE_2STOP CONFIG_UART5_2STOP @@ -108,10 +115,27 @@ # endif #endif /* HAVE_UART_CONSOLE */ +/* REVISIT: Oversampling is hardcoded to 16 here. Perhaps this should be in + * the config structure. + */ + +#define UART_OVERSAMPLING 16 + /**************************************************************************** - * Private Functions + * Private Data ****************************************************************************/ +#ifdef HAVE_UART_CONSOLE +static const struct uart_config_s g_console_config = +{ + .baud = CONSOLE_BAUD, + .dx = CONSOLE_DX, + .parity = CONSOLE_PARITY, + .nbits = CONSOLE_BITS, + .stop2 = CONSOLE_2STOP +}; +#endif + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -127,25 +151,26 @@ void up_lowputc(char ch) { #ifdef HAVE_UART_CONSOLE - /* Wait until the transmit data register is "empty" (TDRE). This state - * depends on the TX watermark setting and may not mean that the transmit - * buffer is truly empty. It just means that we can now add another - * character to the transmit buffer without exceeding the watermark. - * - * NOTE: UART0 has an 8-byte deep FIFO; the other UARTs have no FIFOs - * (1-deep). There appears to be no way to know when the FIFO is not - * full (other than reading the FIFO length and comparing the FIFO count). - * Hence, the FIFOs are not used in this implementation and, as a result - * TDRE indeed mean that the single output buffer is available. - * - * Performance on UART0 could be improved by enabling the FIFO and by - * redesigning all of the FIFO status logic. - */ -#warning Missing logic + uintptr_t base; + uint32_t regval; - /* Then write the character to the UART data register */ + /* Get the base address of the USIC registers associated with this channel */ -#warning Missing logic + base = xmc4_channel_baseaddress(CONSOLE_CHAN); + DEBUGASSERT(base != 0); + + /* Wait for the transmit buffer/fifo to be "not full." */ + + do + { + regval = getreg32(base + XMC4_USIC_TRBSR_OFFSET); + } + while ((regval & USIC_TRBSR_TFULL) != 0); + + /* Then write the character to the USIC IN register */ + + putreg32((uint32_t)ch, base + XMC4_USIC_IN_OFFSET); +#endif } /**************************************************************************** @@ -160,40 +185,55 @@ void up_lowputc(char ch) void xmc4_lowsetup(void) { - uint32_t regval; +#ifdef HAVE_UART_DEVICE + /* Configure UART pins for the all enabled UARTs. + * + * NOTE that the board must provide the definitions in the board.h header + * file of the form like: GPIO_UARTn_RXm and GPIO_UARTn_TXm where n is + * the USIC module, 0..(XMC_NUSIC-1), and m is the USIC channel number, 0 + * or 1. + * + * In additional, the board.h must provide the definition of + * BOARD_BOARD_UARTn_DX which indicates which input pin is selected, i.e. + * one of the 0=DXA, 1=DXB, ... 6=DXG. + */ - /* Enable peripheral clocking for all enabled UARTs. */ -#warning Missing logic - - /* Configure UART pins for the all enabled UARTs */ +#ifdef HAVE_UART0 + (void)xmc4_gpio_config(GPIO_UART0_RXD0); + (void)xmc4_gpio_config(GPIO_UART0_TXD0); +#endif +#ifdef HAVE_UART1 + (void)xmc4_gpio_config(GPIO_UART0_RXD1); + (void)xmc4_gpio_config(GPIO_UART0_TXD1); +#endif +#ifdef HAVE_UART2 + (void)xmc4_gpio_config(GPIO_UART0_RXD2); + (void)xmc4_gpio_config(GPIO_UART0_TXD2); +#endif +#ifdef HAVE_UART3 + (void)xmc4_gpio_config(GPIO_UART0_RXD3); + (void)xmc4_gpio_config(GPIO_UART0_TXD3); +#endif +#ifdef HAVE_UART4 + (void)xmc4_gpio_config(GPIO_UART0_RXD4); + (void)xmc4_gpio_config(GPIO_UART0_TXD4); +#endif +#ifdef HAVE_UART5 + (void)xmc4_gpio_config(GPIO_UART0_RXD5); + (void)xmc4_gpio_config(GPIO_UART0_TXD5); +#endif +#ifdef HAVE_UART_CONSOLE /* Configure the console (only) now. Other UARTs will be configured * when the serial driver is opened. */ - xmc4_uart_configure(CONSOLE_CHAN, CONSOLE_BAUD, CONSOLE_FREQ, \ - CONSOLE_PARITY, CONSOLE_BITS, CONSOLE_2STOP); + xmc4_uart_configure(CONSOLE_CHAN, &g_console_config); + +#endif /* HAVE_UART_CONSOLE */ #endif /* HAVE_UART_DEVICE */ } -/**************************************************************************** - * Name: xmc4_uart_reset - * - * Description: - * Reset a UART. - * - ****************************************************************************/ - -#ifdef HAVE_UART_DEVICE -void xmc4_uart_reset(uintptr_t uart_base) -{ - uint8_t regval; - - /* Just disable the transmitter and receiver */ -#warning Missing logic -} -#endif - /**************************************************************************** * Name: xmc4_uart_configure * @@ -207,12 +247,11 @@ void xmc4_uart_reset(uintptr_t uart_base) ****************************************************************************/ #ifdef HAVE_UART_DEVICE -int xmc4_uart_configure(enum usic_channel_e channel, uint32_t baud, - uint32_t clock, unsigned int parity, - unsigned int nbits, unsigned int stop2) +int xmc4_uart_configure(enum usic_channel_e channel, + FAR const struct uart_config_s *config) { uintptr_t base; - uint32_t oversampling; + uint32_t regval; int ret; /* Get the base address of the USIC registers associated with this channel */ @@ -231,30 +270,159 @@ int xmc4_uart_configure(enum usic_channel_e channel, uint32_t baud, return ret; } - ret = xmc4_uisc_baudrate(channel, baud, oversampling); + /* Configure the BAUD rate. + * REVISIT: Oversample is hardcoded to 16 here. Perhaps this should be in + * the config structure. + */ - /* Configure number of bits, stop bits and parity */ -#warning Missing logic + ret = xmc4_uisc_baudrate(channel, config->baud, UART_OVERSAMPLING); - /* Check for odd parity */ -#warning Missing logic + /* Configure frame format. + * + * - Pulse length for standard UART signaling, i.e. the 0 level is + * signaled during the complete bit time + * - Enable Sample Majority Decision sample mode + */ - /* Check for even parity */ -#warning Missing logic + regval = USIC_PCR_ASCMODE_PLBIT | USIC_PCR_ASCMODE_SMD; - /* Check for 9-bit operation */ -#warning Missing logic + /* - Sampling point set equal to the half of the oversampling period */ - /* Calculate baud settings (truncating) */ -#warning Missing logic + regval |= USIC_PCR_ASCMODE_SP((UART_OVERSAMPLING >> 1) + 1); - /* Configure FIFOs */ -#warning Missing logic + /* - Configure the number of stop bits */ - /* Enable RX and TX FIFOs */ -#warning Missing logic + if (config->stop2) + { + regval |= USIC_PCR_ASCMODE_STPB; + } - /* Now we can (re-)enable the transmitter and receiver */ -#warning Missing logic + putreg32(regval, base + XMC4_USIC_PCR_OFFSET); + + /* Configure Shift Control Register: + * + * - Set passive data level, high + * - Transmission Mode: The shift control signal is considered active if + * it is at 1-level. This is the setting to be programmed to allow + * data transfers. + * - Set word length + * - Set frame length equal to the word length + */ + + regval = USIC_SCTR_PDL0 | USIC_SCTR_TRM_1LEVEL | + USIC_SCTR_FLE(config->nbits) | USIC_SCTR_WLE(config->nbits); + putreg32(regval, base + XMC4_USIC_SCTR_OFFSET); + + /* Enable transfer buffer */ + + regval = USIC_TCSR_TDEN_TDIV | USIC_TCSR_TDSSM; + putreg32(regval, base + XMC4_USIC_TCSR_OFFSET); + + /* Clear protocol status */ + + putreg32(0xffffffff, base + XMC4_USIC_PSCR_OFFSET); + + /* Configure parity */ + + if (config->parity == 1) + { + /* Odd parrity */ + + regval = USIC_CCR_PM_ODD; + } + else if (config->parity == 2) + { + /* Even parity */ + + regval = USIC_CCR_PM_EVEN; + } + else + { + /* No parity */ + + DEBUGASSERT(config->parity == 0); + regval = USIC_CCR_PM_NONE; + } + + putreg32(regval, base + XMC4_USIC_CCR_OFFSET); + + /* Set DX0CR input source path */ + + regval = getreg32(base + XMC4_USIC_DX0CR_OFFSET); + regval &= ~USIC_DXCR_DSEL_MASK; + regval |= USIC_DXCR_DSEL_DX(config->dx); + putreg32(regval, base + XMC4_USIC_DX0CR_OFFSET); + + /* Disable transmit FIFO */ + + regval = getreg32(base + XMC4_USIC_TBCTR_OFFSET); + regval &= ~USIC_TBCTR_SIZE_MASK; + putreg32(regval, base + XMC4_USIC_TBCTR_OFFSET); + + /* Configure transmit FIFO + * + * - DPTR = 16 + * - LIMIT = 1 + * - STBTEN = 0, the trigger of the standard transmit buffer event is + * based on the transition of the fill level from equal to below the + * limit, not the fact being below + * - SIZE = 16 + * - LOF = 0, A standard transmit buffer event occurs when the filling + * level equals the limit value and gets lower due to transmission of + * a data word + */ + + regval &= ~(USIC_TBCTR_DPTR_MASK | USIC_TBCTR_LIMIT_MASK | USIC_RBCTR_SRBTEN | + USIC_TBCTR_SIZE_MASK | USIC_RBCTR_LOF); + regval |= (USIC_TBCTR_DPTR(16) | USIC_TBCTR_LIMIT(1) | USIC_TBCTR_SIZE_16); + putreg32(regval, base + XMC4_USIC_TBCTR_OFFSET); + + /* Disable the receive FIFO */ + + regval = getreg32(base + XMC4_USIC_RBCTR_OFFSET); + regval &= ~USIC_RBCTR_SIZE_MASK; + putreg32(regval, base + XMC4_USIC_RBCTR_OFFSET); + + /* Configure receive FIFO. + * + * - DPTR = 0 + * - LIMIT = 15 + * - SIZE = 16 + * - LOF = 1, A standard receive buffer event occurs when the filling + * level equals the limit value and gets bigger due to the reception + * of a new data word + */ + + regval &= ~(USIC_RBCTR_DPTR_MASK | USIC_RBCTR_LIMIT_MASK | USIC_RBCTR_SIZE_MASK); + regval |= (USIC_RBCTR_DPTR(0) | USIC_RBCTR_LIMIT(15) | USIC_RBCTR_SIZE_16 | USIC_RBCTR_LOF); + putreg32(regval, base + XMC4_USIC_RBCTR_OFFSET); + + /* Start UART */ + + regval = getreg32(base + XMC4_USIC_CCR_OFFSET); + regval &= ~USIC_CCR_MODE_MASK; + regval |= USIC_CCR_MODE_ASC; + putreg32(regval, base + XMC4_USIC_CCR_OFFSET); + + /* Set service request for UART protocol events. + * + * Set channel 0 protocol events on sevice request 0 + * Set channel 1 protocol events on sevice request 1 + */ + + regval = getreg32(base + XMC4_USIC_INPR_OFFSET); + regval &= ~USIC_INPR_PINP_MASK; + + if (((unsigned int)channel & 1) != 0) + { + regval |= USIC_INPR_PINP_SR0; + } + else + { + regval |= USIC_INPR_PINP_SR1; + } + + putreg32(regval, base + XMC4_USIC_INPR_OFFSET); + return OK; } #endif diff --git a/arch/arm/src/xmc4/xmc4_lowputc.h b/arch/arm/src/xmc4/xmc4_lowputc.h index fa9d8ce16b..f8016c3d78 100644 --- a/arch/arm/src/xmc4/xmc4_lowputc.h +++ b/arch/arm/src/xmc4/xmc4_lowputc.h @@ -47,6 +47,21 @@ #include "xmc4_config.h" #include "xmc4_usic.h" +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* This structure provides the configuration of one UART channel */ + +struct uart_config_s +{ + uint32_t baud; /* Desired BAUD rate */ + uint8_t dx; /* Input pin 0=DXA, 1=DXB, ... 6=DXG */ + uint8_t parity; /* Parity selection: 0=none, 1=odd, 2=even */ + uint8_t nbits; /* Number of bits per word */ + bool stop2; /* true=2 stop bits; false=1 stop bit */ +}; + /**************************************************************************** * Public Function Prototypes ****************************************************************************/ @@ -63,18 +78,6 @@ void xmc4_lowsetup(void); -/**************************************************************************** - * Name: xmc4_uart_reset - * - * Description: - * Reset a UART. - * - ****************************************************************************/ - -#ifdef HAVE_UART_DEVICE -void xmc4_uart_reset(uintptr_t uart_base); -#endif - /**************************************************************************** * Name: xmc4_uart_configure * @@ -88,9 +91,8 @@ void xmc4_uart_reset(uintptr_t uart_base); ****************************************************************************/ #ifdef HAVE_UART_DEVICE -int xmc4_uart_configure(enum usic_channel_e channel, uint32_t baud, - uint32_t clock, unsigned int parity, - unsigned int nbits, unsigned int stop2); +int xmc4_uart_configure(enum usic_channel_e channel, + FAR const struct uart_config_s *config); #endif /**************************************************************************** diff --git a/arch/arm/src/xmc4/xmc4_serial.c b/arch/arm/src/xmc4/xmc4_serial.c index 78db3fd792..f1cccd7809 100644 --- a/arch/arm/src/xmc4/xmc4_serial.c +++ b/arch/arm/src/xmc4/xmc4_serial.c @@ -227,17 +227,18 @@ * Private Types ****************************************************************************/ +/* This structure provides the state of one UART device */ + struct xmc4_dev_s { uintptr_t uartbase; /* Base address of UART registers */ - uint32_t baud; /* Configured baud */ - uint32_t clock; /* Clocking frequency of the UART module */ uint8_t channel; /* USIC channel identification */ uint8_t irqs; /* Status IRQ associated with this UART (for enable) */ uint8_t ie; /* Interrupts enabled */ - uint8_t parity; /* 0=none, 1=odd, 2=even */ - uint8_t bits; /* Number of bits (8 or 9) */ - uint8_t stop2; /* Use 2 stop bits */ + + /* UART configuration */ + + struct uart_config_s config; }; /**************************************************************************** @@ -314,13 +315,16 @@ static char g_uart5txbuffer[CONFIG_UART5_TXBUFSIZE]; static struct xmc4_dev_s g_uart0priv = { .uartbase = XMC4_USIC0_CH0_BASE, - .clock = BOARD_CORECLK_FREQ, .channel = (uint8_t)USIC0_CHAN0, - .baud = CONFIG_UART0_BAUD, - .irqs = XMC4_IRQ_USIC0, - .parity = CONFIG_UART0_PARITY, - .bits = CONFIG_UART0_BITS, - .stop2 = CONFIG_UART0_2STOP, + .irqs = XMC4_IRQ_USIC0_SR0, + .config = + { + .baud = CONFIG_UART0_BAUD, + .dx = BOARD_UART0_DX, + .parity = CONFIG_UART0_PARITY, + .nbits = CONFIG_UART0_BITS, + .stop2 = CONFIG_UART0_2STOP, + } }; static uart_dev_t g_uart0port = @@ -346,13 +350,16 @@ static uart_dev_t g_uart0port = static struct xmc4_dev_s g_uart1priv = { .uartbase = XMC4_USIC0_CH1_BASE, - .clock = BOARD_CORECLK_FREQ, .channel = (uint8_t)USIC0_CHAN1, - .baud = CONFIG_UART1_BAUD, - .irqs = XMC4_IRQ_USIC1, - .parity = CONFIG_UART1_PARITY, - .bits = CONFIG_UART1_BITS, - .stop2 = CONFIG_UART1_2STOP, + .irqs = XMC4_IRQ_USIC0_SR1, + .config = + { + .baud = CONFIG_UART1_BAUD, + .dx = BOARD_UART1_DX, + .parity = CONFIG_UART1_PARITY, + .nbits = CONFIG_UART1_BITS, + .stop2 = CONFIG_UART1_2STOP, + } }; static uart_dev_t g_uart1port = @@ -378,13 +385,16 @@ static uart_dev_t g_uart1port = static struct xmc4_dev_s g_uart2priv = { .uartbase = XMC4_USIC1_CH0_BASE, - .clock = BOARD_BUS_FREQ, .channel = (uint8_t)USIC1_CHAN0, - .baud = CONFIG_UART2_BAUD, - .irqs = XMC4_IRQ_USIC2, - .parity = CONFIG_UART2_PARITY, - .bits = CONFIG_UART2_BITS, - .stop2 = CONFIG_UART2_2STOP, + .irqs = XMC4_IRQ_USIC1_SR0, + .config = + { + .baud = CONFIG_UART2_BAUD, + .dx = BOARD_UART2_DX, + .parity = CONFIG_UART2_PARITY, + .nbits = CONFIG_UART2_BITS, + .stop2 = CONFIG_UART2_2STOP, + } }; static uart_dev_t g_uart2port = @@ -410,13 +420,16 @@ static uart_dev_t g_uart2port = static struct xmc4_dev_s g_uart3priv = { .uartbase = XMC4_USIC1_CH1_BASE, - .clock = BOARD_BUS_FREQ, .channel = (uint8_t)USIC1_CHAN1, - .baud = CONFIG_UART3_BAUD, - .irqs = XMC4_IRQ_USIC3, - .parity = CONFIG_UART3_PARITY, - .bits = CONFIG_UART3_BITS, - .stop2 = CONFIG_UART3_2STOP, + .irqs = XMC4_IRQ_USIC1_SR1, + .config = + { + .baud = CONFIG_UART3_BAUD, + .dx = BOARD_UART3_DX, + .parity = CONFIG_UART3_PARITY, + .nbits = CONFIG_UART3_BITS, + .stop2 = CONFIG_UART3_2STOP, + } }; static uart_dev_t g_uart3port = @@ -442,13 +455,16 @@ static uart_dev_t g_uart3port = static struct xmc4_dev_s g_uart4priv = { .uartbase = XMC4_USIC2_CH0_BASE, - .clock = BOARD_BUS_FREQ, .channel = (uint8_t)USIC2_CHAN0, - .baud = CONFIG_UART4_BAUD, - .irqs = XMC4_IRQ_USIC4, - .parity = CONFIG_UART4_PARITY, - .bits = CONFIG_UART4_BITS, - .stop2 = CONFIG_UART4_2STOP, + .irqs = XMC4_IRQ_USIC2_SR0, + .config = + { + .baud = CONFIG_UART4_BAUD, + .dx = BOARD_UART4_DX, + .parity = CONFIG_UART4_PARITY, + .nbits = CONFIG_UART4_BITS, + .stop2 = CONFIG_UART4_2STOP, + } }; static uart_dev_t g_uart4port = @@ -474,13 +490,16 @@ static uart_dev_t g_uart4port = static struct xmc4_dev_s g_uart5priv = { .uartbase = XMC4_USIC2_CH1_BASE, - .clock = BOARD_BUS_FREQ, .channel = (uint8_t)USIC2_CHAN1, - .baud = CONFIG_UART5_BAUD, - .irqs = XMC4_IRQ_USIC5, - .parity = CONFIG_UART5_PARITY, - .bits = CONFIG_UART5_BITS, - .stop2 = CONFIG_UART5_2STOP, + .irqs = XMC4_IRQ_USIC2_SR1, + .config = + { + .baud = CONFIG_UART5_BAUD, + .dx = BOARD_UART5_DX, + .parity = CONFIG_UART5_PARITY, + .nbits = CONFIG_UART5_BITS, + .stop2 = CONFIG_UART5_2STOP, + } }; static uart_dev_t g_uart5port = @@ -508,7 +527,7 @@ static uart_dev_t g_uart5port = * Name: up_serialin ****************************************************************************/ -static inline uint8_t up_serialin(struct xmc4_dev_s *priv, int offset) +static inline uint32_t up_serialin(struct xmc4_dev_s *priv, int offset) { return getreg8(priv->uartbase + offset); } @@ -517,7 +536,7 @@ static inline uint8_t up_serialin(struct xmc4_dev_s *priv, int offset) * Name: up_serialout ****************************************************************************/ -static inline void up_serialout(struct xmc4_dev_s *priv, int offset, uint8_t value) +static inline void up_serialout(struct xmc4_dev_s *priv, int offset, uint32_t value) { putreg8(value, priv->uartbase + offset); } @@ -586,8 +605,7 @@ static int xmc4_setup(struct uart_dev_s *dev) /* Configure the UART as an RS-232 UART */ - xmc4_uart_configure(priv->uartbase, priv->baud, priv->clock, - priv->parity, priv->bits, priv->stop2); + xmc4_uart_configure(priv->uartbase, &priv->config); #endif /* Make sure that all interrupts are disabled */ @@ -615,7 +633,7 @@ static void xmc4_shutdown(struct uart_dev_s *dev) /* Reset hardware and disable Rx and Tx */ - xmc4_uart_reset(priv->uartbase); + xmc4_uart_disable(priv->channel); } /**************************************************************************** @@ -807,32 +825,23 @@ static int xmc4_ioctl(struct file *filep, int cmd, unsigned long arg) static int xmc4_receive(struct uart_dev_s *dev, uint32_t *status) { struct xmc4_dev_s *priv = (struct xmc4_dev_s *)dev->priv; - uint8_t s1; + uint32_t outr; - /* Get error status information: - * - * FE: Framing error. To clear FE, read S1 with FE set and then read - * read UART data register (D). - * NF: Noise flag. To clear NF, read S1 and then read the UART data - * register (D). - * PF: Parity error flag. To clear PF, read S1 and then read the UART - * data register (D). - */ + /* Get input data along with receiver control information */ - s1 = up_serialin(priv, XMC4_UART_S1_OFFSET); + outr = up_serialin(priv, XMC4_UART_S1_OFFSET); + up_serialout(priv, XMC4_USIC_OUTR_OFFSET, (uint32_t)ch); - /* Return status information */ + /* Return receiver control information */ if (status) { - *status = (uint32_t)s1; + *status = outr >> USIC_OUTR_RCI_SHIFT; } - /* Then return the actual received byte. Reading S1 then D clears all - * RX errors. - */ + /* Then return the actual received data. */ - return (int)up_serialin(priv, XMC4_UART_D_OFFSET); + return outr & USIC_OUTR_DSR_MASK; } /**************************************************************************** @@ -885,14 +894,12 @@ static void xmc4_rxint(struct uart_dev_s *dev, bool enable) static bool xmc4_rxavailable(struct uart_dev_s *dev) { struct xmc4_dev_s *priv = (struct xmc4_dev_s *)dev->priv; - /* Return true if the receive data register is full (RDRF). NOTE: If - * FIFOS are enabled, this does not mean that the FIFO is full, - * rather, it means that the number of bytes in the RX FIFO has - * exceeded the watermark setting. There may actually be RX data - * available! - */ + uint32_t regval; - return (up_serialin(priv, XMC4_UART_S1_OFFSET) & UART_S1_RDRF) != 0; + /* Return true if the transmit buffer/fifo is not "empty." */ + + regval = up_serialin(priv, XMC4_UART_TRBSR_OFFSET); + return ((regval & USIC_TRBSR_REMPTY) == 0); } /**************************************************************************** @@ -906,7 +913,7 @@ static bool xmc4_rxavailable(struct uart_dev_s *dev) static void xmc4_send(struct uart_dev_s *dev, int ch) { struct xmc4_dev_s *priv = (struct xmc4_dev_s *)dev->priv; - up_serialout(priv, XMC4_UART_D_OFFSET, (uint8_t)ch); + up_serialout(priv, XMC4_USIC_IN_OFFSET, (uint32_t)ch); } /**************************************************************************** @@ -960,15 +967,12 @@ static void xmc4_txint(struct uart_dev_s *dev, bool enable) static bool xmc4_txready(struct uart_dev_s *dev) { struct xmc4_dev_s *priv = (struct xmc4_dev_s *)dev->priv; + uint32_t regval; - /* Return true if the transmit data register is "empty." NOTE: If - * FIFOS are enabled, this does not mean that the FIFO is empty, - * rather, it means that the number of bytes in the TX FIFO is - * below the watermark setting. There may actually be space for - * additional TX data. - */ + /* Return true if the transmit buffer/fifo is "not full." */ - return (up_serialin(priv, XMC4_UART_S1_OFFSET) & UART_S1_TDRE) != 0; + regval = up_serialin(priv, XMC4_UART_TRBSR_OFFSET); + return ((regval & USIC_TRBSR_TFULL) == 0); } /**************************************************************************** @@ -982,10 +986,12 @@ static bool xmc4_txready(struct uart_dev_s *dev) static bool xmc4_txempty(struct uart_dev_s *dev) { struct xmc4_dev_s *priv = (struct xmc4_dev_s *)dev->priv; + uint32_t regval; /* Return true if the transmit buffer/fifo is "empty." */ - return (up_serialin(priv, XMC4_UART_SFIFO_OFFSET) & UART_SFIFO_TXEMPT) != 0; + regval = up_serialin(priv, XMC4_UART_TRBSR_OFFSET); + return ((regval & USIC_TRBSR_TEMPTY) != 0); } /**************************************************************************** diff --git a/arch/arm/src/xmc4/xmc4_usic.h b/arch/arm/src/xmc4/xmc4_usic.h index 5c5e78fdb9..910846bc85 100644 --- a/arch/arm/src/xmc4/xmc4_usic.h +++ b/arch/arm/src/xmc4/xmc4_usic.h @@ -44,10 +44,6 @@ #include #include "xmc4_config.h" -/**************************************************************************** - * Pre-processor Definitions - ****************************************************************************/ - /**************************************************************************** * Public Types ****************************************************************************/ @@ -56,9 +52,9 @@ enum usic_e { - USIC0 = 0, /* USIC0 */ - USIC1 = 1, /* USIC1 */ - USIC2 = 2 /* USIC2 */ + USIC0 = 0, /* USIC0 */ + USIC1 = 1, /* USIC1 */ + USIC2 = 2 /* USIC2 */ }; /* This enumeration identifies USIC channels */ @@ -73,6 +69,19 @@ enum usic_channel_e USIC2_CHAN1 = 5 /* USIC2, Channel 1 */ }; +/* This enumeration defines values for the dx input selection */ + +enum uart_dx_e +{ + USIC_DXA = 0, /* USICn_DXmA */ + USIC_DXB = 1, /* USICn_DXmB */ + USIC_DXC = 2, /* USICn_DXmC */ + USIC_DXD = 3, /* USICn_DXmD */ + USIC_DXE = 4, /* USICn_DXmE */ + USIC_DXF = 5, /* USICn_DXmF */ + USIC_DXG = 6 /* USICn_DXmG */ +}; + /**************************************************************************** * Public Function Prototypes ****************************************************************************/ diff --git a/configs/xmc4500-relax/include/board.h b/configs/xmc4500-relax/include/board.h index dbc2440902..e90e3f730c 100644 --- a/configs/xmc4500-relax/include/board.h +++ b/configs/xmc4500-relax/include/board.h @@ -192,6 +192,17 @@ #define BUTTON_0_BIT (1 << BUTTON_0) #define BUTTON_1_BIT (1 << BUTTON_1) +/* USIC0 ****************************************************************************/ +/* USIC0 CH0 is used as UART0 + * + * RX - P1.4 + * TX - P1.5 + */ + +#define BOARD_UART0_DX USIC_DXB +#define GPIO_UART0_RXD0 GPIO_U0C0_DX0B +#define GPIO_UART0_TXD0 (GPIO_U0C0_DOUT0_3 | GPIO_PADA1P_STRONGSOFT | GPIO_OUTPUT_SET) + /************************************************************************************ * Public Data ************************************************************************************/