t

Fork of mbed-dev by mbed official

Committer:
<>
Date:
Fri Oct 28 11:17:30 2016 +0100
Revision:
149:156823d33999
Parent:
targets/hal/TARGET_Atmel/TARGET_SAM_CortexM0P/drivers/sercom/usart/usart.c@15:a81a8d6c1dfe
This updates the lib to the mbed lib v128

NOTE: This release includes a restructuring of the file and directory locations and thus some
include paths in your code may need updating accordingly.

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 }