Christina Quast | 8be71e4 | 2014-12-02 13:06:01 +0100 | [diff] [blame] | 1 | /* ----------------------------------------------------------------------------
|
| 2 | * ATMEL Microcontroller Software Support
|
| 3 | * ----------------------------------------------------------------------------
|
| 4 | * Copyright (c) 2009, Atmel Corporation
|
| 5 | *
|
| 6 | * All rights reserved.
|
| 7 | *
|
| 8 | * Redistribution and use in source and binary forms, with or without
|
| 9 | * modification, are permitted provided that the following conditions are met:
|
| 10 | *
|
| 11 | * - Redistributions of source code must retain the above copyright notice,
|
| 12 | * this list of conditions and the disclaimer below.
|
| 13 | *
|
| 14 | * Atmel's name may not be used to endorse or promote products derived from
|
| 15 | * this software without specific prior written permission.
|
| 16 | *
|
| 17 | * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
| 18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
| 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
| 20 | * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
| 21 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
| 22 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
| 23 | * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
| 24 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
| 25 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
| 26 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
| 27 | * ----------------------------------------------------------------------------
|
| 28 | */
|
| 29 |
|
| 30 | /** \addtogroup usart_module Working with USART
|
| 31 | * The USART driver provides the interface to configure and use the USART peripheral.\n
|
| 32 | *
|
| 33 | * The USART supports several kinds of comminication modes such as full-duplex asynchronous/
|
| 34 | * synchronous serial commnunication,RS485 with driver control signal,ISO7816,SPI and Test modes.
|
| 35 | *
|
| 36 | * To start a USART transfer with \ref AT91SAM3S_PDC "PDC" support, the user could follow these steps:
|
| 37 | * <ul>
|
| 38 | * <li> Configure USART with expected mode and baudrate(see \ref USART_Configure), which could be done by:
|
| 39 | * -# Resetting and disabling transmitter and receiver by setting US_CR(Control Register). </li>
|
| 40 | * -# Conifguring the USART in a specific mode by setting USART_MODE bits in US_MR(Mode Register) </li>
|
| 41 | * -# Setting baudrate which is different from mode to mode.
|
| 42 | </li>
|
| 43 | * <li> Enable transmitter or receiver respectively by set US_CR_TXEN or US_CR_RXEN in US_CR.</li>
|
| 44 | * <li> Read from or write to the peripheral with \ref USART_ReadBuffer or \ref USART_WriteBuffer.
|
| 45 | These operations could be done by polling or interruption. </li>
|
| 46 | * <li> For polling, check the status bit US_CSR_ENDRX/US_CSR_RXBUFF (READ) or US_CSR_ENDTX/
|
| 47 | US_CSR_TXBUFE (WRITE). </li>
|
| 48 | * <li> For interruption,"enable" the status bit through US_IER and
|
| 49 | realize the hanler with USARTx_IrqHandler according to IRQ vector
|
| 50 | table which is defined in board_cstartup_<toolchain>.c
|
| 51 | To enable the interruption of USART,it should be configured with priority and enabled first through
|
| 52 | NVIC .</li>
|
| 53 | * </ul>
|
| 54 | *
|
| 55 | * For more accurate information, please look at the USART section of the
|
| 56 | * Datasheet.
|
| 57 | *
|
| 58 | * Related files :\n
|
| 59 | * \ref usart.c\n
|
| 60 | * \ref usart.h\n
|
| 61 | */
|
| 62 |
|
| 63 |
|
| 64 |
|
| 65 | /**
|
| 66 | * \file
|
| 67 | *
|
| 68 | * Implementation of USART (Universal Synchronous Asynchronous Receiver Transmitter)
|
| 69 | * controller.
|
| 70 | *
|
| 71 | */
|
| 72 | /*------------------------------------------------------------------------------
|
| 73 | * Headers
|
| 74 | *------------------------------------------------------------------------------*/
|
| 75 | #include "chip.h"
|
| 76 | #include "trace.h"
|
| 77 |
|
| 78 | #include <assert.h>
|
| 79 | #include <string.h>
|
| 80 |
|
| 81 | /*----------------------------------------------------------------------------
|
| 82 | * Local definitions
|
| 83 | *----------------------------------------------------------------------------*/
|
| 84 |
|
| 85 |
|
| 86 | /*------------------------------------------------------------------------------
|
| 87 | * Exported functions
|
| 88 | *------------------------------------------------------------------------------*/
|
| 89 |
|
| 90 | /**
|
| 91 | * \brief Configures an USART peripheral with the specified parameters.
|
| 92 | *
|
| 93 | *
|
| 94 | * \param usart Pointer to the USART peripheral to configure.
|
| 95 | * \param mode Desired value for the USART mode register (see the datasheet).
|
| 96 | * \param baudrate Baudrate at which the USART should operate (in Hz).
|
| 97 | * \param masterClock Frequency of the system master clock (in Hz).
|
| 98 | */
|
| 99 | void USART_Configure(Usart *usart,
|
| 100 | uint32_t mode,
|
| 101 | uint32_t baudrate,
|
| 102 | uint32_t masterClock)
|
| 103 | {
|
| 104 | /* Reset and disable receiver & transmitter*/
|
| 105 | usart->US_CR = US_CR_RSTRX | US_CR_RSTTX
|
| 106 | | US_CR_RXDIS | US_CR_TXDIS;
|
| 107 |
|
| 108 | /* Configure mode*/
|
| 109 | usart->US_MR = mode;
|
| 110 |
|
| 111 | /* Configure baudrate*/
|
| 112 | /* Asynchronous, no oversampling*/
|
| 113 | if ( ((mode & US_MR_SYNC) == 0) && ((mode & US_MR_OVER) == 0) )
|
| 114 | {
|
| 115 | usart->US_BRGR = (masterClock / baudrate) / 16;
|
| 116 | }
|
| 117 |
|
| 118 | if( ((mode & US_MR_USART_MODE_SPI_MASTER) == US_MR_USART_MODE_SPI_MASTER)
|
| 119 | || ((mode & US_MR_SYNC) == US_MR_SYNC))
|
| 120 | {
|
| 121 | if( (mode & US_MR_USCLKS_Msk) == US_MR_USCLKS_MCK)
|
| 122 | {
|
| 123 | usart->US_BRGR = masterClock / baudrate;
|
| 124 | }
|
| 125 | else
|
| 126 | {
|
| 127 | if ( (mode & US_MR_USCLKS_DIV) == US_MR_USCLKS_DIV)
|
| 128 | {
|
| 129 | usart->US_BRGR = masterClock / baudrate / 8;
|
| 130 | }
|
| 131 | }
|
| 132 | }
|
| 133 | /* TODO other modes*/
|
| 134 | }
|
| 135 | /**
|
| 136 | * \brief Enables or disables the transmitter of an USART peripheral.
|
| 137 | *
|
| 138 | *
|
| 139 | * \param usart Pointer to an USART peripheral
|
| 140 | * \param enabled If true, the transmitter is enabled; otherwise it is
|
| 141 | * disabled.
|
| 142 | */
|
| 143 | void USART_SetTransmitterEnabled(Usart *usart, uint8_t enabled)
|
| 144 | {
|
| 145 | if (enabled) {
|
| 146 |
|
| 147 | usart->US_CR = US_CR_TXEN;
|
| 148 | }
|
| 149 | else {
|
| 150 |
|
| 151 | usart->US_CR = US_CR_TXDIS;
|
| 152 | }
|
| 153 | }
|
| 154 |
|
| 155 | /**
|
| 156 | * \brief Enables or disables the receiver of an USART peripheral
|
| 157 | *
|
| 158 | *
|
| 159 | * \param usart Pointer to an USART peripheral
|
| 160 | * \param enabled If true, the receiver is enabled; otherwise it is disabled.
|
| 161 | */
|
| 162 | void USART_SetReceiverEnabled(Usart *usart,
|
| 163 | uint8_t enabled)
|
| 164 | {
|
| 165 | if (enabled) {
|
| 166 |
|
| 167 | usart->US_CR = US_CR_RXEN;
|
| 168 | }
|
| 169 | else {
|
| 170 |
|
| 171 | usart->US_CR = US_CR_RXDIS;
|
| 172 | }
|
| 173 | }
|
| 174 |
|
| 175 | /**
|
| 176 | * \brief Sends one packet of data through the specified USART peripheral. This
|
| 177 | * function operates synchronously, so it only returns when the data has been
|
| 178 | * actually sent.
|
| 179 | *
|
| 180 | *
|
| 181 | * \param usart Pointer to an USART peripheral.
|
| 182 | * \param data Data to send including 9nth bit and sync field if necessary (in
|
| 183 | * the same format as the US_THR register in the datasheet).
|
| 184 | * \param timeOut Time out value (0 = no timeout).
|
| 185 | */
|
| 186 | void USART_Write(
|
| 187 | Usart *usart,
|
| 188 | uint16_t data,
|
| 189 | volatile uint32_t timeOut)
|
| 190 | {
|
| 191 | if (timeOut == 0) {
|
| 192 |
|
| 193 | while ((usart->US_CSR & US_CSR_TXEMPTY) == 0);
|
| 194 | }
|
| 195 | else {
|
| 196 |
|
| 197 | while ((usart->US_CSR & US_CSR_TXEMPTY) == 0) {
|
| 198 |
|
| 199 | if (timeOut == 0) {
|
| 200 |
|
| 201 | TRACE_ERROR("USART_Write: Timed out.\n\r");
|
| 202 | return;
|
| 203 | }
|
| 204 | timeOut--;
|
| 205 | }
|
| 206 | }
|
| 207 |
|
| 208 | usart->US_THR = data;
|
| 209 | }
|
| 210 |
|
| 211 | /**
|
| 212 | * \brief Sends the contents of a data buffer through the specified USART peripheral.
|
| 213 | * This function returns immediately (1 if the buffer has been queued, 0
|
| 214 | * otherwise); poll the ENDTX and TXBUFE bits of the USART status register
|
| 215 | * to check for the transfer completion.
|
| 216 | *
|
| 217 | * \param usart Pointer to an USART peripheral.
|
| 218 | * \param buffer Pointer to the data buffer to send.
|
| 219 | * \param size Size of the data buffer (in bytes).
|
| 220 | */
|
| 221 | uint8_t USART_WriteBuffer(
|
| 222 | Usart *usart,
|
| 223 | void *buffer,
|
| 224 | uint32_t size)
|
| 225 | {
|
| 226 | /* Check if the first PDC bank is free*/
|
| 227 | if ((usart->US_TCR == 0) && (usart->US_TNCR == 0)) {
|
| 228 |
|
| 229 | usart->US_TPR = (uint32_t) buffer;
|
| 230 | usart->US_TCR = size;
|
| 231 | usart->US_PTCR = US_PTCR_TXTEN;
|
| 232 |
|
| 233 | return 1;
|
| 234 | }
|
| 235 | /* Check if the second PDC bank is free*/
|
| 236 | else if (usart->US_TNCR == 0) {
|
| 237 |
|
| 238 | usart->US_TNPR = (uint32_t) buffer;
|
| 239 | usart->US_TNCR = size;
|
| 240 |
|
| 241 | return 1;
|
| 242 | }
|
| 243 | else {
|
| 244 |
|
| 245 | return 0;
|
| 246 | }
|
| 247 | }
|
| 248 |
|
| 249 |
|
| 250 | /**
|
| 251 | * \brief Reads and return a packet of data on the specified USART peripheral. This
|
| 252 | * function operates asynchronously, so it waits until some data has been
|
| 253 | * received.
|
| 254 | *
|
| 255 | * \param usart Pointer to an USART peripheral.
|
| 256 | * \param timeOut Time out value (0 -> no timeout).
|
| 257 | */
|
| 258 | uint16_t USART_Read(
|
| 259 | Usart *usart,
|
| 260 | volatile uint32_t timeOut)
|
| 261 | {
|
| 262 | if (timeOut == 0) {
|
| 263 |
|
| 264 | while ((usart->US_CSR & US_CSR_RXRDY) == 0);
|
| 265 | }
|
| 266 | else {
|
| 267 |
|
| 268 | while ((usart->US_CSR & US_CSR_RXRDY) == 0) {
|
| 269 |
|
| 270 | if (timeOut == 0) {
|
| 271 |
|
| 272 | TRACE_ERROR( "USART_Read: Timed out.\n\r" ) ;
|
| 273 | return 0;
|
| 274 | }
|
| 275 | timeOut--;
|
| 276 | }
|
| 277 | }
|
| 278 |
|
| 279 | return usart->US_RHR;
|
| 280 | }
|
| 281 |
|
| 282 | /**
|
| 283 | * \brief Reads data from an USART peripheral, filling the provided buffer until it
|
| 284 | * becomes full. This function returns immediately with 1 if the buffer has
|
| 285 | * been queued for transmission; otherwise 0.
|
| 286 | *
|
| 287 | * \param usart Pointer to an USART peripheral.
|
| 288 | * \param buffer Pointer to the buffer where the received data will be stored.
|
| 289 | * \param size Size of the data buffer (in bytes).
|
| 290 | */
|
| 291 | uint8_t USART_ReadBuffer(Usart *usart,
|
| 292 | void *buffer,
|
| 293 | uint32_t size)
|
| 294 | {
|
| 295 | /* Check if the first PDC bank is free*/
|
| 296 | if ((usart->US_RCR == 0) && (usart->US_RNCR == 0)) {
|
| 297 |
|
| 298 | usart->US_RPR = (uint32_t) buffer;
|
| 299 | usart->US_RCR = size;
|
| 300 | usart->US_PTCR = US_PTCR_RXTEN;
|
| 301 |
|
| 302 | return 1;
|
| 303 | }
|
| 304 | /* Check if the second PDC bank is free*/
|
| 305 | else if (usart->US_RNCR == 0) {
|
| 306 |
|
| 307 | usart->US_RNPR = (uint32_t) buffer;
|
| 308 | usart->US_RNCR = size;
|
| 309 |
|
| 310 | return 1;
|
| 311 | }
|
| 312 | else {
|
| 313 |
|
| 314 | return 0;
|
| 315 | }
|
| 316 | }
|
| 317 |
|
| 318 | /**
|
| 319 | * \brief Returns 1 if some data has been received and can be read from an USART;
|
| 320 | * otherwise returns 0.
|
| 321 | *
|
| 322 | * \param usart Pointer to an Usart instance.
|
| 323 | */
|
| 324 | uint8_t USART_IsDataAvailable(Usart *usart)
|
| 325 | {
|
| 326 | if ((usart->US_CSR & US_CSR_RXRDY) != 0) {
|
| 327 |
|
| 328 | return 1;
|
| 329 | }
|
| 330 | else {
|
| 331 |
|
| 332 | return 0;
|
| 333 | }
|
| 334 | }
|
| 335 |
|
| 336 | /**
|
| 337 | * \brief Sets the filter value for the IRDA demodulator.
|
| 338 | *
|
| 339 | * \param pUsart Pointer to an Usart instance.
|
| 340 | * \param filter Filter value.
|
| 341 | */
|
| 342 | void USART_SetIrdaFilter(Usart *pUsart, uint8_t filter)
|
| 343 | {
|
| 344 | assert( pUsart != NULL ) ;
|
| 345 |
|
| 346 | pUsart->US_IF = filter;
|
| 347 | }
|
| 348 |
|
| 349 | /**
|
| 350 | * \brief Sends one packet of data through the specified USART peripheral. This
|
| 351 | * function operates synchronously, so it only returns when the data has been
|
| 352 | * actually sent.
|
| 353 | *
|
| 354 | * \param usart Pointer to an USART peripheral.
|
| 355 | * \param c Character to send
|
| 356 | */
|
| 357 | void USART_PutChar(
|
| 358 | Usart *usart,
|
| 359 | uint8_t c)
|
| 360 | {
|
| 361 | /* Wait for the transmitter to be ready*/
|
| 362 | while ((usart->US_CSR & US_CSR_TXEMPTY) == 0);
|
| 363 |
|
| 364 | /* Send character*/
|
| 365 | usart->US_THR = c;
|
| 366 |
|
| 367 | /* Wait for the transfer to complete*/
|
| 368 | while ((usart->US_CSR & US_CSR_TXEMPTY) == 0);
|
| 369 | }
|
| 370 |
|
| 371 | /**
|
| 372 | * \brief Return 1 if a character can be read in USART
|
| 373 | */
|
| 374 | uint32_t USART_IsRxReady(Usart *usart)
|
| 375 | {
|
| 376 | return (usart->US_CSR & US_CSR_RXRDY);
|
| 377 | }
|
| 378 | /**
|
| 379 | * \brief Get present status
|
| 380 | */
|
| 381 | uint32_t USART_GetStatus(Usart *usart)
|
| 382 | {
|
| 383 | return usart->US_CSR;
|
| 384 | }
|
| 385 | /**
|
| 386 | * \brief Enable interrupt
|
| 387 | */
|
| 388 | void USART_EnableIt(Usart *usart,uint32_t mode)
|
| 389 | {
|
| 390 | usart->US_IER = mode;
|
| 391 | }
|
| 392 | /**
|
| 393 | * \brief Disable interrupt
|
| 394 | */
|
| 395 | void USART_DisableIt(Usart *usart,uint32_t mode)
|
| 396 | {
|
| 397 | usart->US_IDR = mode;
|
| 398 | }
|
| 399 | /**
|
| 400 | * \brief Reads and returns a character from the USART.
|
| 401 | *
|
| 402 | * \note This function is synchronous (i.e. uses polling).
|
| 403 | * \param usart Pointer to an USART peripheral.
|
| 404 | * \return Character received.
|
| 405 | */
|
| 406 | uint8_t USART_GetChar(Usart *usart)
|
| 407 | {
|
| 408 | while ((usart->US_CSR & US_CSR_RXRDY) == 0);
|
| 409 | return usart->US_RHR;
|
| 410 | }
|