mbed library sources

Dependents:   Encrypted my_mbed lklk CyaSSL_DTLS_Cellular ... more

Superseded

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

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

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

Import librarymbed

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

Committer:
mbed_official
Date:
Fri Jul 17 09:15:10 2015 +0100
Revision:
592:a274ee790e56
Parent:
579:53297373a894
Synchronized with git revision e7144f83a8d75df80c4877936b6ffe552b0be9e6

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

More API implementation for SAMR21

Who changed what in which revision?

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