/* * Copyright (c) 2015, Freescale Semiconductor, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * o Redistributions of source code must retain the above copyright notice, this list * of conditions and the following disclaimer. * * o Redistributions in binary form must reproduce the above copyright notice, this * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * * o Neither the name of Freescale Semiconductor, Inc. nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "uart_imx.h" /******************************************************************************* * Code ******************************************************************************/ /******************************************************************************* * Initialization and Configuration functions ******************************************************************************/ /*FUNCTION********************************************************************** * * Function Name : UART_Init * Description : This function initializes the module according to uart * initialize structure. * *END**************************************************************************/ void UART_Init(UART_Type* base, const uart_init_config_t* initConfig) { assert(initConfig); /* Disable UART Module. */ UART_UCR1_REG(base) &= ~UART_UCR1_UARTEN_MASK; /* Reset UART register to its default value. */ UART_Deinit(base); /* Set UART data word length, stop bit count, parity mode and communication * direction according to uart init struct, disable RTS hardware flow * control. */ UART_UCR2_REG(base) |= (initConfig->wordLength | initConfig->stopBitNum | initConfig->parity | initConfig->direction | UART_UCR2_IRTS_MASK); /* For imx family device, UARTs are used in MUXED mode, * so that this bit should always be set.*/ UART_UCR3_REG(base) |= UART_UCR3_RXDMUXSEL_MASK; /* Set BaudRate according to uart initialize struct. */ /* Baud Rate = Ref Freq / (16 * (UBMR + 1)/(UBIR+1)) */ UART_SetBaudRate(base, initConfig->clockRate, initConfig->baudRate); } /*FUNCTION********************************************************************** * * Function Name : UART_Deinit * Description : This function reset Uart module register content to its * default value. * *END**************************************************************************/ void UART_Deinit(UART_Type* base) { /* Disable UART Module */ UART_UCR1_REG(base) &= ~UART_UCR1_UARTEN_MASK; /* Reset UART Module Register content to default value */ UART_UCR1_REG(base) = 0x0; UART_UCR2_REG(base) = UART_UCR2_SRST_MASK; UART_UCR3_REG(base) = UART_UCR3_DSR_MASK | UART_UCR3_DCD_MASK | UART_UCR3_RI_MASK; UART_UCR4_REG(base) = UART_UCR4_CTSTL(32); UART_UFCR_REG(base) = UART_UFCR_TXTL(2) | UART_UFCR_RXTL(1); UART_UESC_REG(base) = UART_UESC_ESC_CHAR(0x2B); UART_UTIM_REG(base) = 0x0; UART_ONEMS_REG(base) = 0x0; UART_UTS_REG(base) = UART_UTS_TXEMPTY_MASK | UART_UTS_RXEMPTY_MASK; UART_UMCR_REG(base) = 0x0; /* Reset the transmit and receive state machines, all FIFOs and register * USR1, USR2, UBIR, UBMR, UBRC, URXD, UTXD and UTS[6-3]. */ UART_UCR2_REG(base) &= ~UART_UCR2_SRST_MASK; while (!(UART_UCR2_REG(base) & UART_UCR2_SRST_MASK)); } /*FUNCTION********************************************************************** * * Function Name : UART_SetBaudRate * Description : * *END**************************************************************************/ void UART_SetBaudRate(UART_Type* base, uint32_t clockRate, uint32_t baudRate) { uint32_t numerator; uint32_t denominator; uint32_t divisor; uint32_t refFreqDiv; uint32_t divider = 1; /* get the approximately maximum divisor */ numerator = clockRate; denominator = baudRate << 4; divisor = 1; while (denominator != 0) { divisor = denominator; denominator = numerator % denominator; numerator = divisor; } numerator = clockRate / divisor; denominator = (baudRate << 4) / divisor; /* numerator ranges from 1 ~ 7 * 64k */ /* denominator ranges from 1 ~ 64k */ if ((numerator > (UART_UBIR_INC_MASK * 7)) || (denominator > UART_UBIR_INC_MASK)) { uint32_t m = (numerator - 1) / (UART_UBIR_INC_MASK * 7) + 1; uint32_t n = (denominator - 1) / UART_UBIR_INC_MASK + 1; uint32_t max = m > n ? m : n; numerator /= max; denominator /= max; if (0 == numerator) numerator = 1; if (0 == denominator) denominator = 1; } divider = (numerator - 1) / UART_UBIR_INC_MASK + 1; switch (divider) { case 1: refFreqDiv = 0x05; break; case 2: refFreqDiv = 0x04; break; case 3: refFreqDiv = 0x03; break; case 4: refFreqDiv = 0x02; break; case 5: refFreqDiv = 0x01; break; case 6: refFreqDiv = 0x00; break; case 7: refFreqDiv = 0x06; break; default: refFreqDiv = 0x05; } UART_UFCR_REG(base) &= ~UART_UFCR_RFDIV_MASK; UART_UFCR_REG(base) |= UART_UFCR_RFDIV(refFreqDiv); UART_UBIR_REG(base) = UART_UBIR_INC(denominator - 1); UART_UBMR_REG(base) = UART_UBMR_MOD(numerator / divider - 1); UART_ONEMS_REG(base) = UART_ONEMS_ONEMS(clockRate/(1000 * divider)); } /*FUNCTION********************************************************************** * * Function Name : UART_SetInvertCmd * Description : This function is used to set the polarity of UART signal. * The polarity of Tx and Rx can be set separately. * *END**************************************************************************/ void UART_SetInvertCmd(UART_Type* base, uint32_t direction, bool invert) { assert((direction & uartDirectionTx) || (direction & uartDirectionRx)); if (invert) { if (direction & UART_UCR2_RXEN_MASK) UART_UCR4_REG(base) |= UART_UCR4_INVR_MASK; if (direction & UART_UCR2_TXEN_MASK) UART_UCR3_REG(base) |= UART_UCR3_INVT_MASK; } else { if (direction & UART_UCR2_RXEN_MASK) UART_UCR4_REG(base) &= ~UART_UCR4_INVR_MASK; if (direction & UART_UCR2_TXEN_MASK) UART_UCR3_REG(base) &= ~UART_UCR3_INVT_MASK; } } /******************************************************************************* * Low Power Mode functions ******************************************************************************/ /*FUNCTION********************************************************************** * * Function Name : UART_SetDozeMode * Description : This function is used to set UART enable condition in the * DOZE state. * *END**************************************************************************/ void UART_SetDozeMode(UART_Type* base, bool enable) { if (enable) UART_UCR1_REG(base) &= UART_UCR1_DOZE_MASK; else UART_UCR1_REG(base) |= ~UART_UCR1_DOZE_MASK; } /*FUNCTION********************************************************************** * * Function Name : UART_SetLowPowerMode * Description : This function is used to set UART enable condition of the * UART low power feature. * *END**************************************************************************/ void UART_SetLowPowerMode(UART_Type* base, bool enable) { if (enable) UART_UCR4_REG(base) &= ~UART_UCR4_LPBYP_MASK; else UART_UCR4_REG(base) |= UART_UCR4_LPBYP_MASK; } /******************************************************************************* * Interrupt and Flag control functions ******************************************************************************/ /*FUNCTION********************************************************************** * * Function Name : UART_SetIntCmd * Description : This function is used to set the enable condition of * specific UART interrupt source. The available interrupt * source can be select from uart_int_source enumeration. * *END**************************************************************************/ void UART_SetIntCmd(UART_Type* base, uint32_t intSource, bool enable) { volatile uint32_t* uart_reg = 0; uint32_t uart_mask = 0; uart_reg = (uint32_t *)((uint32_t)base + (intSource >> 16)); uart_mask = (1 << (intSource & 0x0000FFFF)); if (enable) *uart_reg |= uart_mask; else *uart_reg &= ~uart_mask; } /*FUNCTION********************************************************************** * * Function Name : UART_GetStatusFlag * Description : This function is used to get the current status of specific * UART status flag. The available status flag can be select * from uart_status_flag & uart_interrupt_flag enumeration. * *END**************************************************************************/ bool UART_GetStatusFlag(UART_Type* base, uint32_t flag) { volatile uint32_t* uart_reg = 0; uart_reg = (uint32_t *)((uint32_t)base + (flag >> 16)); return (bool)((*uart_reg >> (flag & 0x0000FFFF)) & 0x1); } /*FUNCTION********************************************************************** * * Function Name : UART_ClearStatusFlag * Description : This function is used to get the current status * of specific UART status flag. The available status * flag can be select from uart_status_flag & * uart_interrupt_flag enumeration. * *END**************************************************************************/ void UART_ClearStatusFlag(UART_Type* base, uint32_t flag) { volatile uint32_t* uart_reg = 0; uint32_t uart_mask = 0; uart_reg = (uint32_t *)((uint32_t)base + (flag >> 16)); uart_mask = (1 << (flag & 0x0000FFFF)); /* write 1 to clear. */ *uart_reg = uart_mask; } /******************************************************************************* * DMA control functions ******************************************************************************/ /*FUNCTION********************************************************************** * * Function Name : UART_SetDmaCmd * Description : This function is used to set the enable condition of * specific UART DMA source. The available DMA * source can be select from uart_dma_source enumeration. * *END**************************************************************************/ void UART_SetDmaCmd(UART_Type* base, uint32_t dmaSource, bool enable) { volatile uint32_t* uart_reg = 0; uint32_t uart_mask = 0; uart_reg = (uint32_t *)((uint32_t)base + (dmaSource >> 16)); uart_mask = (1 << (dmaSource & 0x0000FFFF)); if (enable) *uart_reg |= uart_mask; else *uart_reg &= ~uart_mask; } /******************************************************************************* * Hardware Flow control and Modem Signal functions ******************************************************************************/ /*FUNCTION********************************************************************** * * Function Name : UART_SetRtsFlowCtrlCmd * Description : This function is used to set the enable condition of RTS * Hardware flow control. * *END**************************************************************************/ void UART_SetRtsFlowCtrlCmd(UART_Type* base, bool enable) { if (enable) UART_UCR2_REG(base) &= ~UART_UCR2_IRTS_MASK; else UART_UCR2_REG(base) |= UART_UCR2_IRTS_MASK; } /*FUNCTION********************************************************************** * * Function Name : UART_SetCtsFlowCtrlCmd * Description : This function is used to set the enable condition of CTS * auto control. if CTS control is enabled, the CTS_B pin will * be controlled by the receiver, otherwise the CTS_B pin will * controlled by UART_CTSPinCtrl function. * *END**************************************************************************/ void UART_SetCtsFlowCtrlCmd(UART_Type* base, bool enable) { if (enable) UART_UCR2_REG(base) |= UART_UCR2_CTSC_MASK; else UART_UCR2_REG(base) &= ~UART_UCR2_CTSC_MASK; } /*FUNCTION********************************************************************** * * Function Name : UART_SetCtsPinLevel * Description : This function is used to control the CTS_B pin state when * auto CTS control is disabled. * The CTS_B pin is low (active) * The CTS_B pin is high (inactive) * *END**************************************************************************/ void UART_SetCtsPinLevel(UART_Type* base, bool active) { if (active) UART_UCR2_REG(base) |= UART_UCR2_CTS_MASK; else UART_UCR2_REG(base) &= ~UART_UCR2_CTS_MASK; } /*FUNCTION********************************************************************** * * Function Name : UART_SetModemMode * Description : This function is used to set the role(DTE/DCE) of UART module * in RS-232 communication. * *END**************************************************************************/ void UART_SetModemMode(UART_Type* base, uint32_t mode) { assert((mode == uartModemModeDce) || (mode == uartModemModeDte)); if (uartModemModeDce == mode) UART_UFCR_REG(base) &= ~UART_UFCR_DCEDTE_MASK; else UART_UFCR_REG(base) |= UART_UFCR_DCEDTE_MASK; } /*FUNCTION********************************************************************** * * Function Name : UART_SetDtrPinLevel * Description : This function is used to set the pin state of * DSR pin(for DCE mode) or DTR pin(for DTE mode) for the * modem interface. * *END**************************************************************************/ void UART_SetDtrPinLevel(UART_Type* base, bool active) { if (active) UART_UCR3_REG(base) |= UART_UCR3_DSR_MASK; else UART_UCR3_REG(base) &= ~UART_UCR3_DSR_MASK; } /*FUNCTION********************************************************************** * * Function Name : UART_SetDcdPinLevel * Description : This function is used to set the pin state of * DCD pin. THIS FUNCTION IS FOR DCE MODE ONLY. * *END**************************************************************************/ void UART_SetDcdPinLevel(UART_Type* base, bool active) { if (active) UART_UCR3_REG(base) |= UART_UCR3_DCD_MASK; else UART_UCR3_REG(base) &= ~UART_UCR3_DCD_MASK; } /*FUNCTION********************************************************************** * * Function Name : UART_SetRiPinLevel * Description : This function is used to set the pin state of * RI pin. THIS FUNCTION IS FOR DCE MODE ONLY. * *END**************************************************************************/ void UART_SetRiPinLevel(UART_Type* base, bool active) { if (active) UART_UCR3_REG(base) |= UART_UCR3_RI_MASK; else UART_UCR3_REG(base) &= ~UART_UCR3_RI_MASK; } /******************************************************************************* * Multiprocessor and RS-485 functions ******************************************************************************/ /*FUNCTION********************************************************************** * * Function Name : UART_Putchar9 * Description : This function is used to send 9 Bits length data in * RS-485 Multidrop mode. * *END**************************************************************************/ void UART_Putchar9(UART_Type* base, uint16_t data) { assert(data <= 0x1FF); if (data & 0x0100) UART_UMCR_REG(base) |= UART_UMCR_TXB8_MASK; else UART_UMCR_REG(base) &= ~UART_UMCR_TXB8_MASK; UART_UTXD_REG(base) = (data & UART_UTXD_TX_DATA_MASK); } /*FUNCTION********************************************************************** * * Function Name : UART_Getchar9 * Description : This functions is used to receive 9 Bits length data in * RS-485 Multidrop mode. * *END**************************************************************************/ uint16_t UART_Getchar9(UART_Type* base) { uint16_t rxData = UART_URXD_REG(base); if (rxData & UART_URXD_PRERR_MASK) { rxData = (rxData & 0x00FF) | 0x0100; } else { rxData &= 0x00FF; } return rxData; } /*FUNCTION********************************************************************** * * Function Name : UART_SetMultidropMode * Description : This function is used to set the enable condition of * 9-Bits data or Multidrop mode. * *END**************************************************************************/ void UART_SetMultidropMode(UART_Type* base, bool enable) { if (enable) UART_UMCR_REG(base) |= UART_UMCR_MDEN_MASK; else UART_UMCR_REG(base) &= ~UART_UMCR_MDEN_MASK; } /*FUNCTION********************************************************************** * * Function Name : UART_SetSlaveAddressDetectCmd * Description : This function is used to set the enable condition of * Automatic Address Detect Mode. * *END**************************************************************************/ void UART_SetSlaveAddressDetectCmd(UART_Type* base, bool enable) { if (enable) UART_UMCR_REG(base) |= UART_UMCR_SLAM_MASK; else UART_UMCR_REG(base) &= ~UART_UMCR_SLAM_MASK; } /******************************************************************************* * IrDA control functions ******************************************************************************/ /*FUNCTION********************************************************************** * * Function Name : UART_SetIrDACmd * Description : This function is used to set the enable condition of * IrDA Mode. * *END**************************************************************************/ void UART_SetIrDACmd(UART_Type* base, bool enable) { if (enable) UART_UCR1_REG(base) |= UART_UCR1_IREN_MASK; else UART_UCR1_REG(base) &= ~UART_UCR1_IREN_MASK; } /*FUNCTION********************************************************************** * * Function Name : UART_SetIrDAVoteClock * Description : This function is used to set the clock for the IR pulsed * vote logic. The available clock can be select from * uart_irda_vote_clock enumeration. * *END**************************************************************************/ void UART_SetIrDAVoteClock(UART_Type* base, uint32_t voteClock) { assert((voteClock == uartIrdaVoteClockSampling) || \ (voteClock == uartIrdaVoteClockReference)); if (uartIrdaVoteClockSampling == voteClock) UART_UCR4_REG(base) |= UART_UCR4_IRSC_MASK; else UART_UCR4_REG(base) &= ~UART_UCR4_IRSC_MASK; } /******************************************************************************* * Misc. functions ******************************************************************************/ /*FUNCTION********************************************************************** * * Function Name : UART_SetAutoBaudRateCmd * Description : This function is used to set the enable condition of * Automatic Baud Rate Detection feature. * *END**************************************************************************/ void UART_SetAutoBaudRateCmd(UART_Type* base, bool enable) { if (enable) UART_UCR1_REG(base) |= UART_UCR1_ADBR_MASK; else UART_UCR1_REG(base) &= ~UART_UCR1_ADBR_MASK; } /*FUNCTION********************************************************************** * * Function Name : UART_SendBreakChar * Description : This function is used to send BREAK character.It is * important that SNDBRK is asserted high for a sufficient * period of time to generate a valid BREAK. * *END**************************************************************************/ void UART_SendBreakChar(UART_Type* base, bool active) { if (active) UART_UCR1_REG(base) |= UART_UCR1_SNDBRK_MASK; else UART_UCR1_REG(base) &= ~UART_UCR1_SNDBRK_MASK; } /*FUNCTION********************************************************************** * * Function Name : UART_SetEscapeDecectCmd * Description : This function is used to set the enable condition of * Escape Sequence Detection feature. * *END**************************************************************************/ void UART_SetEscapeDecectCmd(UART_Type* base, bool enable) { if (enable) UART_UCR2_REG(base) |= UART_UCR2_ESCEN_MASK; else UART_UCR2_REG(base) &= ~UART_UCR2_ESCEN_MASK; } /******************************************************************************* * EOF ******************************************************************************/