diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2016-01-12 15:34:31 +0100 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2016-01-19 08:36:20 +0100 |
commit | e1eeb883d82ce218c2a9c754795cb3c86ac0f36d (patch) | |
tree | 646a7c22772297094bb77303953eda0e71679dd9 /c/src/lib/libbsp/arm/atsam/libraries/libchip/source/usart.c | |
parent | bsps/arm: Copy vector table only if necessary (diff) | |
download | rtems-e1eeb883d82ce218c2a9c754795cb3c86ac0f36d.tar.bz2 |
bsp/atsam: Import SAM Software Package
Import selected files of the "SAM V71 / V70 / E70 / S70 Software
Package" obtained from the "SAMV71-XULT GNU Software Package 1.5".
Converted files via dos2unix before import.
Update #2529.
Diffstat (limited to 'c/src/lib/libbsp/arm/atsam/libraries/libchip/source/usart.c')
-rw-r--r-- | c/src/lib/libbsp/arm/atsam/libraries/libchip/source/usart.c | 462 |
1 files changed, 462 insertions, 0 deletions
diff --git a/c/src/lib/libbsp/arm/atsam/libraries/libchip/source/usart.c b/c/src/lib/libbsp/arm/atsam/libraries/libchip/source/usart.c new file mode 100644 index 0000000000..313d9c38dc --- /dev/null +++ b/c/src/lib/libbsp/arm/atsam/libraries/libchip/source/usart.c @@ -0,0 +1,462 @@ +/* ---------------------------------------------------------------------------- */ +/* Atmel Microcontroller Software Support */ +/* SAM Software Package License */ +/* ---------------------------------------------------------------------------- */ +/* Copyright (c) 2015, Atmel Corporation */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following condition is met: */ +/* */ +/* - Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the disclaimer below. */ +/* */ +/* Atmel's name may not be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR */ +/* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE */ +/* DISCLAIMED. IN NO EVENT SHALL ATMEL 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. */ +/* ---------------------------------------------------------------------------- */ + +/** + * \file + * + * Implementation of USART (Universal Synchronous Asynchronous Receiver + * Transmitter) controller. + * + */ +/*------------------------------------------------------------------------------ + * Headers + *-----------------------------------------------------------------------------*/ +#include "chip.h" + +#include <assert.h> +#include <string.h> + +/*---------------------------------------------------------------------------- + * Local definitions + *----------------------------------------------------------------------------*/ + + +/*------------------------------------------------------------------------------ + * Exported functions + *-----------------------------------------------------------------------------*/ + +/** + * \brief Configures an USART baudrate. + * + * + * \param pUsart Pointer to the USART peripheral to configure. + * \param baudrate Baudrate at which the USART should operate (in Hz). + * \param masterClock Frequency of the system master clock (in Hz). + */ +void USART_SetBaudrate(Usart *pUsart, + uint8_t OverSamp, + uint32_t baudrate, + uint32_t masterClock) +{ + unsigned int CD, FP, BaudError, ActualBaudRate; + /* Configure baudrate*/ + BaudError = 10; + OverSamp = 0; + + /*Asynchronous*/ + if ((pUsart->US_MR & US_MR_SYNC) == 0) { + /* 7816 mode */ + if (((pUsart->US_MR & US_MR_USART_MODE_IS07816_T_0) + == US_MR_USART_MODE_IS07816_T_0) + || ((pUsart->US_MR & US_MR_USART_MODE_IS07816_T_1) + == US_MR_USART_MODE_IS07816_T_1)) { + /* Define the baud rate divisor register */ + /* CD = MCK / SCK */ + /* SCK = FIDI x BAUD = 372 x 9600 */ + /* BOARD_MCK */ + /* CD = MCK/(FIDI x BAUD) = 150000000 / (372x9600) = 42 */ + CD = masterClock / (pUsart->US_FIDI * baudrate); + FP = 0; + } else { + while (BaudError > 5) { + CD = (masterClock / (baudrate * 8 * (2 - OverSamp))); + FP = ((masterClock / (baudrate * (2 - OverSamp))) - CD * 8); + ActualBaudRate = (masterClock / (CD * 8 + FP)) / (2 - OverSamp); + BaudError = (100 - ((baudrate * 100 / ActualBaudRate))); + + if (BaudError > 5) { + OverSamp++; + + if (OverSamp >= 2) { + TRACE_ERROR("Canont set this baudrate \n\r"); + break; + } + } + } + } + } + + /*Synchronous SPI */ + if ((pUsart->US_MR & US_MR_USART_MODE_SPI_MASTER) + == US_MR_USART_MODE_SPI_MASTER + || ((pUsart->US_MR & US_MR_SYNC) == US_MR_SYNC)) { + if ((pUsart->US_MR & US_MR_USCLKS_Msk) == US_MR_USCLKS_MCK) { + CD = masterClock / baudrate; + FP = ((masterClock / baudrate) - CD); + } + } + + pUsart->US_BRGR = (US_BRGR_CD(CD) | US_BRGR_FP(FP)); + + /* Configure OverSamp*/ + pUsart->US_MR |= (OverSamp << 19); +} + +/** + * \brief Configures an USART peripheral with the specified parameters. + * + * + * \param pUsart Pointer to the USART peripheral to configure. + * \param mode Desired value for the USART mode register (see the datasheet). + * \param baudrate Baudrate at which the USART should operate (in Hz). + * \param masterClock Frequency of the system master clock (in Hz). + */ +void USART_Configure(Usart *pUsart, + uint32_t mode, + uint32_t baudrate, + uint32_t masterClock) +{ + + /* Reset and disable receiver & transmitter*/ + pUsart->US_CR = US_CR_RSTRX | US_CR_RSTTX + | US_CR_RXDIS | US_CR_TXDIS | US_CR_RSTSTA; + pUsart->US_IDR = 0xFFFFFFFF; + + pUsart->US_MR = mode; + /* Configure baudrate*/ + USART_SetBaudrate(pUsart, 0, baudrate, masterClock); + + /* Enable receiver and transmitter */ + pUsart->US_CR = US_CR_RXEN | US_CR_TXEN; + + /* Disable buffering for printf(). */ +#if (defined (__GNUC__) && !defined (__SAMBA__)) + setvbuf(stdout, (char *)NULL, _IONBF, 0); +#endif + +} +/** + * \brief Enables or disables the transmitter of an USART peripheral. + * + * + * \param pUsart Pointer to an USART peripheral + * \param enabled If true, the transmitter is enabled; otherwise it is + * disabled. + */ +void USART_SetTransmitterEnabled(Usart *pUsart, uint8_t enabled) +{ + if (enabled) + pUsart->US_CR = US_CR_TXEN; + else + pUsart->US_CR = US_CR_TXDIS; +} + +/** + * \brief Disables the Receiver of an USART peripheral. + * + * \param pUsart Pointer to an USART peripheral + */ +void USART_DisableRx(Usart *pUsart) +{ + + pUsart->US_CR = US_CR_RXDIS; +} + +/** + * \brief Disables the transmitter of an USART peripheral. + * + * \param pUsart Pointer to an USART peripheral + */ +void USART_DisableTx(Usart *pUsart) +{ + pUsart->US_CR = US_CR_TXDIS; +} + +/** + * \brief Enables the Receiver of an USART peripheral. + * + * \param pUsart Pointer to an USART peripheral + */ +void USART_EnableRx(Usart *pUsart) +{ + + pUsart->US_CR = US_CR_RXEN; +} + +/** + * \brief Enables the transmitter of an USART peripheral + * + * \param pUsart Pointer to an USART peripheral + */ +void USART_EnableTx(Usart *pUsart) +{ + pUsart->US_CR = US_CR_TXEN; +} +/** + * \brief Resets or disables the Receiver of an USART peripheral. + * + * + * \param pUsart Pointer to an USART peripheral + */ +void USART_ResetRx(Usart *pUsart) +{ + + pUsart->US_CR = US_CR_RSTRX | US_CR_RXDIS; +} + +/** + * \brief resets and disables the transmitter of an USART peripheral. + * + * + * \param pUsart Pointer to an USART peripheral + */ +void USART_ResetTx(Usart *pUsart) +{ + pUsart->US_CR = US_CR_RSTTX | US_CR_TXDIS; +} +/** + * \brief Enables or disables the receiver of an USART peripheral + * + * + * \param pUsart Pointer to an USART peripheral + * \param enabled If true, the receiver is enabled; otherwise it is disabled. + */ +void USART_SetReceiverEnabled(Usart *pUsart, uint8_t enabled) +{ + if (enabled) + pUsart->US_CR = US_CR_RXEN; + else + pUsart->US_CR = US_CR_RXDIS; +} + +/** + * \brief Enables or disables the Request To Send (RTS) of an USART peripheral + * + * + * \param pUsart Pointer to an USART peripheral + * \param enabled If true, the RTS is enabled (0); otherwise it is disabled. + */ +void USART_SetRTSEnabled(Usart *pUsart, uint8_t enabled) +{ + if (enabled) + pUsart->US_CR = US_CR_RTSEN; + else + pUsart->US_CR = US_CR_RTSDIS; +} + +/** + * \brief Sends one packet of data through the specified USART peripheral. This + * function operates synchronously, so it only returns when the data has been + * actually sent. + * + * + * \param pUsart Pointer to an USART peripheral. + * \param data Data to send including 9nth bit and sync field if necessary (in + * the same format as the US_THR register in the datasheet). + * \param timeOut Time out value (0 = no timeout). + */ +void USART_Write(Usart *pUsart, uint16_t data, volatile uint32_t timeOut) +{ + if (timeOut == 0) { + while ((pUsart->US_CSR & US_CSR_TXEMPTY) == 0); + } else { + while ((pUsart->US_CSR & US_CSR_TXEMPTY) == 0) { + if (timeOut == 0) { + TRACE_ERROR("USART_Write: Timed out.\n\r"); + return; + } + + timeOut--; + } + } + + pUsart->US_THR = data; +} + +/** + * \brief Reads and return a packet of data on the specified USART peripheral. + * This function operates asynchronously, so it waits until some data has been + * received. + * + * \param pUsart Pointer to an USART peripheral. + * \param timeOut Time out value (0 -> no timeout). + */ +uint16_t USART_Read(Usart *pUsart, volatile uint32_t timeOut) +{ + if (timeOut == 0) { + while ((pUsart->US_CSR & US_CSR_RXRDY) == 0); + } else { + while ((pUsart->US_CSR & US_CSR_RXRDY) == 0) { + if (timeOut == 0) { + TRACE_ERROR("USART_Read: Timed out.\n\r"); + return 0; + } + + timeOut--; + } + } + + return pUsart->US_RHR; +} + +/** + * \brief Returns 1 if some data has been received and can be read from an + * USART; otherwise returns 0. + * + * \param pUsart Pointer to an USART instance. + */ +uint8_t USART_IsDataAvailable(Usart *pUsart) +{ + if ((pUsart->US_CSR & US_CSR_RXRDY) != 0) + return 1; + else + return 0; +} + +/** + * \brief Sends one packet of data through the specified USART peripheral. This + * function operates synchronously, so it only returns when the data has been + * actually sent. + * + * \param pUsart Pointer to an USART peripheral. + * \param c Character to send + */ +void USART_PutChar(Usart *pUsart, uint8_t c) +{ + /* Wait for the transmitter to be ready*/ + while ((pUsart->US_CSR & US_CSR_TXEMPTY) == 0); + + /* Send character*/ + pUsart->US_THR = c; + + /* Wait for the transfer to complete*/ + while ((pUsart->US_CSR & US_CSR_TXEMPTY) == 0); +} + +/** + * \brief Return 1 if a character can be read in USART + * \param pUsart Pointer to an USART peripheral. + */ +uint32_t USART_IsRxReady(Usart *pUsart) +{ + return (pUsart->US_CSR & US_CSR_RXRDY); +} + +/** + * \brief Get present status + * \param pUsart Pointer to an USART peripheral. + */ +uint32_t USART_GetStatus(Usart *pUsart) +{ + return pUsart->US_CSR; +} + +/** + * \brief Enable interrupt + * \param pUsart Pointer to an USART peripheral. + * \param mode Interrupt mode. + */ +void USART_EnableIt(Usart *pUsart, uint32_t mode) +{ + pUsart->US_IER = mode; +} + +/** + * \brief Disable interrupt + * \param pUsart Pointer to an USART peripheral. + * \param mode Interrupt mode. + */ +void USART_DisableIt(Usart *pUsart, uint32_t mode) +{ + pUsart->US_IDR = mode; +} + +/** + * \brief Return interrupt mask + * \param pUsart Pointer to an USART peripheral. + */ +uint32_t USART_GetItMask(Usart *pUsart) +{ + return pUsart->US_IMR; +} + +/** + * \brief Reads and returns a character from the USART. + * + * \note This function is synchronous (i.e. uses polling). + * \param pUsart Pointer to an USART peripheral. + * \return Character received. + */ +uint8_t USART_GetChar(Usart *pUsart) +{ + while ((pUsart->US_CSR & US_CSR_RXRDY) == 0); + + return pUsart->US_RHR; +} + +/** + * \brief Enable Rx Timeout for USART. + * + * \param pUsart Pointer to an USART peripheral. + * \param Timeout Timeout value + * \return None + */ +void USART_EnableRecvTimeOut(Usart *pUsart, uint32_t Timeout) +{ + if (Timeout <= MAX_RX_TIMEOUT) + pUsart->US_RTOR = Timeout; + else if (Timeout == 0) { + TRACE_DEBUG("Timeout is disabled\n\r"); + } else { + TRACE_INFO_WP("\n\r"); + TRACE_FATAL("Timeout value is out of range\n\r"); + } +} + +/** + * \brief Enable Tx Timeout for USART. + * + * \param pUsart Pointer to an USART peripheral. + * \param TimeGaurd TimeGaurd value + * \return None + */ +void USART_EnableTxTimeGaurd(Usart *pUsart, uint32_t TimeGaurd) +{ + if (((pUsart->US_MR & US_MR_USART_MODE_LON) && TimeGaurd <= 16777215) || + ((pUsart->US_MR & US_MR_USART_MODE_LON) && TimeGaurd <= 255)) + pUsart->US_TTGR = TimeGaurd; + else + TRACE_ERROR(" TimeGaurd Value is too big for mode"); +} +/** + * \brief Acknowledge Rx timeout and sets to Idle or periodic repetitive state. + * + * \param pUsart Pointer to an USART peripheral. + * \param Periodic If timeout is periodic or should wait for new char + * \return None + */ +void USART_AcknowledgeRxTimeOut(Usart *pUsart, uint8_t Periodic) +{ + if (Periodic) { + pUsart->US_CR = US_CR_RETTO; // Restart timeout timer + } else { + // Puts USARt in Idle mode and waits for a char after timeout + pUsart->US_CR = US_CR_STTTO; + } +} |