mbed library sources

Dependents:   Encrypted my_mbed lklk CyaSSL_DTLS_Cellular ... more

Superseded

This library was superseded by mbed-dev - https://os.mbed.com/users/mbed_official/code/mbed-dev/.

Development branch of the mbed library sources. This library is kept in synch with the latest changes from the mbed SDK and it is not guaranteed to work.

If you are looking for a stable and tested release, please import one of the official mbed library releases:

Import librarymbed

The official Mbed 2 C/C++ SDK provides the software platform and libraries to build your applications.

Committer:
mbed_official
Date:
Wed Jul 01 09:45:11 2015 +0100
Revision:
579:53297373a894
Child:
592:a274ee790e56
Synchronized with git revision d5b4d2ab9c47edb4dc5776e7177b0c2263459081

Full URL: https://github.com/mbedmicro/mbed/commit/d5b4d2ab9c47edb4dc5776e7177b0c2263459081/

Initial version of drivers for SAMR21

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mbed_official 579:53297373a894 1 /**
mbed_official 579:53297373a894 2 * \file
mbed_official 579:53297373a894 3 *
mbed_official 579:53297373a894 4 * \brief SAM SERCOM USART Driver
mbed_official 579:53297373a894 5 *
mbed_official 579:53297373a894 6 * Copyright (C) 2012-2014 Atmel Corporation. All rights reserved.
mbed_official 579:53297373a894 7 *
mbed_official 579:53297373a894 8 * \asf_license_start
mbed_official 579:53297373a894 9 *
mbed_official 579:53297373a894 10 * \page License
mbed_official 579:53297373a894 11 *
mbed_official 579:53297373a894 12 * Redistribution and use in source and binary forms, with or without
mbed_official 579:53297373a894 13 * modification, are permitted provided that the following conditions are met:
mbed_official 579:53297373a894 14 *
mbed_official 579:53297373a894 15 * 1. Redistributions of source code must retain the above copyright notice,
mbed_official 579:53297373a894 16 * this list of conditions and the following disclaimer.
mbed_official 579:53297373a894 17 *
mbed_official 579:53297373a894 18 * 2. Redistributions in binary form must reproduce the above copyright notice,
mbed_official 579:53297373a894 19 * this list of conditions and the following disclaimer in the documentation
mbed_official 579:53297373a894 20 * and/or other materials provided with the distribution.
mbed_official 579:53297373a894 21 *
mbed_official 579:53297373a894 22 * 3. The name of Atmel may not be used to endorse or promote products derived
mbed_official 579:53297373a894 23 * from this software without specific prior written permission.
mbed_official 579:53297373a894 24 *
mbed_official 579:53297373a894 25 * 4. This software may only be redistributed and used in connection with an
mbed_official 579:53297373a894 26 * Atmel microcontroller product.
mbed_official 579:53297373a894 27 *
mbed_official 579:53297373a894 28 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
mbed_official 579:53297373a894 29 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
mbed_official 579:53297373a894 30 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
mbed_official 579:53297373a894 31 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
mbed_official 579:53297373a894 32 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
mbed_official 579:53297373a894 33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
mbed_official 579:53297373a894 34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
mbed_official 579:53297373a894 35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
mbed_official 579:53297373a894 36 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
mbed_official 579:53297373a894 37 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
mbed_official 579:53297373a894 38 * POSSIBILITY OF SUCH DAMAGE.
mbed_official 579:53297373a894 39 *
mbed_official 579:53297373a894 40 * \asf_license_stop
mbed_official 579:53297373a894 41 *
mbed_official 579:53297373a894 42 */
mbed_official 579:53297373a894 43 /**
mbed_official 579:53297373a894 44 * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
mbed_official 579:53297373a894 45 */
mbed_official 579:53297373a894 46 #include "usart.h"
mbed_official 579:53297373a894 47 #include <pinmux.h>
mbed_official 579:53297373a894 48 #if USART_CALLBACK_MODE == true
mbed_official 579:53297373a894 49 # include "usart_interrupt.h"
mbed_official 579:53297373a894 50 #endif
mbed_official 579:53297373a894 51
mbed_official 579:53297373a894 52 /**
mbed_official 579:53297373a894 53 * \internal
mbed_official 579:53297373a894 54 * Set Configuration of the USART module
mbed_official 579:53297373a894 55 */
mbed_official 579:53297373a894 56 static enum status_code _usart_set_config(
mbed_official 579:53297373a894 57 struct usart_module *const module,
mbed_official 579:53297373a894 58 const struct usart_config *const config)
mbed_official 579:53297373a894 59 {
mbed_official 579:53297373a894 60 /* Sanity check arguments */
mbed_official 579:53297373a894 61 Assert(module);
mbed_official 579:53297373a894 62 Assert(module->hw);
mbed_official 579:53297373a894 63
mbed_official 579:53297373a894 64 /* Get a pointer to the hardware module instance */
mbed_official 579:53297373a894 65 SercomUsart *const usart_hw = &(module->hw->USART);
mbed_official 579:53297373a894 66
mbed_official 579:53297373a894 67 /* Index for generic clock */
mbed_official 579:53297373a894 68 uint32_t sercom_index = _sercom_get_sercom_inst_index(module->hw);
mbed_official 579:53297373a894 69 uint32_t gclk_index = sercom_index + SERCOM0_GCLK_ID_CORE;
mbed_official 579:53297373a894 70
mbed_official 579:53297373a894 71 /* Cache new register values to minimize the number of register writes */
mbed_official 579:53297373a894 72 uint32_t ctrla = 0;
mbed_official 579:53297373a894 73 uint32_t ctrlb = 0;
mbed_official 579:53297373a894 74 uint16_t baud = 0;
mbed_official 579:53297373a894 75
mbed_official 579:53297373a894 76 enum sercom_asynchronous_operation_mode mode = SERCOM_ASYNC_OPERATION_MODE_ARITHMETIC;
mbed_official 579:53297373a894 77 enum sercom_asynchronous_sample_num sample_num = SERCOM_ASYNC_SAMPLE_NUM_16;
mbed_official 579:53297373a894 78
mbed_official 579:53297373a894 79 #ifdef FEATURE_USART_OVER_SAMPLE
mbed_official 579:53297373a894 80 switch (config->sample_rate) {
mbed_official 579:53297373a894 81 case USART_SAMPLE_RATE_16X_ARITHMETIC:
mbed_official 579:53297373a894 82 mode = SERCOM_ASYNC_OPERATION_MODE_ARITHMETIC;
mbed_official 579:53297373a894 83 sample_num = SERCOM_ASYNC_SAMPLE_NUM_16;
mbed_official 579:53297373a894 84 break;
mbed_official 579:53297373a894 85 case USART_SAMPLE_RATE_8X_ARITHMETIC:
mbed_official 579:53297373a894 86 mode = SERCOM_ASYNC_OPERATION_MODE_ARITHMETIC;
mbed_official 579:53297373a894 87 sample_num = SERCOM_ASYNC_SAMPLE_NUM_8;
mbed_official 579:53297373a894 88 break;
mbed_official 579:53297373a894 89 case USART_SAMPLE_RATE_3X_ARITHMETIC:
mbed_official 579:53297373a894 90 mode = SERCOM_ASYNC_OPERATION_MODE_ARITHMETIC;
mbed_official 579:53297373a894 91 sample_num = SERCOM_ASYNC_SAMPLE_NUM_3;
mbed_official 579:53297373a894 92 break;
mbed_official 579:53297373a894 93 case USART_SAMPLE_RATE_16X_FRACTIONAL:
mbed_official 579:53297373a894 94 mode = SERCOM_ASYNC_OPERATION_MODE_FRACTIONAL;
mbed_official 579:53297373a894 95 sample_num = SERCOM_ASYNC_SAMPLE_NUM_16;
mbed_official 579:53297373a894 96 break;
mbed_official 579:53297373a894 97 case USART_SAMPLE_RATE_8X_FRACTIONAL:
mbed_official 579:53297373a894 98 mode = SERCOM_ASYNC_OPERATION_MODE_FRACTIONAL;
mbed_official 579:53297373a894 99 sample_num = SERCOM_ASYNC_SAMPLE_NUM_8;
mbed_official 579:53297373a894 100 break;
mbed_official 579:53297373a894 101 }
mbed_official 579:53297373a894 102 #endif
mbed_official 579:53297373a894 103
mbed_official 579:53297373a894 104 /* Set data order, internal muxing, and clock polarity */
mbed_official 579:53297373a894 105 ctrla = (uint32_t)config->data_order |
mbed_official 579:53297373a894 106 (uint32_t)config->mux_setting |
mbed_official 579:53297373a894 107 #ifdef FEATURE_USART_OVER_SAMPLE
mbed_official 579:53297373a894 108 config->sample_adjustment |
mbed_official 579:53297373a894 109 config->sample_rate |
mbed_official 579:53297373a894 110 #endif
mbed_official 579:53297373a894 111 #ifdef FEATURE_USART_IMMEDIATE_BUFFER_OVERFLOW_NOTIFICATION
mbed_official 579:53297373a894 112 (config->immediate_buffer_overflow_notification << SERCOM_USART_CTRLA_IBON_Pos) |
mbed_official 579:53297373a894 113 #endif
mbed_official 579:53297373a894 114 (config->clock_polarity_inverted << SERCOM_USART_CTRLA_CPOL_Pos);
mbed_official 579:53297373a894 115
mbed_official 579:53297373a894 116 enum status_code status_code = STATUS_OK;
mbed_official 579:53297373a894 117
mbed_official 579:53297373a894 118 /* Get baud value from mode and clock */
mbed_official 579:53297373a894 119 switch (config->transfer_mode) {
mbed_official 579:53297373a894 120 case USART_TRANSFER_SYNCHRONOUSLY:
mbed_official 579:53297373a894 121 if (!config->use_external_clock) {
mbed_official 579:53297373a894 122 status_code = _sercom_get_sync_baud_val(config->baudrate,
mbed_official 579:53297373a894 123 system_gclk_chan_get_hz(gclk_index), &baud);
mbed_official 579:53297373a894 124 }
mbed_official 579:53297373a894 125
mbed_official 579:53297373a894 126 break;
mbed_official 579:53297373a894 127
mbed_official 579:53297373a894 128 case USART_TRANSFER_ASYNCHRONOUSLY:
mbed_official 579:53297373a894 129 if (config->use_external_clock) {
mbed_official 579:53297373a894 130 status_code =
mbed_official 579:53297373a894 131 _sercom_get_async_baud_val(config->baudrate,
mbed_official 579:53297373a894 132 config->ext_clock_freq, &baud, mode, sample_num);
mbed_official 579:53297373a894 133 } else {
mbed_official 579:53297373a894 134 status_code =
mbed_official 579:53297373a894 135 _sercom_get_async_baud_val(config->baudrate,
mbed_official 579:53297373a894 136 system_gclk_chan_get_hz(gclk_index), &baud, mode, sample_num);
mbed_official 579:53297373a894 137 }
mbed_official 579:53297373a894 138
mbed_official 579:53297373a894 139 break;
mbed_official 579:53297373a894 140 }
mbed_official 579:53297373a894 141
mbed_official 579:53297373a894 142 /* Check if calculating the baudrate failed */
mbed_official 579:53297373a894 143 if (status_code != STATUS_OK) {
mbed_official 579:53297373a894 144 /* Abort */
mbed_official 579:53297373a894 145 return status_code;
mbed_official 579:53297373a894 146 }
mbed_official 579:53297373a894 147
mbed_official 579:53297373a894 148 #ifdef FEATURE_USART_IRDA
mbed_official 579:53297373a894 149 if(config->encoding_format_enable) {
mbed_official 579:53297373a894 150 usart_hw->RXPL.reg = config->receive_pulse_length;
mbed_official 579:53297373a894 151 }
mbed_official 579:53297373a894 152 #endif
mbed_official 579:53297373a894 153
mbed_official 579:53297373a894 154 /* Wait until synchronization is complete */
mbed_official 579:53297373a894 155 _usart_wait_for_sync(module);
mbed_official 579:53297373a894 156
mbed_official 579:53297373a894 157 /*Set baud val */
mbed_official 579:53297373a894 158 usart_hw->BAUD.reg = baud;
mbed_official 579:53297373a894 159
mbed_official 579:53297373a894 160 /* Set sample mode */
mbed_official 579:53297373a894 161 ctrla |= config->transfer_mode;
mbed_official 579:53297373a894 162
mbed_official 579:53297373a894 163 if (config->use_external_clock == false) {
mbed_official 579:53297373a894 164 ctrla |= SERCOM_USART_CTRLA_MODE(0x1);
mbed_official 579:53297373a894 165 } else {
mbed_official 579:53297373a894 166 ctrla |= SERCOM_USART_CTRLA_MODE(0x0);
mbed_official 579:53297373a894 167 }
mbed_official 579:53297373a894 168
mbed_official 579:53297373a894 169 /* Set stopbits, character size and enable transceivers */
mbed_official 579:53297373a894 170 ctrlb = (uint32_t)config->stopbits | (uint32_t)config->character_size |
mbed_official 579:53297373a894 171 #ifdef FEATURE_USART_IRDA
mbed_official 579:53297373a894 172 (config->encoding_format_enable << SERCOM_USART_CTRLB_ENC_Pos) |
mbed_official 579:53297373a894 173 #endif
mbed_official 579:53297373a894 174 #ifdef FEATURE_USART_START_FRAME_DECTION
mbed_official 579:53297373a894 175 (config->start_frame_detection_enable << SERCOM_USART_CTRLB_SFDE_Pos) |
mbed_official 579:53297373a894 176 #endif
mbed_official 579:53297373a894 177 #ifdef FEATURE_USART_COLLISION_DECTION
mbed_official 579:53297373a894 178 (config->collision_detection_enable << SERCOM_USART_CTRLB_COLDEN_Pos) |
mbed_official 579:53297373a894 179 #endif
mbed_official 579:53297373a894 180 (config->receiver_enable << SERCOM_USART_CTRLB_RXEN_Pos) |
mbed_official 579:53297373a894 181 (config->transmitter_enable << SERCOM_USART_CTRLB_TXEN_Pos);
mbed_official 579:53297373a894 182
mbed_official 579:53297373a894 183 /* Check parity mode bits */
mbed_official 579:53297373a894 184 if (config->parity != USART_PARITY_NONE) {
mbed_official 579:53297373a894 185 #ifdef FEATURE_USART_LIN_SLAVE
mbed_official 579:53297373a894 186 if(config->lin_slave_enable) {
mbed_official 579:53297373a894 187 ctrla |= SERCOM_USART_CTRLA_FORM(0x5);
mbed_official 579:53297373a894 188 } else {
mbed_official 579:53297373a894 189 ctrla |= SERCOM_USART_CTRLA_FORM(1);
mbed_official 579:53297373a894 190 }
mbed_official 579:53297373a894 191 #else
mbed_official 579:53297373a894 192 ctrla |= SERCOM_USART_CTRLA_FORM(1);
mbed_official 579:53297373a894 193 #endif
mbed_official 579:53297373a894 194 ctrlb |= config->parity;
mbed_official 579:53297373a894 195 } else {
mbed_official 579:53297373a894 196 #ifdef FEATURE_USART_LIN_SLAVE
mbed_official 579:53297373a894 197 if(config->lin_slave_enable) {
mbed_official 579:53297373a894 198 ctrla |= SERCOM_USART_CTRLA_FORM(0x4);
mbed_official 579:53297373a894 199 } else {
mbed_official 579:53297373a894 200 ctrla |= SERCOM_USART_CTRLA_FORM(0);
mbed_official 579:53297373a894 201 }
mbed_official 579:53297373a894 202 #else
mbed_official 579:53297373a894 203 ctrla |= SERCOM_USART_CTRLA_FORM(0);
mbed_official 579:53297373a894 204 #endif
mbed_official 579:53297373a894 205 }
mbed_official 579:53297373a894 206
mbed_official 579:53297373a894 207 /* Set whether module should run in standby. */
mbed_official 579:53297373a894 208 if (config->run_in_standby || system_is_debugger_present()) {
mbed_official 579:53297373a894 209 ctrla |= SERCOM_USART_CTRLA_RUNSTDBY;
mbed_official 579:53297373a894 210 }
mbed_official 579:53297373a894 211
mbed_official 579:53297373a894 212 /* Wait until synchronization is complete */
mbed_official 579:53297373a894 213 _usart_wait_for_sync(module);
mbed_official 579:53297373a894 214
mbed_official 579:53297373a894 215 /* Write configuration to CTRLB */
mbed_official 579:53297373a894 216 usart_hw->CTRLB.reg = ctrlb;
mbed_official 579:53297373a894 217
mbed_official 579:53297373a894 218 /* Wait until synchronization is complete */
mbed_official 579:53297373a894 219 _usart_wait_for_sync(module);
mbed_official 579:53297373a894 220
mbed_official 579:53297373a894 221 /* Write configuration to CTRLA */
mbed_official 579:53297373a894 222 usart_hw->CTRLA.reg = ctrla;
mbed_official 579:53297373a894 223
mbed_official 579:53297373a894 224 return STATUS_OK;
mbed_official 579:53297373a894 225 }
mbed_official 579:53297373a894 226
mbed_official 579:53297373a894 227 /**
mbed_official 579:53297373a894 228 * \brief Initializes the device
mbed_official 579:53297373a894 229 *
mbed_official 579:53297373a894 230 * Initializes the USART device based on the setting specified in the
mbed_official 579:53297373a894 231 * configuration struct.
mbed_official 579:53297373a894 232 *
mbed_official 579:53297373a894 233 * \param[out] module Pointer to USART device
mbed_official 579:53297373a894 234 * \param[in] hw Pointer to USART hardware instance
mbed_official 579:53297373a894 235 * \param[in] config Pointer to configuration struct
mbed_official 579:53297373a894 236 *
mbed_official 579:53297373a894 237 * \return Status of the initialization.
mbed_official 579:53297373a894 238 *
mbed_official 579:53297373a894 239 * \retval STATUS_OK The initialization was successful
mbed_official 579:53297373a894 240 * \retval STATUS_BUSY The USART module is busy
mbed_official 579:53297373a894 241 * resetting
mbed_official 579:53297373a894 242 * \retval STATUS_ERR_DENIED The USART have not been disabled in
mbed_official 579:53297373a894 243 * advance of initialization
mbed_official 579:53297373a894 244 * \retval STATUS_ERR_INVALID_ARG The configuration struct contains
mbed_official 579:53297373a894 245 * invalid configuration
mbed_official 579:53297373a894 246 * \retval STATUS_ERR_ALREADY_INITIALIZED The SERCOM instance has already been
mbed_official 579:53297373a894 247 * initialized with different clock
mbed_official 579:53297373a894 248 * configuration
mbed_official 579:53297373a894 249 * \retval STATUS_ERR_BAUD_UNAVAILABLE The BAUD rate given by the
mbed_official 579:53297373a894 250 * configuration
mbed_official 579:53297373a894 251 * struct cannot be reached with
mbed_official 579:53297373a894 252 * the current clock configuration
mbed_official 579:53297373a894 253 */
mbed_official 579:53297373a894 254 enum status_code usart_init(
mbed_official 579:53297373a894 255 struct usart_module *const module,
mbed_official 579:53297373a894 256 Sercom *const hw,
mbed_official 579:53297373a894 257 const struct usart_config *const config)
mbed_official 579:53297373a894 258 {
mbed_official 579:53297373a894 259 /* Sanity check arguments */
mbed_official 579:53297373a894 260 Assert(module);
mbed_official 579:53297373a894 261 Assert(hw);
mbed_official 579:53297373a894 262 Assert(config);
mbed_official 579:53297373a894 263
mbed_official 579:53297373a894 264 enum status_code status_code = STATUS_OK;
mbed_official 579:53297373a894 265
mbed_official 579:53297373a894 266 /* Assign module pointer to software instance struct */
mbed_official 579:53297373a894 267 module->hw = hw;
mbed_official 579:53297373a894 268
mbed_official 579:53297373a894 269 /* Get a pointer to the hardware module instance */
mbed_official 579:53297373a894 270 SercomUsart *const usart_hw = &(module->hw->USART);
mbed_official 579:53297373a894 271
mbed_official 579:53297373a894 272 uint32_t sercom_index = _sercom_get_sercom_inst_index(module->hw);
mbed_official 579:53297373a894 273 #if (SAML21)
mbed_official 579:53297373a894 274 uint32_t pm_index = sercom_index + MCLK_APBCMASK_SERCOM0_Pos;
mbed_official 579:53297373a894 275 #else
mbed_official 579:53297373a894 276 uint32_t pm_index = sercom_index + PM_APBCMASK_SERCOM0_Pos;
mbed_official 579:53297373a894 277 #endif
mbed_official 579:53297373a894 278 uint32_t gclk_index = sercom_index + SERCOM0_GCLK_ID_CORE;
mbed_official 579:53297373a894 279
mbed_official 579:53297373a894 280 if (usart_hw->CTRLA.reg & SERCOM_USART_CTRLA_SWRST) {
mbed_official 579:53297373a894 281 /* The module is busy resetting itself */
mbed_official 579:53297373a894 282 return STATUS_BUSY;
mbed_official 579:53297373a894 283 }
mbed_official 579:53297373a894 284
mbed_official 579:53297373a894 285 if (usart_hw->CTRLA.reg & SERCOM_USART_CTRLA_ENABLE) {
mbed_official 579:53297373a894 286 /* Check the module is enabled */
mbed_official 579:53297373a894 287 return STATUS_ERR_DENIED;
mbed_official 579:53297373a894 288 }
mbed_official 579:53297373a894 289
mbed_official 579:53297373a894 290 /* Turn on module in PM */
mbed_official 579:53297373a894 291 system_apb_clock_set_mask(SYSTEM_CLOCK_APB_APBC, 1 << pm_index);
mbed_official 579:53297373a894 292
mbed_official 579:53297373a894 293 /* Set up the GCLK for the module */
mbed_official 579:53297373a894 294 struct system_gclk_chan_config gclk_chan_conf;
mbed_official 579:53297373a894 295 system_gclk_chan_get_config_defaults(&gclk_chan_conf);
mbed_official 579:53297373a894 296 gclk_chan_conf.source_generator = config->generator_source;
mbed_official 579:53297373a894 297 system_gclk_chan_set_config(gclk_index, &gclk_chan_conf);
mbed_official 579:53297373a894 298 system_gclk_chan_enable(gclk_index);
mbed_official 579:53297373a894 299 sercom_set_gclk_generator(config->generator_source, false);
mbed_official 579:53297373a894 300
mbed_official 579:53297373a894 301 /* Set character size */
mbed_official 579:53297373a894 302 module->character_size = config->character_size;
mbed_official 579:53297373a894 303
mbed_official 579:53297373a894 304 /* Set transmitter and receiver status */
mbed_official 579:53297373a894 305 module->receiver_enabled = config->receiver_enable;
mbed_official 579:53297373a894 306 module->transmitter_enabled = config->transmitter_enable;
mbed_official 579:53297373a894 307
mbed_official 579:53297373a894 308 #ifdef FEATURE_USART_LIN_SLAVE
mbed_official 579:53297373a894 309 module->lin_slave_enabled = config->lin_slave_enable;
mbed_official 579:53297373a894 310 #endif
mbed_official 579:53297373a894 311 #ifdef FEATURE_USART_START_FRAME_DECTION
mbed_official 579:53297373a894 312 module->start_frame_detection_enabled = config->start_frame_detection_enable;
mbed_official 579:53297373a894 313 #endif
mbed_official 579:53297373a894 314 /* Set configuration according to the config struct */
mbed_official 579:53297373a894 315 status_code = _usart_set_config(module, config);
mbed_official 579:53297373a894 316 if(status_code != STATUS_OK) {
mbed_official 579:53297373a894 317 return status_code;
mbed_official 579:53297373a894 318 }
mbed_official 579:53297373a894 319
mbed_official 579:53297373a894 320 struct system_pinmux_config pin_conf;
mbed_official 579:53297373a894 321 system_pinmux_get_config_defaults(&pin_conf);
mbed_official 579:53297373a894 322 pin_conf.direction = SYSTEM_PINMUX_PIN_DIR_INPUT;
mbed_official 579:53297373a894 323 pin_conf.input_pull = SYSTEM_PINMUX_PIN_PULL_NONE;
mbed_official 579:53297373a894 324
mbed_official 579:53297373a894 325 uint32_t pad_pinmuxes[] = {
mbed_official 579:53297373a894 326 config->pinmux_pad0, config->pinmux_pad1,
mbed_official 579:53297373a894 327 config->pinmux_pad2, config->pinmux_pad3
mbed_official 579:53297373a894 328 };
mbed_official 579:53297373a894 329
mbed_official 579:53297373a894 330 /* Configure the SERCOM pins according to the user configuration */
mbed_official 579:53297373a894 331 for (uint8_t pad = 0; pad < 4; pad++) {
mbed_official 579:53297373a894 332 uint32_t current_pinmux = pad_pinmuxes[pad];
mbed_official 579:53297373a894 333
mbed_official 579:53297373a894 334 if (current_pinmux == PINMUX_DEFAULT) {
mbed_official 579:53297373a894 335 current_pinmux = _sercom_get_default_pad(hw, pad);
mbed_official 579:53297373a894 336 }
mbed_official 579:53297373a894 337
mbed_official 579:53297373a894 338 if (current_pinmux != PINMUX_UNUSED) {
mbed_official 579:53297373a894 339 pin_conf.mux_position = current_pinmux & 0xFFFF;
mbed_official 579:53297373a894 340 system_pinmux_pin_set_config(current_pinmux >> 16, &pin_conf);
mbed_official 579:53297373a894 341 }
mbed_official 579:53297373a894 342 }
mbed_official 579:53297373a894 343
mbed_official 579:53297373a894 344 #if USART_CALLBACK_MODE == true
mbed_official 579:53297373a894 345 /* Initialize parameters */
mbed_official 579:53297373a894 346 for (uint32_t i = 0; i < USART_CALLBACK_N; i++) {
mbed_official 579:53297373a894 347 module->callback[i] = NULL;
mbed_official 579:53297373a894 348 }
mbed_official 579:53297373a894 349
mbed_official 579:53297373a894 350 module->tx_buffer_ptr = NULL;
mbed_official 579:53297373a894 351 module->rx_buffer_ptr = NULL;
mbed_official 579:53297373a894 352 module->remaining_tx_buffer_length = 0x0000;
mbed_official 579:53297373a894 353 module->remaining_rx_buffer_length = 0x0000;
mbed_official 579:53297373a894 354 module->callback_reg_mask = 0x00;
mbed_official 579:53297373a894 355 module->callback_enable_mask = 0x00;
mbed_official 579:53297373a894 356 module->rx_status = STATUS_OK;
mbed_official 579:53297373a894 357 module->tx_status = STATUS_OK;
mbed_official 579:53297373a894 358
mbed_official 579:53297373a894 359 /* Set interrupt handler and register USART software module struct in
mbed_official 579:53297373a894 360 * look-up table */
mbed_official 579:53297373a894 361 uint8_t instance_index = _sercom_get_sercom_inst_index(module->hw);
mbed_official 579:53297373a894 362 _sercom_set_handler(instance_index, _usart_interrupt_handler);
mbed_official 579:53297373a894 363 _sercom_instances[instance_index] = module;
mbed_official 579:53297373a894 364 #endif
mbed_official 579:53297373a894 365
mbed_official 579:53297373a894 366 return status_code;
mbed_official 579:53297373a894 367 }
mbed_official 579:53297373a894 368
mbed_official 579:53297373a894 369 /**
mbed_official 579:53297373a894 370 * \brief Transmit a character via the USART
mbed_official 579:53297373a894 371 *
mbed_official 579:53297373a894 372 * This blocking function will transmit a single character via the
mbed_official 579:53297373a894 373 * USART.
mbed_official 579:53297373a894 374 *
mbed_official 579:53297373a894 375 * \param[in] module Pointer to the software instance struct
mbed_official 579:53297373a894 376 * \param[in] tx_data Data to transfer
mbed_official 579:53297373a894 377 *
mbed_official 579:53297373a894 378 * \return Status of the operation.
mbed_official 579:53297373a894 379 * \retval STATUS_OK If the operation was completed
mbed_official 579:53297373a894 380 * \retval STATUS_BUSY If the operation was not completed, due to the USART
mbed_official 579:53297373a894 381 * module being busy
mbed_official 579:53297373a894 382 * \retval STATUS_ERR_DENIED If the transmitter is not enabled
mbed_official 579:53297373a894 383 */
mbed_official 579:53297373a894 384 enum status_code usart_write_wait(
mbed_official 579:53297373a894 385 struct usart_module *const module,
mbed_official 579:53297373a894 386 const uint16_t tx_data)
mbed_official 579:53297373a894 387 {
mbed_official 579:53297373a894 388 /* Sanity check arguments */
mbed_official 579:53297373a894 389 Assert(module);
mbed_official 579:53297373a894 390 Assert(module->hw);
mbed_official 579:53297373a894 391
mbed_official 579:53297373a894 392 /* Get a pointer to the hardware module instance */
mbed_official 579:53297373a894 393 SercomUsart *const usart_hw = &(module->hw->USART);
mbed_official 579:53297373a894 394
mbed_official 579:53297373a894 395 /* Check that the transmitter is enabled */
mbed_official 579:53297373a894 396 if (!(module->transmitter_enabled)) {
mbed_official 579:53297373a894 397 return STATUS_ERR_DENIED;
mbed_official 579:53297373a894 398 }
mbed_official 579:53297373a894 399
mbed_official 579:53297373a894 400 #if USART_CALLBACK_MODE == true
mbed_official 579:53297373a894 401 /* Check if the USART is busy doing asynchronous operation. */
mbed_official 579:53297373a894 402 if (module->remaining_tx_buffer_length > 0) {
mbed_official 579:53297373a894 403 return STATUS_BUSY;
mbed_official 579:53297373a894 404 }
mbed_official 579:53297373a894 405
mbed_official 579:53297373a894 406 #else
mbed_official 579:53297373a894 407 /* Check if USART is ready for new data */
mbed_official 579:53297373a894 408 if (!(usart_hw->INTFLAG.reg & SERCOM_USART_INTFLAG_DRE)) {
mbed_official 579:53297373a894 409 /* Return error code */
mbed_official 579:53297373a894 410 return STATUS_BUSY;
mbed_official 579:53297373a894 411 }
mbed_official 579:53297373a894 412 #endif
mbed_official 579:53297373a894 413
mbed_official 579:53297373a894 414 /* Wait until synchronization is complete */
mbed_official 579:53297373a894 415 _usart_wait_for_sync(module);
mbed_official 579:53297373a894 416
mbed_official 579:53297373a894 417 /* Write data to USART module */
mbed_official 579:53297373a894 418 usart_hw->DATA.reg = tx_data;
mbed_official 579:53297373a894 419
mbed_official 579:53297373a894 420 while (!(usart_hw->INTFLAG.reg & SERCOM_USART_INTFLAG_TXC)) {
mbed_official 579:53297373a894 421 /* Wait until data is sent */
mbed_official 579:53297373a894 422 }
mbed_official 579:53297373a894 423
mbed_official 579:53297373a894 424 return STATUS_OK;
mbed_official 579:53297373a894 425 }
mbed_official 579:53297373a894 426
mbed_official 579:53297373a894 427 /**
mbed_official 579:53297373a894 428 * \brief Receive a character via the USART
mbed_official 579:53297373a894 429 *
mbed_official 579:53297373a894 430 * This blocking function will receive a character via the USART.
mbed_official 579:53297373a894 431 *
mbed_official 579:53297373a894 432 * \param[in] module Pointer to the software instance struct
mbed_official 579:53297373a894 433 * \param[out] rx_data Pointer to received data
mbed_official 579:53297373a894 434 *
mbed_official 579:53297373a894 435 * \return Status of the operation.
mbed_official 579:53297373a894 436 * \retval STATUS_OK If the operation was completed
mbed_official 579:53297373a894 437 * \retval STATUS_BUSY If the operation was not completed,
mbed_official 579:53297373a894 438 * due to the USART module being busy
mbed_official 579:53297373a894 439 * \retval STATUS_ERR_BAD_FORMAT If the operation was not completed,
mbed_official 579:53297373a894 440 * due to configuration mismatch between USART
mbed_official 579:53297373a894 441 * and the sender
mbed_official 579:53297373a894 442 * \retval STATUS_ERR_BAD_OVERFLOW If the operation was not completed,
mbed_official 579:53297373a894 443 * due to the baudrate being too low or the
mbed_official 579:53297373a894 444 * system frequency being too high
mbed_official 579:53297373a894 445 * \retval STATUS_ERR_BAD_DATA If the operation was not completed, due to
mbed_official 579:53297373a894 446 * data being corrupted
mbed_official 579:53297373a894 447 * \retval STATUS_ERR_DENIED If the receiver is not enabled
mbed_official 579:53297373a894 448 */
mbed_official 579:53297373a894 449 enum status_code usart_read_wait(
mbed_official 579:53297373a894 450 struct usart_module *const module,
mbed_official 579:53297373a894 451 uint16_t *const rx_data)
mbed_official 579:53297373a894 452 {
mbed_official 579:53297373a894 453 /* Sanity check arguments */
mbed_official 579:53297373a894 454 Assert(module);
mbed_official 579:53297373a894 455 Assert(module->hw);
mbed_official 579:53297373a894 456
mbed_official 579:53297373a894 457 /* Error variable */
mbed_official 579:53297373a894 458 uint8_t error_code;
mbed_official 579:53297373a894 459
mbed_official 579:53297373a894 460 /* Get a pointer to the hardware module instance */
mbed_official 579:53297373a894 461 SercomUsart *const usart_hw = &(module->hw->USART);
mbed_official 579:53297373a894 462
mbed_official 579:53297373a894 463 /* Check that the receiver is enabled */
mbed_official 579:53297373a894 464 if (!(module->receiver_enabled)) {
mbed_official 579:53297373a894 465 return STATUS_ERR_DENIED;
mbed_official 579:53297373a894 466 }
mbed_official 579:53297373a894 467
mbed_official 579:53297373a894 468 #if USART_CALLBACK_MODE == true
mbed_official 579:53297373a894 469 /* Check if the USART is busy doing asynchronous operation. */
mbed_official 579:53297373a894 470 if (module->remaining_rx_buffer_length > 0) {
mbed_official 579:53297373a894 471 return STATUS_BUSY;
mbed_official 579:53297373a894 472 }
mbed_official 579:53297373a894 473 #endif
mbed_official 579:53297373a894 474
mbed_official 579:53297373a894 475 /* Check if USART has new data */
mbed_official 579:53297373a894 476 if (!(usart_hw->INTFLAG.reg & SERCOM_USART_INTFLAG_RXC)) {
mbed_official 579:53297373a894 477 /* Return error code */
mbed_official 579:53297373a894 478 return STATUS_BUSY;
mbed_official 579:53297373a894 479 }
mbed_official 579:53297373a894 480
mbed_official 579:53297373a894 481 /* Wait until synchronization is complete */
mbed_official 579:53297373a894 482 _usart_wait_for_sync(module);
mbed_official 579:53297373a894 483
mbed_official 579:53297373a894 484 /* Read out the status code and mask away all but the 3 LSBs*/
mbed_official 579:53297373a894 485 error_code = (uint8_t)(usart_hw->STATUS.reg & SERCOM_USART_STATUS_MASK);
mbed_official 579:53297373a894 486
mbed_official 579:53297373a894 487 /* Check if an error has occurred during the receiving */
mbed_official 579:53297373a894 488 if (error_code) {
mbed_official 579:53297373a894 489 /* Check which error occurred */
mbed_official 579:53297373a894 490 if (error_code & SERCOM_USART_STATUS_FERR) {
mbed_official 579:53297373a894 491 /* Clear flag by writing a 1 to it and
mbed_official 579:53297373a894 492 * return with an error code */
mbed_official 579:53297373a894 493 usart_hw->STATUS.reg = SERCOM_USART_STATUS_FERR;
mbed_official 579:53297373a894 494
mbed_official 579:53297373a894 495 return STATUS_ERR_BAD_FORMAT;
mbed_official 579:53297373a894 496 } else if (error_code & SERCOM_USART_STATUS_BUFOVF) {
mbed_official 579:53297373a894 497 /* Clear flag by writing a 1 to it and
mbed_official 579:53297373a894 498 * return with an error code */
mbed_official 579:53297373a894 499 usart_hw->STATUS.reg = SERCOM_USART_STATUS_BUFOVF;
mbed_official 579:53297373a894 500
mbed_official 579:53297373a894 501 return STATUS_ERR_OVERFLOW;
mbed_official 579:53297373a894 502 } else if (error_code & SERCOM_USART_STATUS_PERR) {
mbed_official 579:53297373a894 503 /* Clear flag by writing a 1 to it and
mbed_official 579:53297373a894 504 * return with an error code */
mbed_official 579:53297373a894 505 usart_hw->STATUS.reg = SERCOM_USART_STATUS_PERR;
mbed_official 579:53297373a894 506
mbed_official 579:53297373a894 507 return STATUS_ERR_BAD_DATA;
mbed_official 579:53297373a894 508 }
mbed_official 579:53297373a894 509 #ifdef FEATURE_USART_LIN_SLAVE
mbed_official 579:53297373a894 510 else if (error_code & SERCOM_USART_STATUS_ISF) {
mbed_official 579:53297373a894 511 /* Clear flag by writing 1 to it and
mbed_official 579:53297373a894 512 * return with an error code */
mbed_official 579:53297373a894 513 usart_hw->STATUS.reg |= SERCOM_USART_STATUS_ISF;
mbed_official 579:53297373a894 514
mbed_official 579:53297373a894 515 return STATUS_ERR_PROTOCOL;
mbed_official 579:53297373a894 516 }
mbed_official 579:53297373a894 517 #endif
mbed_official 579:53297373a894 518 #ifdef FEATURE_USART_COLLISION_DECTION
mbed_official 579:53297373a894 519 else if (error_code & SERCOM_USART_STATUS_COLL) {
mbed_official 579:53297373a894 520 /* Clear flag by writing 1 to it
mbed_official 579:53297373a894 521 * return with an error code */
mbed_official 579:53297373a894 522 usart_hw->STATUS.reg |= SERCOM_USART_STATUS_COLL;
mbed_official 579:53297373a894 523
mbed_official 579:53297373a894 524 return STATUS_ERR_PACKET_COLLISION;
mbed_official 579:53297373a894 525 }
mbed_official 579:53297373a894 526 #endif
mbed_official 579:53297373a894 527 }
mbed_official 579:53297373a894 528
mbed_official 579:53297373a894 529 /* Read data from USART module */
mbed_official 579:53297373a894 530 *rx_data = usart_hw->DATA.reg;
mbed_official 579:53297373a894 531
mbed_official 579:53297373a894 532 return STATUS_OK;
mbed_official 579:53297373a894 533 }
mbed_official 579:53297373a894 534
mbed_official 579:53297373a894 535 /**
mbed_official 579:53297373a894 536 * \brief Transmit a buffer of characters via the USART
mbed_official 579:53297373a894 537 *
mbed_official 579:53297373a894 538 * This blocking function will transmit a block of \c length characters
mbed_official 579:53297373a894 539 * via the USART.
mbed_official 579:53297373a894 540 *
mbed_official 579:53297373a894 541 * \note Using this function in combination with the interrupt (\c _job) functions is
mbed_official 579:53297373a894 542 * not recommended as it has no functionality to check if there is an
mbed_official 579:53297373a894 543 * ongoing interrupt driven operation running or not.
mbed_official 579:53297373a894 544 *
mbed_official 579:53297373a894 545 * \param[in] module Pointer to USART software instance struct
mbed_official 579:53297373a894 546 * \param[in] tx_data Pointer to data to transmit
mbed_official 579:53297373a894 547 * \param[in] length Number of characters to transmit
mbed_official 579:53297373a894 548 *
mbed_official 579:53297373a894 549 * \note if using 9-bit data, the array that *tx_data point to should be defined
mbed_official 579:53297373a894 550 * as uint16_t array and should be casted to uint8_t* pointer. Because it
mbed_official 579:53297373a894 551 * is an address pointer, the highest byte is not discarded. For example:
mbed_official 579:53297373a894 552 * \code
mbed_official 579:53297373a894 553 #define TX_LEN 3
mbed_official 579:53297373a894 554 uint16_t tx_buf[TX_LEN] = {0x0111, 0x0022, 0x0133};
mbed_official 579:53297373a894 555 usart_write_buffer_wait(&module, (uint8_t*)tx_buf, TX_LEN);
mbed_official 579:53297373a894 556 \endcode
mbed_official 579:53297373a894 557 *
mbed_official 579:53297373a894 558 * \return Status of the operation.
mbed_official 579:53297373a894 559 * \retval STATUS_OK If operation was completed
mbed_official 579:53297373a894 560 * \retval STATUS_ERR_INVALID_ARG If operation was not completed, due to invalid
mbed_official 579:53297373a894 561 * arguments
mbed_official 579:53297373a894 562 * \retval STATUS_ERR_TIMEOUT If operation was not completed, due to USART
mbed_official 579:53297373a894 563 * module timing out
mbed_official 579:53297373a894 564 * \retval STATUS_ERR_DENIED If the transmitter is not enabled
mbed_official 579:53297373a894 565 */
mbed_official 579:53297373a894 566 enum status_code usart_write_buffer_wait(
mbed_official 579:53297373a894 567 struct usart_module *const module,
mbed_official 579:53297373a894 568 const uint8_t *tx_data,
mbed_official 579:53297373a894 569 uint16_t length)
mbed_official 579:53297373a894 570 {
mbed_official 579:53297373a894 571 /* Sanity check arguments */
mbed_official 579:53297373a894 572 Assert(module);
mbed_official 579:53297373a894 573 Assert(module->hw);
mbed_official 579:53297373a894 574
mbed_official 579:53297373a894 575 /* Check if the buffer length is valid */
mbed_official 579:53297373a894 576 if (length == 0) {
mbed_official 579:53297373a894 577 return STATUS_ERR_INVALID_ARG;
mbed_official 579:53297373a894 578 }
mbed_official 579:53297373a894 579
mbed_official 579:53297373a894 580 /* Check that the transmitter is enabled */
mbed_official 579:53297373a894 581 if (!(module->transmitter_enabled)) {
mbed_official 579:53297373a894 582 return STATUS_ERR_DENIED;
mbed_official 579:53297373a894 583 }
mbed_official 579:53297373a894 584
mbed_official 579:53297373a894 585 /* Get a pointer to the hardware module instance */
mbed_official 579:53297373a894 586 SercomUsart *const usart_hw = &(module->hw->USART);
mbed_official 579:53297373a894 587
mbed_official 579:53297373a894 588 /* Wait until synchronization is complete */
mbed_official 579:53297373a894 589 _usart_wait_for_sync(module);
mbed_official 579:53297373a894 590
mbed_official 579:53297373a894 591 uint16_t tx_pos = 0;
mbed_official 579:53297373a894 592
mbed_official 579:53297373a894 593 /* Blocks while buffer is being transferred */
mbed_official 579:53297373a894 594 while (length--) {
mbed_official 579:53297373a894 595 /* Wait for the USART to be ready for new data and abort
mbed_official 579:53297373a894 596 * operation if it doesn't get ready within the timeout*/
mbed_official 579:53297373a894 597 for (uint32_t i = 0; i <= USART_TIMEOUT; i++) {
mbed_official 579:53297373a894 598 if (usart_hw->INTFLAG.reg & SERCOM_USART_INTFLAG_DRE) {
mbed_official 579:53297373a894 599 break;
mbed_official 579:53297373a894 600 } else if (i == USART_TIMEOUT) {
mbed_official 579:53297373a894 601 return STATUS_ERR_TIMEOUT;
mbed_official 579:53297373a894 602 }
mbed_official 579:53297373a894 603 }
mbed_official 579:53297373a894 604
mbed_official 579:53297373a894 605 /* Data to send is at least 8 bits long */
mbed_official 579:53297373a894 606 uint16_t data_to_send = tx_data[tx_pos++];
mbed_official 579:53297373a894 607
mbed_official 579:53297373a894 608 /* Check if the character size exceeds 8 bit */
mbed_official 579:53297373a894 609 if (module->character_size == USART_CHARACTER_SIZE_9BIT) {
mbed_official 579:53297373a894 610 data_to_send |= (tx_data[tx_pos++] << 8);
mbed_official 579:53297373a894 611 }
mbed_official 579:53297373a894 612
mbed_official 579:53297373a894 613 /* Send the data through the USART module */
mbed_official 579:53297373a894 614 usart_write_wait(module, data_to_send);
mbed_official 579:53297373a894 615 }
mbed_official 579:53297373a894 616
mbed_official 579:53297373a894 617 /* Wait until Transmit is complete or timeout */
mbed_official 579:53297373a894 618 for (uint32_t i = 0; i <= USART_TIMEOUT; i++) {
mbed_official 579:53297373a894 619 if (usart_hw->INTFLAG.reg & SERCOM_USART_INTFLAG_TXC) {
mbed_official 579:53297373a894 620 break;
mbed_official 579:53297373a894 621 } else if (i == USART_TIMEOUT) {
mbed_official 579:53297373a894 622 return STATUS_ERR_TIMEOUT;
mbed_official 579:53297373a894 623 }
mbed_official 579:53297373a894 624 }
mbed_official 579:53297373a894 625
mbed_official 579:53297373a894 626 return STATUS_OK;
mbed_official 579:53297373a894 627 }
mbed_official 579:53297373a894 628
mbed_official 579:53297373a894 629 /**
mbed_official 579:53297373a894 630 * \brief Receive a buffer of \c length characters via the USART
mbed_official 579:53297373a894 631 *
mbed_official 579:53297373a894 632 * This blocking function will receive a block of \c length characters
mbed_official 579:53297373a894 633 * via the USART.
mbed_official 579:53297373a894 634 *
mbed_official 579:53297373a894 635 * \note Using this function in combination with the interrupt (\c *_job)
mbed_official 579:53297373a894 636 * functions is not recommended as it has no functionality to check if
mbed_official 579:53297373a894 637 * there is an ongoing interrupt driven operation running or not.
mbed_official 579:53297373a894 638 *
mbed_official 579:53297373a894 639 * \param[in] module Pointer to USART software instance struct
mbed_official 579:53297373a894 640 * \param[out] rx_data Pointer to receive buffer
mbed_official 579:53297373a894 641 * \param[in] length Number of characters to receive
mbed_official 579:53297373a894 642 *
mbed_official 579:53297373a894 643 * \note if using 9-bit data, the array that *rx_data point to should be defined
mbed_official 579:53297373a894 644 * as uint16_t array and should be casted to uint8_t* pointer. Because it
mbed_official 579:53297373a894 645 * is an address pointer, the highest byte is not discarded. For example:
mbed_official 579:53297373a894 646 * \code
mbed_official 579:53297373a894 647 #define RX_LEN 3
mbed_official 579:53297373a894 648 uint16_t rx_buf[RX_LEN] = {0x0,};
mbed_official 579:53297373a894 649 usart_read_buffer_wait(&module, (uint8_t*)rx_buf, RX_LEN);
mbed_official 579:53297373a894 650 \endcode
mbed_official 579:53297373a894 651 *
mbed_official 579:53297373a894 652 * \return Status of the operation.
mbed_official 579:53297373a894 653 * \retval STATUS_OK If operation was completed
mbed_official 579:53297373a894 654 * \retval STATUS_ERR_INVALID_ARG If operation was not completed, due to an
mbed_official 579:53297373a894 655 * invalid argument being supplied
mbed_official 579:53297373a894 656 * \retval STATUS_ERR_TIMEOUT If operation was not completed, due
mbed_official 579:53297373a894 657 * to USART module timing out
mbed_official 579:53297373a894 658 * \retval STATUS_ERR_BAD_FORMAT If the operation was not completed,
mbed_official 579:53297373a894 659 * due to a configuration mismatch
mbed_official 579:53297373a894 660 * between USART and the sender
mbed_official 579:53297373a894 661 * \retval STATUS_ERR_BAD_OVERFLOW If the operation was not completed,
mbed_official 579:53297373a894 662 * due to the baudrate being too low or the
mbed_official 579:53297373a894 663 * system frequency being too high
mbed_official 579:53297373a894 664 * \retval STATUS_ERR_BAD_DATA If the operation was not completed, due
mbed_official 579:53297373a894 665 * to data being corrupted
mbed_official 579:53297373a894 666 * \retval STATUS_ERR_DENIED If the receiver is not enabled
mbed_official 579:53297373a894 667 */
mbed_official 579:53297373a894 668 enum status_code usart_read_buffer_wait(
mbed_official 579:53297373a894 669 struct usart_module *const module,
mbed_official 579:53297373a894 670 uint8_t *rx_data,
mbed_official 579:53297373a894 671 uint16_t length)
mbed_official 579:53297373a894 672 {
mbed_official 579:53297373a894 673 /* Sanity check arguments */
mbed_official 579:53297373a894 674 Assert(module);
mbed_official 579:53297373a894 675 Assert(module->hw);
mbed_official 579:53297373a894 676
mbed_official 579:53297373a894 677 /* Check if the buffer length is valid */
mbed_official 579:53297373a894 678 if (length == 0) {
mbed_official 579:53297373a894 679 return STATUS_ERR_INVALID_ARG;
mbed_official 579:53297373a894 680 }
mbed_official 579:53297373a894 681
mbed_official 579:53297373a894 682 /* Check that the receiver is enabled */
mbed_official 579:53297373a894 683 if (!(module->receiver_enabled)) {
mbed_official 579:53297373a894 684 return STATUS_ERR_DENIED;
mbed_official 579:53297373a894 685 }
mbed_official 579:53297373a894 686
mbed_official 579:53297373a894 687 /* Get a pointer to the hardware module instance */
mbed_official 579:53297373a894 688 SercomUsart *const usart_hw = &(module->hw->USART);
mbed_official 579:53297373a894 689
mbed_official 579:53297373a894 690 uint16_t rx_pos = 0;
mbed_official 579:53297373a894 691
mbed_official 579:53297373a894 692 /* Blocks while buffer is being received */
mbed_official 579:53297373a894 693 while (length--) {
mbed_official 579:53297373a894 694 /* Wait for the USART to have new data and abort operation if it
mbed_official 579:53297373a894 695 * doesn't get ready within the timeout*/
mbed_official 579:53297373a894 696 for (uint32_t i = 0; i <= USART_TIMEOUT; i++) {
mbed_official 579:53297373a894 697 if (usart_hw->INTFLAG.reg & SERCOM_USART_INTFLAG_RXC) {
mbed_official 579:53297373a894 698 break;
mbed_official 579:53297373a894 699 } else if (i == USART_TIMEOUT) {
mbed_official 579:53297373a894 700 return STATUS_ERR_TIMEOUT;
mbed_official 579:53297373a894 701 }
mbed_official 579:53297373a894 702 }
mbed_official 579:53297373a894 703
mbed_official 579:53297373a894 704 enum status_code retval;
mbed_official 579:53297373a894 705 uint16_t received_data = 0;
mbed_official 579:53297373a894 706
mbed_official 579:53297373a894 707 retval = usart_read_wait(module, &received_data);
mbed_official 579:53297373a894 708
mbed_official 579:53297373a894 709 if (retval != STATUS_OK) {
mbed_official 579:53297373a894 710 /* Overflow, abort */
mbed_official 579:53297373a894 711 return retval;
mbed_official 579:53297373a894 712 }
mbed_official 579:53297373a894 713
mbed_official 579:53297373a894 714 /* Read value will be at least 8-bits long */
mbed_official 579:53297373a894 715 rx_data[rx_pos++] = received_data;
mbed_official 579:53297373a894 716
mbed_official 579:53297373a894 717 /* If 9-bit data, write next received byte to the buffer */
mbed_official 579:53297373a894 718 if (module->character_size == USART_CHARACTER_SIZE_9BIT) {
mbed_official 579:53297373a894 719 rx_data[rx_pos++] = (received_data >> 8);
mbed_official 579:53297373a894 720 }
mbed_official 579:53297373a894 721 }
mbed_official 579:53297373a894 722
mbed_official 579:53297373a894 723 return STATUS_OK;
mbed_official 579:53297373a894 724 }