mbed library sources. Supersedes mbed-src.

Fork of mbed-dev by mbed official

Committer:
screamer
Date:
Tue Aug 02 14:07:36 2016 +0000
Revision:
144:423e1876dc07
Parent:
15:a81a8d6c1dfe
Added targets.json file for the supported targets in the release

Who changed what in which revision?

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