| /* ---------------------------------------------------------------------------- |
| * ATMEL Microcontroller Software Support |
| * ---------------------------------------------------------------------------- |
| * Copyright (c) 2009, Atmel Corporation |
| * |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are 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. |
| * ---------------------------------------------------------------------------- |
| */ |
| |
| /** \addtogroup usart_module Working with USART |
| * The USART driver provides the interface to configure and use the USART peripheral.\n |
| * |
| * The USART supports several kinds of comminication modes such as full-duplex asynchronous/ |
| * synchronous serial commnunication,RS485 with driver control signal,ISO7816,SPI and Test modes. |
| * |
| * To start a USART transfer with \ref AT91SAM3S_PDC "PDC" support, the user could follow these steps: |
| * <ul> |
| * <li> Configure USART with expected mode and baudrate(see \ref USART_Configure), which could be done by: |
| * -# Resetting and disabling transmitter and receiver by setting US_CR(Control Register). </li> |
| * -# Conifguring the USART in a specific mode by setting USART_MODE bits in US_MR(Mode Register) </li> |
| * -# Setting baudrate which is different from mode to mode. |
| </li> |
| * <li> Enable transmitter or receiver respectively by set US_CR_TXEN or US_CR_RXEN in US_CR.</li> |
| * <li> Read from or write to the peripheral with \ref USART_ReadBuffer or \ref USART_WriteBuffer. |
| These operations could be done by polling or interruption. </li> |
| * <li> For polling, check the status bit US_CSR_ENDRX/US_CSR_RXBUFF (READ) or US_CSR_ENDTX/ |
| US_CSR_TXBUFE (WRITE). </li> |
| * <li> For interruption,"enable" the status bit through US_IER and |
| realize the hanler with USARTx_IrqHandler according to IRQ vector |
| table which is defined in board_cstartup_<toolchain>.c |
| To enable the interruption of USART,it should be configured with priority and enabled first through |
| NVIC .</li> |
| * </ul> |
| * |
| * For more accurate information, please look at the USART section of the |
| * Datasheet. |
| * |
| * Related files :\n |
| * \ref usart.c\n |
| * \ref usart.h\n |
| */ |
| |
| |
| |
| /** |
| * \file |
| * |
| * Implementation of USART (Universal Synchronous Asynchronous Receiver Transmitter) |
| * controller. |
| * |
| */ |
| /*------------------------------------------------------------------------------ |
| * Headers |
| *------------------------------------------------------------------------------*/ |
| #include "chip.h" |
| #include "trace.h" |
| |
| #include <assert.h> |
| #include <string.h> |
| |
| /*---------------------------------------------------------------------------- |
| * Local definitions |
| *----------------------------------------------------------------------------*/ |
| |
| |
| /*------------------------------------------------------------------------------ |
| * Exported functions |
| *------------------------------------------------------------------------------*/ |
| |
| /** |
| * \brief Configures an USART peripheral with the specified parameters. |
| * |
| * |
| * \param usart 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 *usart, |
| uint32_t mode, |
| uint32_t baudrate, |
| uint32_t masterClock) |
| { |
| /* Reset and disable receiver & transmitter*/ |
| usart->US_CR = US_CR_RSTRX | US_CR_RSTTX |
| | US_CR_RXDIS | US_CR_TXDIS; |
| |
| /* Configure mode*/ |
| usart->US_MR = mode; |
| |
| /* Configure baudrate*/ |
| /* Asynchronous, no oversampling*/ |
| if ( ((mode & US_MR_SYNC) == 0) && ((mode & US_MR_OVER) == 0) ) |
| { |
| usart->US_BRGR = (masterClock / baudrate) / 16; |
| } |
| |
| if( ((mode & US_MR_USART_MODE_SPI_MASTER) == US_MR_USART_MODE_SPI_MASTER) |
| || ((mode & US_MR_SYNC) == US_MR_SYNC)) |
| { |
| if( (mode & US_MR_USCLKS_Msk) == US_MR_USCLKS_MCK) |
| { |
| usart->US_BRGR = masterClock / baudrate; |
| } |
| else |
| { |
| if ( (mode & US_MR_USCLKS_DIV) == US_MR_USCLKS_DIV) |
| { |
| usart->US_BRGR = masterClock / baudrate / 8; |
| } |
| } |
| } |
| /* TODO other modes*/ |
| } |
| /** |
| * \brief Enables or disables the transmitter of an USART peripheral. |
| * |
| * |
| * \param usart Pointer to an USART peripheral |
| * \param enabled If true, the transmitter is enabled; otherwise it is |
| * disabled. |
| */ |
| void USART_SetTransmitterEnabled(Usart *usart, uint8_t enabled) |
| { |
| if (enabled) { |
| |
| usart->US_CR = US_CR_TXEN; |
| } |
| else { |
| |
| usart->US_CR = US_CR_TXDIS; |
| } |
| } |
| |
| /** |
| * \brief Enables or disables the receiver of an USART peripheral |
| * |
| * |
| * \param usart Pointer to an USART peripheral |
| * \param enabled If true, the receiver is enabled; otherwise it is disabled. |
| */ |
| void USART_SetReceiverEnabled(Usart *usart, |
| uint8_t enabled) |
| { |
| if (enabled) { |
| |
| usart->US_CR = US_CR_RXEN; |
| } |
| else { |
| |
| usart->US_CR = US_CR_RXDIS; |
| } |
| } |
| |
| /** |
| * \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 usart 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 *usart, |
| uint16_t data, |
| volatile uint32_t timeOut) |
| { |
| if (timeOut == 0) { |
| |
| while ((usart->US_CSR & US_CSR_TXEMPTY) == 0); |
| } |
| else { |
| |
| while ((usart->US_CSR & US_CSR_TXEMPTY) == 0) { |
| |
| if (timeOut == 0) { |
| |
| TRACE_ERROR("USART_Write: Timed out.\n\r"); |
| return; |
| } |
| timeOut--; |
| } |
| } |
| |
| usart->US_THR = data; |
| } |
| |
| /** |
| * \brief Sends the contents of a data buffer through the specified USART peripheral. |
| * This function returns immediately (1 if the buffer has been queued, 0 |
| * otherwise); poll the ENDTX and TXBUFE bits of the USART status register |
| * to check for the transfer completion. |
| * |
| * \param usart Pointer to an USART peripheral. |
| * \param buffer Pointer to the data buffer to send. |
| * \param size Size of the data buffer (in bytes). |
| */ |
| uint8_t USART_WriteBuffer( |
| Usart *usart, |
| void *buffer, |
| uint32_t size) |
| { |
| /* Check if the first PDC bank is free*/ |
| if ((usart->US_TCR == 0) && (usart->US_TNCR == 0)) { |
| |
| usart->US_TPR = (uint32_t) buffer; |
| usart->US_TCR = size; |
| usart->US_PTCR = US_PTCR_TXTEN; |
| |
| return 1; |
| } |
| /* Check if the second PDC bank is free*/ |
| else if (usart->US_TNCR == 0) { |
| |
| usart->US_TNPR = (uint32_t) buffer; |
| usart->US_TNCR = size; |
| |
| return 1; |
| } |
| else { |
| |
| return 0; |
| } |
| } |
| |
| |
| /** |
| * \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 usart Pointer to an USART peripheral. |
| * \param timeOut Time out value (0 -> no timeout). |
| */ |
| uint16_t USART_Read( |
| Usart *usart, |
| volatile uint32_t timeOut) |
| { |
| if (timeOut == 0) { |
| |
| while ((usart->US_CSR & US_CSR_RXRDY) == 0); |
| } |
| else { |
| |
| while ((usart->US_CSR & US_CSR_RXRDY) == 0) { |
| |
| if (timeOut == 0) { |
| |
| TRACE_ERROR( "USART_Read: Timed out.\n\r" ) ; |
| return 0; |
| } |
| timeOut--; |
| } |
| } |
| |
| return usart->US_RHR; |
| } |
| |
| /** |
| * \brief Reads data from an USART peripheral, filling the provided buffer until it |
| * becomes full. This function returns immediately with 1 if the buffer has |
| * been queued for transmission; otherwise 0. |
| * |
| * \param usart Pointer to an USART peripheral. |
| * \param buffer Pointer to the buffer where the received data will be stored. |
| * \param size Size of the data buffer (in bytes). |
| */ |
| uint8_t USART_ReadBuffer(Usart *usart, |
| void *buffer, |
| uint32_t size) |
| { |
| /* Check if the first PDC bank is free*/ |
| if ((usart->US_RCR == 0) && (usart->US_RNCR == 0)) { |
| |
| usart->US_RPR = (uint32_t) buffer; |
| usart->US_RCR = size; |
| usart->US_PTCR = US_PTCR_RXTEN; |
| |
| return 1; |
| } |
| /* Check if the second PDC bank is free*/ |
| else if (usart->US_RNCR == 0) { |
| |
| usart->US_RNPR = (uint32_t) buffer; |
| usart->US_RNCR = size; |
| |
| return 1; |
| } |
| else { |
| |
| return 0; |
| } |
| } |
| |
| /** |
| * \brief Returns 1 if some data has been received and can be read from an USART; |
| * otherwise returns 0. |
| * |
| * \param usart Pointer to an Usart instance. |
| */ |
| uint8_t USART_IsDataAvailable(Usart *usart) |
| { |
| if ((usart->US_CSR & US_CSR_RXRDY) != 0) { |
| |
| return 1; |
| } |
| else { |
| |
| return 0; |
| } |
| } |
| |
| /** |
| * \brief Sets the filter value for the IRDA demodulator. |
| * |
| * \param pUsart Pointer to an Usart instance. |
| * \param filter Filter value. |
| */ |
| void USART_SetIrdaFilter(Usart *pUsart, uint8_t filter) |
| { |
| assert( pUsart != NULL ) ; |
| |
| pUsart->US_IF = filter; |
| } |
| |
| /** |
| * \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 usart Pointer to an USART peripheral. |
| * \param c Character to send |
| */ |
| void USART_PutChar( |
| Usart *usart, |
| uint8_t c) |
| { |
| /* Wait for the transmitter to be ready*/ |
| while ((usart->US_CSR & US_CSR_TXEMPTY) == 0); |
| |
| /* Send character*/ |
| usart->US_THR = c; |
| |
| /* Wait for the transfer to complete*/ |
| while ((usart->US_CSR & US_CSR_TXEMPTY) == 0); |
| } |
| |
| /** |
| * \brief Return 1 if a character can be read in USART |
| */ |
| uint32_t USART_IsRxReady(Usart *usart) |
| { |
| return (usart->US_CSR & US_CSR_RXRDY); |
| } |
| /** |
| * \brief Get present status |
| */ |
| uint32_t USART_GetStatus(Usart *usart) |
| { |
| return usart->US_CSR; |
| } |
| /** |
| * \brief Enable interrupt |
| */ |
| void USART_EnableIt(Usart *usart,uint32_t mode) |
| { |
| usart->US_IER = mode; |
| } |
| /** |
| * \brief Disable interrupt |
| */ |
| void USART_DisableIt(Usart *usart,uint32_t mode) |
| { |
| usart->US_IDR = mode; |
| } |
| /** |
| * \brief Reads and returns a character from the USART. |
| * |
| * \note This function is synchronous (i.e. uses polling). |
| * \param usart Pointer to an USART peripheral. |
| * \return Character received. |
| */ |
| uint8_t USART_GetChar(Usart *usart) |
| { |
| while ((usart->US_CSR & US_CSR_RXRDY) == 0); |
| return usart->US_RHR; |
| } |