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_interrupt.h"
mbed_official 579:53297373a894 2
mbed_official 579:53297373a894 3 /**
mbed_official 579:53297373a894 4 * \internal
mbed_official 579:53297373a894 5 * Asynchronous write of a buffer with a given length
mbed_official 579:53297373a894 6 *
mbed_official 579:53297373a894 7 * \param[in] module Pointer to USART software instance struct
mbed_official 579:53297373a894 8 * \param[in] tx_data Pointer to data to be transmitted
mbed_official 579:53297373a894 9 * \param[in] length Length of data buffer
mbed_official 579:53297373a894 10 *
mbed_official 579:53297373a894 11 */
mbed_official 579:53297373a894 12 void _usart_write_buffer(
mbed_official 579:53297373a894 13 struct usart_module *const module,
mbed_official 579:53297373a894 14 uint8_t *tx_data,
mbed_official 579:53297373a894 15 uint16_t length)
mbed_official 579:53297373a894 16 {
mbed_official 579:53297373a894 17 /* Sanity check arguments */
mbed_official 579:53297373a894 18 Assert(module);
mbed_official 579:53297373a894 19 Assert(module->hw);
mbed_official 579:53297373a894 20
mbed_official 579:53297373a894 21 /* Get a pointer to the hardware module instance */
mbed_official 579:53297373a894 22 SercomUsart *const usart_hw = &(module->hw->USART);
mbed_official 579:53297373a894 23
mbed_official 579:53297373a894 24 /* Write parameters to the device instance */
mbed_official 579:53297373a894 25 module->remaining_tx_buffer_length = length;
mbed_official 579:53297373a894 26 module->tx_buffer_ptr = tx_data;
mbed_official 579:53297373a894 27 module->tx_status = STATUS_BUSY;
mbed_official 579:53297373a894 28
mbed_official 579:53297373a894 29 /* Enable the Data Register Empty Interrupt */
mbed_official 579:53297373a894 30 usart_hw->INTENSET.reg = SERCOM_USART_INTFLAG_DRE;
mbed_official 579:53297373a894 31 }
mbed_official 579:53297373a894 32
mbed_official 579:53297373a894 33 /**
mbed_official 579:53297373a894 34 * \internal
mbed_official 579:53297373a894 35 * Asynchronous read of a buffer with a given length
mbed_official 579:53297373a894 36 *
mbed_official 579:53297373a894 37 * \param[in] module Pointer to USART software instance struct
mbed_official 579:53297373a894 38 * \param[in] rx_data Pointer to data to be received
mbed_official 579:53297373a894 39 * \param[in] length Length of data buffer
mbed_official 579:53297373a894 40 *
mbed_official 579:53297373a894 41 */
mbed_official 579:53297373a894 42 void _usart_read_buffer(
mbed_official 579:53297373a894 43 struct usart_module *const module,
mbed_official 579:53297373a894 44 uint8_t *rx_data,
mbed_official 579:53297373a894 45 uint16_t length)
mbed_official 579:53297373a894 46 {
mbed_official 579:53297373a894 47 /* Sanity check arguments */
mbed_official 579:53297373a894 48 Assert(module);
mbed_official 579:53297373a894 49 Assert(module->hw);
mbed_official 579:53297373a894 50
mbed_official 579:53297373a894 51 /* Get a pointer to the hardware module instance */
mbed_official 579:53297373a894 52 SercomUsart *const usart_hw = &(module->hw->USART);
mbed_official 579:53297373a894 53
mbed_official 579:53297373a894 54 /* Set length for the buffer and the pointer, and let
mbed_official 579:53297373a894 55 * the interrupt handler do the rest */
mbed_official 579:53297373a894 56 module->remaining_rx_buffer_length = length;
mbed_official 579:53297373a894 57 module->rx_buffer_ptr = rx_data;
mbed_official 579:53297373a894 58 module->rx_status = STATUS_BUSY;
mbed_official 579:53297373a894 59
mbed_official 579:53297373a894 60 /* Enable the RX Complete Interrupt */
mbed_official 579:53297373a894 61 usart_hw->INTENSET.reg = SERCOM_USART_INTFLAG_RXC;
mbed_official 579:53297373a894 62
mbed_official 579:53297373a894 63 #ifdef FEATURE_USART_LIN_SLAVE
mbed_official 579:53297373a894 64 /* Enable the break character is received Interrupt */
mbed_official 579:53297373a894 65 if(module->lin_slave_enabled) {
mbed_official 579:53297373a894 66 usart_hw->INTENSET.reg = SERCOM_USART_INTFLAG_RXBRK;
mbed_official 579:53297373a894 67 }
mbed_official 579:53297373a894 68 #endif
mbed_official 579:53297373a894 69
mbed_official 579:53297373a894 70 #ifdef FEATURE_USART_START_FRAME_DECTION
mbed_official 579:53297373a894 71 /* Enable a start condition is detected Interrupt */
mbed_official 579:53297373a894 72 if(module->start_frame_detection_enabled) {
mbed_official 579:53297373a894 73 usart_hw->INTENSET.reg = SERCOM_USART_INTFLAG_RXS;
mbed_official 579:53297373a894 74 }
mbed_official 579:53297373a894 75 #endif
mbed_official 579:53297373a894 76 }
mbed_official 579:53297373a894 77
mbed_official 579:53297373a894 78 /**
mbed_official 579:53297373a894 79 * \brief Registers a callback
mbed_official 579:53297373a894 80 *
mbed_official 579:53297373a894 81 * Registers a callback function which is implemented by the user.
mbed_official 579:53297373a894 82 *
mbed_official 579:53297373a894 83 * \note The callback must be enabled by \ref usart_enable_callback,
mbed_official 579:53297373a894 84 * in order for the interrupt handler to call it when the conditions for
mbed_official 579:53297373a894 85 * the callback type are met.
mbed_official 579:53297373a894 86 *
mbed_official 579:53297373a894 87 * \param[in] module Pointer to USART software instance struct
mbed_official 579:53297373a894 88 * \param[in] callback_func Pointer to callback function
mbed_official 579:53297373a894 89 * \param[in] callback_type Callback type given by an enum
mbed_official 579:53297373a894 90 *
mbed_official 579:53297373a894 91 */
mbed_official 579:53297373a894 92 void usart_register_callback(
mbed_official 579:53297373a894 93 struct usart_module *const module,
mbed_official 579:53297373a894 94 usart_callback_t callback_func,
mbed_official 579:53297373a894 95 enum usart_callback callback_type)
mbed_official 579:53297373a894 96 {
mbed_official 579:53297373a894 97 /* Sanity check arguments */
mbed_official 579:53297373a894 98 Assert(module);
mbed_official 579:53297373a894 99 Assert(callback_func);
mbed_official 579:53297373a894 100
mbed_official 579:53297373a894 101 /* Register callback function */
mbed_official 579:53297373a894 102 module->callback[callback_type] = callback_func;
mbed_official 579:53297373a894 103
mbed_official 579:53297373a894 104 /* Set the bit corresponding to the callback_type */
mbed_official 579:53297373a894 105 module->callback_reg_mask |= (1 << callback_type);
mbed_official 579:53297373a894 106 }
mbed_official 579:53297373a894 107
mbed_official 579:53297373a894 108 /**
mbed_official 579:53297373a894 109 * \brief Unregisters a callback
mbed_official 579:53297373a894 110 *
mbed_official 579:53297373a894 111 * Unregisters a callback function which is implemented by the user.
mbed_official 579:53297373a894 112 *
mbed_official 579:53297373a894 113 * \param[in,out] module Pointer to USART software instance struct
mbed_official 579:53297373a894 114 * \param[in] callback_type Callback type given by an enum
mbed_official 579:53297373a894 115 *
mbed_official 579:53297373a894 116 */
mbed_official 579:53297373a894 117 void usart_unregister_callback(
mbed_official 579:53297373a894 118 struct usart_module *const module,
mbed_official 579:53297373a894 119 enum usart_callback callback_type)
mbed_official 579:53297373a894 120 {
mbed_official 579:53297373a894 121 /* Sanity check arguments */
mbed_official 579:53297373a894 122 Assert(module);
mbed_official 579:53297373a894 123
mbed_official 579:53297373a894 124 /* Unregister callback function */
mbed_official 579:53297373a894 125 module->callback[callback_type] = NULL;
mbed_official 579:53297373a894 126
mbed_official 579:53297373a894 127 /* Clear the bit corresponding to the callback_type */
mbed_official 579:53297373a894 128 module->callback_reg_mask &= ~(1 << callback_type);
mbed_official 579:53297373a894 129 }
mbed_official 579:53297373a894 130
mbed_official 579:53297373a894 131 /**
mbed_official 579:53297373a894 132 * \brief Asynchronous write a single char
mbed_official 579:53297373a894 133 *
mbed_official 579:53297373a894 134 * Sets up the driver to write the data given. If registered and enabled,
mbed_official 579:53297373a894 135 * a callback function will be called when the transmit is completed.
mbed_official 579:53297373a894 136 *
mbed_official 579:53297373a894 137 * \param[in] module Pointer to USART software instance struct
mbed_official 579:53297373a894 138 * \param[in] tx_data Data to transfer
mbed_official 579:53297373a894 139 *
mbed_official 579:53297373a894 140 * \returns Status of the operation.
mbed_official 579:53297373a894 141 * \retval STATUS_OK If operation was completed
mbed_official 579:53297373a894 142 * \retval STATUS_BUSY If operation was not completed, due to the
mbed_official 579:53297373a894 143 * USART module being busy
mbed_official 579:53297373a894 144 * \retval STATUS_ERR_DENIED If the transmitter is not enabled
mbed_official 579:53297373a894 145 */
mbed_official 579:53297373a894 146 enum status_code usart_write_job(
mbed_official 579:53297373a894 147 struct usart_module *const module,
mbed_official 579:53297373a894 148 const uint16_t *tx_data)
mbed_official 579:53297373a894 149 {
mbed_official 579:53297373a894 150 /* Sanity check arguments */
mbed_official 579:53297373a894 151 Assert(module);
mbed_official 579:53297373a894 152 Assert(tx_data);
mbed_official 579:53297373a894 153
mbed_official 579:53297373a894 154 /* Check if the USART transmitter is busy */
mbed_official 579:53297373a894 155 if (module->remaining_tx_buffer_length > 0) {
mbed_official 579:53297373a894 156 return STATUS_BUSY;
mbed_official 579:53297373a894 157 }
mbed_official 579:53297373a894 158
mbed_official 579:53297373a894 159 /* Check that the transmitter is enabled */
mbed_official 579:53297373a894 160 if (!(module->transmitter_enabled)) {
mbed_official 579:53297373a894 161 return STATUS_ERR_DENIED;
mbed_official 579:53297373a894 162 }
mbed_official 579:53297373a894 163
mbed_official 579:53297373a894 164 /* Call internal write buffer function with length 1 */
mbed_official 579:53297373a894 165 _usart_write_buffer(module, (uint8_t *)tx_data, 1);
mbed_official 579:53297373a894 166
mbed_official 579:53297373a894 167 return STATUS_OK;
mbed_official 579:53297373a894 168 }
mbed_official 579:53297373a894 169
mbed_official 579:53297373a894 170 /**
mbed_official 579:53297373a894 171 * \brief Asynchronous read a single char
mbed_official 579:53297373a894 172 *
mbed_official 579:53297373a894 173 * Sets up the driver to read data from the USART module to the data
mbed_official 579:53297373a894 174 * pointer given. If registered and enabled, a callback will be called
mbed_official 579:53297373a894 175 * when the receiving is completed.
mbed_official 579:53297373a894 176 *
mbed_official 579:53297373a894 177 * \param[in] module Pointer to USART software instance struct
mbed_official 579:53297373a894 178 * \param[out] rx_data Pointer to where received data should be put
mbed_official 579:53297373a894 179 *
mbed_official 579:53297373a894 180 * \returns Status of the operation.
mbed_official 579:53297373a894 181 * \retval STATUS_OK If operation was completed
mbed_official 579:53297373a894 182 * \retval STATUS_BUSY If operation was not completed
mbed_official 579:53297373a894 183 */
mbed_official 579:53297373a894 184 enum status_code usart_read_job(
mbed_official 579:53297373a894 185 struct usart_module *const module,
mbed_official 579:53297373a894 186 uint16_t *const rx_data)
mbed_official 579:53297373a894 187 {
mbed_official 579:53297373a894 188 /* Sanity check arguments */
mbed_official 579:53297373a894 189 Assert(module);
mbed_official 579:53297373a894 190 Assert(rx_data);
mbed_official 579:53297373a894 191
mbed_official 579:53297373a894 192 /* Check if the USART receiver is busy */
mbed_official 579:53297373a894 193 if (module->remaining_rx_buffer_length > 0) {
mbed_official 579:53297373a894 194 return STATUS_BUSY;
mbed_official 579:53297373a894 195 }
mbed_official 579:53297373a894 196
mbed_official 579:53297373a894 197 /* Call internal read buffer function with length 1 */
mbed_official 579:53297373a894 198 _usart_read_buffer(module, (uint8_t *)rx_data, 1);
mbed_official 579:53297373a894 199
mbed_official 579:53297373a894 200 return STATUS_OK;
mbed_official 579:53297373a894 201 }
mbed_official 579:53297373a894 202
mbed_official 579:53297373a894 203 /**
mbed_official 579:53297373a894 204 * \brief Asynchronous buffer write
mbed_official 579:53297373a894 205 *
mbed_official 579:53297373a894 206 * Sets up the driver to write a given buffer over the USART. If registered and
mbed_official 579:53297373a894 207 * enabled, a callback function will be called.
mbed_official 579:53297373a894 208 *
mbed_official 579:53297373a894 209 * \param[in] module Pointer to USART software instance struct
mbed_official 579:53297373a894 210 * \param[in] tx_data Pointer do data buffer to transmit
mbed_official 579:53297373a894 211 * \param[in] length Length of the data to transmit
mbed_official 579:53297373a894 212 *
mbed_official 579:53297373a894 213 * \note if using 9-bit data, the array that *tx_data point to should be defined
mbed_official 579:53297373a894 214 * as uint16_t array and should be casted to uint8_t* pointer. Because it
mbed_official 579:53297373a894 215 * is an address pointer, the highest byte is not discarded. For example:
mbed_official 579:53297373a894 216 * \code
mbed_official 579:53297373a894 217 #define TX_LEN 3
mbed_official 579:53297373a894 218 uint16_t tx_buf[TX_LEN] = {0x0111, 0x0022, 0x0133};
mbed_official 579:53297373a894 219 usart_write_buffer_job(&module, (uint8_t*)tx_buf, TX_LEN);
mbed_official 579:53297373a894 220 \endcode
mbed_official 579:53297373a894 221 *
mbed_official 579:53297373a894 222 * \returns Status of the operation.
mbed_official 579:53297373a894 223 * \retval STATUS_OK If operation was completed successfully.
mbed_official 579:53297373a894 224 * \retval STATUS_BUSY If operation was not completed, due to the
mbed_official 579:53297373a894 225 * USART module being busy
mbed_official 579:53297373a894 226 * \retval STATUS_ERR_INVALID_ARG If operation was not completed, due to invalid
mbed_official 579:53297373a894 227 * arguments
mbed_official 579:53297373a894 228 * \retval STATUS_ERR_DENIED If the transmitter is not enabled
mbed_official 579:53297373a894 229 */
mbed_official 579:53297373a894 230 enum status_code usart_write_buffer_job(
mbed_official 579:53297373a894 231 struct usart_module *const module,
mbed_official 579:53297373a894 232 uint8_t *tx_data,
mbed_official 579:53297373a894 233 uint16_t length)
mbed_official 579:53297373a894 234 {
mbed_official 579:53297373a894 235 /* Sanity check arguments */
mbed_official 579:53297373a894 236 Assert(module);
mbed_official 579:53297373a894 237 Assert(tx_data);
mbed_official 579:53297373a894 238
mbed_official 579:53297373a894 239 if (length == 0) {
mbed_official 579:53297373a894 240 return STATUS_ERR_INVALID_ARG;
mbed_official 579:53297373a894 241 }
mbed_official 579:53297373a894 242
mbed_official 579:53297373a894 243 /* Check if the USART transmitter is busy */
mbed_official 579:53297373a894 244 if (module->remaining_tx_buffer_length > 0) {
mbed_official 579:53297373a894 245 return STATUS_BUSY;
mbed_official 579:53297373a894 246 }
mbed_official 579:53297373a894 247
mbed_official 579:53297373a894 248 /* Check that the receiver is enabled */
mbed_official 579:53297373a894 249 if (!(module->transmitter_enabled)) {
mbed_official 579:53297373a894 250 return STATUS_ERR_DENIED;
mbed_official 579:53297373a894 251 }
mbed_official 579:53297373a894 252
mbed_official 579:53297373a894 253 /* Issue internal asynchronous write */
mbed_official 579:53297373a894 254 _usart_write_buffer(module, tx_data, length);
mbed_official 579:53297373a894 255
mbed_official 579:53297373a894 256 return STATUS_OK;
mbed_official 579:53297373a894 257 }
mbed_official 579:53297373a894 258
mbed_official 579:53297373a894 259 /**
mbed_official 579:53297373a894 260 * \brief Asynchronous buffer read
mbed_official 579:53297373a894 261 *
mbed_official 579:53297373a894 262 * Sets up the driver to read from the USART to a given buffer. If registered
mbed_official 579:53297373a894 263 * and enabled, a callback function will be called.
mbed_official 579:53297373a894 264 *
mbed_official 579:53297373a894 265 * \param[in] module Pointer to USART software instance struct
mbed_official 579:53297373a894 266 * \param[out] rx_data Pointer to data buffer to receive
mbed_official 579:53297373a894 267 * \param[in] length Data buffer length
mbed_official 579:53297373a894 268 *
mbed_official 579:53297373a894 269 * \note if using 9-bit data, the array that *rx_data point to should be defined
mbed_official 579:53297373a894 270 * as uint16_t array and should be casted to uint8_t* pointer. Because it
mbed_official 579:53297373a894 271 * is an address pointer, the highest byte is not discarded. For example:
mbed_official 579:53297373a894 272 * \code
mbed_official 579:53297373a894 273 #define RX_LEN 3
mbed_official 579:53297373a894 274 uint16_t rx_buf[RX_LEN] = {0x0,};
mbed_official 579:53297373a894 275 usart_read_buffer_job(&module, (uint8_t*)rx_buf, RX_LEN);
mbed_official 579:53297373a894 276 \endcode
mbed_official 579:53297373a894 277 *
mbed_official 579:53297373a894 278 * \returns Status of the operation.
mbed_official 579:53297373a894 279 * \retval STATUS_OK If operation was completed
mbed_official 579:53297373a894 280 * \retval STATUS_BUSY If operation was not completed, due to the
mbed_official 579:53297373a894 281 * USART module being busy
mbed_official 579:53297373a894 282 * \retval STATUS_ERR_INVALID_ARG If operation was not completed, due to invalid
mbed_official 579:53297373a894 283 * arguments
mbed_official 579:53297373a894 284 * \retval STATUS_ERR_DENIED If the transmitter is not enabled
mbed_official 579:53297373a894 285 */
mbed_official 579:53297373a894 286 enum status_code usart_read_buffer_job(
mbed_official 579:53297373a894 287 struct usart_module *const module,
mbed_official 579:53297373a894 288 uint8_t *rx_data,
mbed_official 579:53297373a894 289 uint16_t length)
mbed_official 579:53297373a894 290 {
mbed_official 579:53297373a894 291 /* Sanity check arguments */
mbed_official 579:53297373a894 292 Assert(module);
mbed_official 579:53297373a894 293 Assert(rx_data);
mbed_official 579:53297373a894 294
mbed_official 579:53297373a894 295 if (length == 0) {
mbed_official 579:53297373a894 296 return STATUS_ERR_INVALID_ARG;
mbed_official 579:53297373a894 297 }
mbed_official 579:53297373a894 298
mbed_official 579:53297373a894 299 /* Check that the receiver is enabled */
mbed_official 579:53297373a894 300 if (!(module->receiver_enabled)) {
mbed_official 579:53297373a894 301 return STATUS_ERR_DENIED;
mbed_official 579:53297373a894 302 }
mbed_official 579:53297373a894 303
mbed_official 579:53297373a894 304 /* Check if the USART receiver is busy */
mbed_official 579:53297373a894 305 if (module->remaining_rx_buffer_length > 0) {
mbed_official 579:53297373a894 306 return STATUS_BUSY;
mbed_official 579:53297373a894 307 }
mbed_official 579:53297373a894 308
mbed_official 579:53297373a894 309 /* Issue internal asynchronous read */
mbed_official 579:53297373a894 310 _usart_read_buffer(module, rx_data, length);
mbed_official 579:53297373a894 311
mbed_official 579:53297373a894 312 return STATUS_OK;
mbed_official 579:53297373a894 313 }
mbed_official 579:53297373a894 314
mbed_official 579:53297373a894 315 /**
mbed_official 579:53297373a894 316 * \brief Cancels ongoing read/write operation
mbed_official 579:53297373a894 317 *
mbed_official 579:53297373a894 318 * Cancels the ongoing read/write operation modifying parameters in the
mbed_official 579:53297373a894 319 * USART software struct.
mbed_official 579:53297373a894 320 *
mbed_official 579:53297373a894 321 * \param[in] module Pointer to USART software instance struct
mbed_official 579:53297373a894 322 * \param[in] transceiver_type Transfer type to cancel
mbed_official 579:53297373a894 323 */
mbed_official 579:53297373a894 324 void usart_abort_job(
mbed_official 579:53297373a894 325 struct usart_module *const module,
mbed_official 579:53297373a894 326 enum usart_transceiver_type transceiver_type)
mbed_official 579:53297373a894 327 {
mbed_official 579:53297373a894 328 /* Sanity check arguments */
mbed_official 579:53297373a894 329 Assert(module);
mbed_official 579:53297373a894 330 Assert(module->hw);
mbed_official 579:53297373a894 331
mbed_official 579:53297373a894 332 /* Get a pointer to the hardware module instance */
mbed_official 579:53297373a894 333 SercomUsart *const usart_hw = &(module->hw->USART);
mbed_official 579:53297373a894 334
mbed_official 579:53297373a894 335 switch(transceiver_type) {
mbed_official 579:53297373a894 336 case USART_TRANSCEIVER_RX:
mbed_official 579:53297373a894 337 /* Clear the interrupt flag in order to prevent the receive
mbed_official 579:53297373a894 338 * complete callback to fire */
mbed_official 579:53297373a894 339 usart_hw->INTFLAG.reg = SERCOM_USART_INTFLAG_RXC;
mbed_official 579:53297373a894 340
mbed_official 579:53297373a894 341 /* Clear the software reception buffer */
mbed_official 579:53297373a894 342 module->remaining_rx_buffer_length = 0;
mbed_official 579:53297373a894 343
mbed_official 579:53297373a894 344 break;
mbed_official 579:53297373a894 345
mbed_official 579:53297373a894 346 case USART_TRANSCEIVER_TX:
mbed_official 579:53297373a894 347 /* Clear the interrupt flag in order to prevent the receive
mbed_official 579:53297373a894 348 * complete callback to fire */
mbed_official 579:53297373a894 349 usart_hw->INTFLAG.reg = SERCOM_USART_INTFLAG_TXC;
mbed_official 579:53297373a894 350
mbed_official 579:53297373a894 351 /* Clear the software reception buffer */
mbed_official 579:53297373a894 352 module->remaining_tx_buffer_length = 0;
mbed_official 579:53297373a894 353
mbed_official 579:53297373a894 354 break;
mbed_official 579:53297373a894 355 }
mbed_official 579:53297373a894 356 }
mbed_official 579:53297373a894 357
mbed_official 579:53297373a894 358 /**
mbed_official 579:53297373a894 359 * \brief Get status from the ongoing or last asynchronous transfer operation
mbed_official 579:53297373a894 360 *
mbed_official 579:53297373a894 361 * Returns the error from a given ongoing or last asynchronous transfer operation.
mbed_official 579:53297373a894 362 * Either from a read or write transfer.
mbed_official 579:53297373a894 363 *
mbed_official 579:53297373a894 364 * \param[in] module Pointer to USART software instance struct
mbed_official 579:53297373a894 365 * \param[in] transceiver_type Transfer type to check
mbed_official 579:53297373a894 366 *
mbed_official 579:53297373a894 367 * \return Status of the given job.
mbed_official 579:53297373a894 368 * \retval STATUS_OK No error occurred during the last transfer
mbed_official 579:53297373a894 369 * \retval STATUS_BUSY A transfer is ongoing
mbed_official 579:53297373a894 370 * \retval STATUS_ERR_BAD_DATA The last operation was aborted due to a
mbed_official 579:53297373a894 371 * parity error. The transfer could be affected
mbed_official 579:53297373a894 372 * by external noise
mbed_official 579:53297373a894 373 * \retval STATUS_ERR_BAD_FORMAT The last operation was aborted due to a
mbed_official 579:53297373a894 374 * frame error
mbed_official 579:53297373a894 375 * \retval STATUS_ERR_OVERFLOW The last operation was aborted due to a
mbed_official 579:53297373a894 376 * buffer overflow
mbed_official 579:53297373a894 377 * \retval STATUS_ERR_INVALID_ARG An invalid transceiver enum given
mbed_official 579:53297373a894 378 */
mbed_official 579:53297373a894 379 enum status_code usart_get_job_status(
mbed_official 579:53297373a894 380 struct usart_module *const module,
mbed_official 579:53297373a894 381 enum usart_transceiver_type transceiver_type)
mbed_official 579:53297373a894 382 {
mbed_official 579:53297373a894 383 /* Sanity check arguments */
mbed_official 579:53297373a894 384 Assert(module);
mbed_official 579:53297373a894 385
mbed_official 579:53297373a894 386 /* Variable for status code */
mbed_official 579:53297373a894 387 enum status_code status_code;
mbed_official 579:53297373a894 388
mbed_official 579:53297373a894 389 switch(transceiver_type) {
mbed_official 579:53297373a894 390 case USART_TRANSCEIVER_RX:
mbed_official 579:53297373a894 391 status_code = module->rx_status;
mbed_official 579:53297373a894 392 break;
mbed_official 579:53297373a894 393
mbed_official 579:53297373a894 394 case USART_TRANSCEIVER_TX:
mbed_official 579:53297373a894 395 status_code = module->tx_status;
mbed_official 579:53297373a894 396 break;
mbed_official 579:53297373a894 397
mbed_official 579:53297373a894 398 default:
mbed_official 579:53297373a894 399 status_code = STATUS_ERR_INVALID_ARG;
mbed_official 579:53297373a894 400 break;
mbed_official 579:53297373a894 401 }
mbed_official 579:53297373a894 402
mbed_official 579:53297373a894 403 return status_code;
mbed_official 579:53297373a894 404 }
mbed_official 579:53297373a894 405
mbed_official 579:53297373a894 406 /**
mbed_official 579:53297373a894 407 * \internal
mbed_official 579:53297373a894 408 * Handles interrupts as they occur, and it will run callback functions
mbed_official 579:53297373a894 409 * which are registered and enabled.
mbed_official 579:53297373a894 410 *
mbed_official 579:53297373a894 411 * \param[in] instance ID of the SERCOM instance calling the interrupt
mbed_official 579:53297373a894 412 * handler.
mbed_official 579:53297373a894 413 */
mbed_official 579:53297373a894 414 void _usart_interrupt_handler(
mbed_official 579:53297373a894 415 uint8_t instance)
mbed_official 579:53297373a894 416 {
mbed_official 579:53297373a894 417 /* Temporary variables */
mbed_official 579:53297373a894 418 uint16_t interrupt_status;
mbed_official 579:53297373a894 419 uint16_t callback_status;
mbed_official 579:53297373a894 420 uint8_t error_code;
mbed_official 579:53297373a894 421
mbed_official 579:53297373a894 422
mbed_official 579:53297373a894 423 /* Get device instance from the look-up table */
mbed_official 579:53297373a894 424 struct usart_module *module
mbed_official 579:53297373a894 425 = (struct usart_module *)_sercom_instances[instance];
mbed_official 579:53297373a894 426
mbed_official 579:53297373a894 427 /* Pointer to the hardware module instance */
mbed_official 579:53297373a894 428 SercomUsart *const usart_hw
mbed_official 579:53297373a894 429 = &(module->hw->USART);
mbed_official 579:53297373a894 430
mbed_official 579:53297373a894 431 /* Wait for the synchronization to complete */
mbed_official 579:53297373a894 432 _usart_wait_for_sync(module);
mbed_official 579:53297373a894 433
mbed_official 579:53297373a894 434 /* Read and mask interrupt flag register */
mbed_official 579:53297373a894 435 interrupt_status = usart_hw->INTFLAG.reg;
mbed_official 579:53297373a894 436 interrupt_status &= usart_hw->INTENSET.reg;
mbed_official 579:53297373a894 437 callback_status = module->callback_reg_mask &
mbed_official 579:53297373a894 438 module->callback_enable_mask;
mbed_official 579:53297373a894 439
mbed_official 579:53297373a894 440 /* Check if a DATA READY interrupt has occurred,
mbed_official 579:53297373a894 441 * and if there is more to transfer */
mbed_official 579:53297373a894 442 if (interrupt_status & SERCOM_USART_INTFLAG_DRE) {
mbed_official 579:53297373a894 443 if (module->remaining_tx_buffer_length) {
mbed_official 579:53297373a894 444 /* Write value will be at least 8-bits long */
mbed_official 579:53297373a894 445 uint16_t data_to_send = *(module->tx_buffer_ptr);
mbed_official 579:53297373a894 446 /* Increment 8-bit pointer */
mbed_official 579:53297373a894 447 (module->tx_buffer_ptr)++;
mbed_official 579:53297373a894 448
mbed_official 579:53297373a894 449 if (module->character_size == USART_CHARACTER_SIZE_9BIT) {
mbed_official 579:53297373a894 450 data_to_send |= (*(module->tx_buffer_ptr) << 8);
mbed_official 579:53297373a894 451 /* Increment 8-bit pointer */
mbed_official 579:53297373a894 452 (module->tx_buffer_ptr)++;
mbed_official 579:53297373a894 453 }
mbed_official 579:53297373a894 454 /* Write the data to send */
mbed_official 579:53297373a894 455 usart_hw->DATA.reg = (data_to_send & SERCOM_USART_DATA_MASK);
mbed_official 579:53297373a894 456
mbed_official 579:53297373a894 457 if (--(module->remaining_tx_buffer_length) == 0) {
mbed_official 579:53297373a894 458 /* Disable the Data Register Empty Interrupt */
mbed_official 579:53297373a894 459 usart_hw->INTENCLR.reg = SERCOM_USART_INTFLAG_DRE;
mbed_official 579:53297373a894 460 /* Enable Transmission Complete interrupt */
mbed_official 579:53297373a894 461 usart_hw->INTENSET.reg = SERCOM_USART_INTFLAG_TXC;
mbed_official 579:53297373a894 462
mbed_official 579:53297373a894 463 }
mbed_official 579:53297373a894 464 } else {
mbed_official 579:53297373a894 465 usart_hw->INTENCLR.reg = SERCOM_USART_INTFLAG_DRE;
mbed_official 579:53297373a894 466 }
mbed_official 579:53297373a894 467
mbed_official 579:53297373a894 468 /* Check if the Transmission Complete interrupt has occurred and
mbed_official 579:53297373a894 469 * that the transmit buffer is empty */
mbed_official 579:53297373a894 470 }
mbed_official 579:53297373a894 471
mbed_official 579:53297373a894 472 if (interrupt_status & SERCOM_USART_INTFLAG_TXC) {
mbed_official 579:53297373a894 473
mbed_official 579:53297373a894 474 /* Disable TX Complete Interrupt, and set STATUS_OK */
mbed_official 579:53297373a894 475 usart_hw->INTENCLR.reg = SERCOM_USART_INTFLAG_TXC;
mbed_official 579:53297373a894 476 module->tx_status = STATUS_OK;
mbed_official 579:53297373a894 477
mbed_official 579:53297373a894 478 /* Run callback if registered and enabled */
mbed_official 579:53297373a894 479 if (callback_status & (1 << USART_CALLBACK_BUFFER_TRANSMITTED)) {
mbed_official 579:53297373a894 480 (*(module->callback[USART_CALLBACK_BUFFER_TRANSMITTED]))(module);
mbed_official 579:53297373a894 481 }
mbed_official 579:53297373a894 482
mbed_official 579:53297373a894 483 /* Check if the Receive Complete interrupt has occurred, and that
mbed_official 579:53297373a894 484 * there's more data to receive */
mbed_official 579:53297373a894 485 }
mbed_official 579:53297373a894 486
mbed_official 579:53297373a894 487 if (interrupt_status & SERCOM_USART_INTFLAG_RXC) {
mbed_official 579:53297373a894 488
mbed_official 579:53297373a894 489 if (module->remaining_rx_buffer_length) {
mbed_official 579:53297373a894 490 /* Read out the status code and mask away all but the 4 LSBs*/
mbed_official 579:53297373a894 491 error_code = (uint8_t)(usart_hw->STATUS.reg & SERCOM_USART_STATUS_MASK);
mbed_official 579:53297373a894 492 #if !SAMD20
mbed_official 579:53297373a894 493 /* CTS status should not be considered as an error */
mbed_official 579:53297373a894 494 if(error_code & SERCOM_USART_STATUS_CTS) {
mbed_official 579:53297373a894 495 error_code &= ~SERCOM_USART_STATUS_CTS;
mbed_official 579:53297373a894 496 }
mbed_official 579:53297373a894 497 #endif
mbed_official 579:53297373a894 498 /* Check if an error has occurred during the receiving */
mbed_official 579:53297373a894 499 if (error_code) {
mbed_official 579:53297373a894 500 /* Check which error occurred */
mbed_official 579:53297373a894 501 if (error_code & SERCOM_USART_STATUS_FERR) {
mbed_official 579:53297373a894 502 /* Store the error code and clear flag by writing 1 to it */
mbed_official 579:53297373a894 503 module->rx_status = STATUS_ERR_BAD_FORMAT;
mbed_official 579:53297373a894 504 usart_hw->STATUS.reg |= SERCOM_USART_STATUS_FERR;
mbed_official 579:53297373a894 505 } else if (error_code & SERCOM_USART_STATUS_BUFOVF) {
mbed_official 579:53297373a894 506 /* Store the error code and clear flag by writing 1 to it */
mbed_official 579:53297373a894 507 module->rx_status = STATUS_ERR_OVERFLOW;
mbed_official 579:53297373a894 508 usart_hw->STATUS.reg |= SERCOM_USART_STATUS_BUFOVF;
mbed_official 579:53297373a894 509 } else if (error_code & SERCOM_USART_STATUS_PERR) {
mbed_official 579:53297373a894 510 /* Store the error code and clear flag by writing 1 to it */
mbed_official 579:53297373a894 511 module->rx_status = STATUS_ERR_BAD_DATA;
mbed_official 579:53297373a894 512 usart_hw->STATUS.reg |= SERCOM_USART_STATUS_PERR;
mbed_official 579:53297373a894 513 }
mbed_official 579:53297373a894 514 #ifdef FEATURE_USART_LIN_SLAVE
mbed_official 579:53297373a894 515 else if (error_code & SERCOM_USART_STATUS_ISF) {
mbed_official 579:53297373a894 516 /* Store the error code and clear flag by writing 1 to it */
mbed_official 579:53297373a894 517 module->rx_status = STATUS_ERR_PROTOCOL;
mbed_official 579:53297373a894 518 usart_hw->STATUS.reg |= SERCOM_USART_STATUS_ISF;
mbed_official 579:53297373a894 519 }
mbed_official 579:53297373a894 520 #endif
mbed_official 579:53297373a894 521 #ifdef FEATURE_USART_COLLISION_DECTION
mbed_official 579:53297373a894 522 else if (error_code & SERCOM_USART_STATUS_COLL) {
mbed_official 579:53297373a894 523 /* Store the error code and clear flag by writing 1 to it */
mbed_official 579:53297373a894 524 module->rx_status = STATUS_ERR_PACKET_COLLISION;
mbed_official 579:53297373a894 525 usart_hw->STATUS.reg |= SERCOM_USART_STATUS_COLL;
mbed_official 579:53297373a894 526 }
mbed_official 579:53297373a894 527 #endif
mbed_official 579:53297373a894 528
mbed_official 579:53297373a894 529 /* Run callback if registered and enabled */
mbed_official 579:53297373a894 530 if (callback_status
mbed_official 579:53297373a894 531 & (1 << USART_CALLBACK_ERROR)) {
mbed_official 579:53297373a894 532 (*(module->callback[USART_CALLBACK_ERROR]))(module);
mbed_official 579:53297373a894 533 }
mbed_official 579:53297373a894 534
mbed_official 579:53297373a894 535 } else {
mbed_official 579:53297373a894 536
mbed_official 579:53297373a894 537 /* Read current packet from DATA register,
mbed_official 579:53297373a894 538 * increment buffer pointer and decrement buffer length */
mbed_official 579:53297373a894 539 uint16_t received_data = (usart_hw->DATA.reg & SERCOM_USART_DATA_MASK);
mbed_official 579:53297373a894 540
mbed_official 579:53297373a894 541 /* Read value will be at least 8-bits long */
mbed_official 579:53297373a894 542 *(module->rx_buffer_ptr) = received_data;
mbed_official 579:53297373a894 543 /* Increment 8-bit pointer */
mbed_official 579:53297373a894 544 module->rx_buffer_ptr += 1;
mbed_official 579:53297373a894 545
mbed_official 579:53297373a894 546 if (module->character_size == USART_CHARACTER_SIZE_9BIT) {
mbed_official 579:53297373a894 547 /* 9-bit data, write next received byte to the buffer */
mbed_official 579:53297373a894 548 *(module->rx_buffer_ptr) = (received_data >> 8);
mbed_official 579:53297373a894 549 /* Increment 8-bit pointer */
mbed_official 579:53297373a894 550 module->rx_buffer_ptr += 1;
mbed_official 579:53297373a894 551 }
mbed_official 579:53297373a894 552
mbed_official 579:53297373a894 553 /* Check if the last character have been received */
mbed_official 579:53297373a894 554 if(--(module->remaining_rx_buffer_length) == 0) {
mbed_official 579:53297373a894 555 /* Disable RX Complete Interrupt,
mbed_official 579:53297373a894 556 * and set STATUS_OK */
mbed_official 579:53297373a894 557 usart_hw->INTENCLR.reg = SERCOM_USART_INTFLAG_RXC;
mbed_official 579:53297373a894 558 module->rx_status = STATUS_OK;
mbed_official 579:53297373a894 559
mbed_official 579:53297373a894 560 /* Run callback if registered and enabled */
mbed_official 579:53297373a894 561 if (callback_status
mbed_official 579:53297373a894 562 & (1 << USART_CALLBACK_BUFFER_RECEIVED)) {
mbed_official 579:53297373a894 563 (*(module->callback[USART_CALLBACK_BUFFER_RECEIVED]))(module);
mbed_official 579:53297373a894 564 }
mbed_official 579:53297373a894 565 }
mbed_official 579:53297373a894 566 }
mbed_official 579:53297373a894 567 } else {
mbed_official 579:53297373a894 568 /* This should not happen. Disable Receive Complete interrupt. */
mbed_official 579:53297373a894 569 usart_hw->INTENCLR.reg = SERCOM_USART_INTFLAG_RXC;
mbed_official 579:53297373a894 570 }
mbed_official 579:53297373a894 571 }
mbed_official 579:53297373a894 572
mbed_official 579:53297373a894 573 #ifdef FEATURE_USART_HARDWARE_FLOW_CONTROL
mbed_official 579:53297373a894 574 if (interrupt_status & SERCOM_USART_INTFLAG_CTSIC) {
mbed_official 579:53297373a894 575 /* Disable interrupts */
mbed_official 579:53297373a894 576 usart_hw->INTENCLR.reg = SERCOM_USART_INTENCLR_CTSIC;
mbed_official 579:53297373a894 577 /* Clear interrupt flag */
mbed_official 579:53297373a894 578 usart_hw->INTFLAG.reg = SERCOM_USART_INTFLAG_CTSIC;
mbed_official 579:53297373a894 579
mbed_official 579:53297373a894 580 /* Run callback if registered and enabled */
mbed_official 579:53297373a894 581 if (callback_status & (1 << USART_CALLBACK_CTS_INPUT_CHANGE)) {
mbed_official 579:53297373a894 582 (*(module->callback[USART_CALLBACK_CTS_INPUT_CHANGE]))(module);
mbed_official 579:53297373a894 583 }
mbed_official 579:53297373a894 584 }
mbed_official 579:53297373a894 585 #endif
mbed_official 579:53297373a894 586
mbed_official 579:53297373a894 587 #ifdef FEATURE_USART_LIN_SLAVE
mbed_official 579:53297373a894 588 if (interrupt_status & SERCOM_USART_INTFLAG_RXBRK) {
mbed_official 579:53297373a894 589 /* Disable interrupts */
mbed_official 579:53297373a894 590 usart_hw->INTENCLR.reg = SERCOM_USART_INTENCLR_RXBRK;
mbed_official 579:53297373a894 591 /* Clear interrupt flag */
mbed_official 579:53297373a894 592 usart_hw->INTFLAG.reg = SERCOM_USART_INTFLAG_RXBRK;
mbed_official 579:53297373a894 593
mbed_official 579:53297373a894 594 /* Run callback if registered and enabled */
mbed_official 579:53297373a894 595 if (callback_status & (1 << USART_CALLBACK_BREAK_RECEIVED)) {
mbed_official 579:53297373a894 596 (*(module->callback[USART_CALLBACK_BREAK_RECEIVED]))(module);
mbed_official 579:53297373a894 597 }
mbed_official 579:53297373a894 598 }
mbed_official 579:53297373a894 599 #endif
mbed_official 579:53297373a894 600
mbed_official 579:53297373a894 601 #ifdef FEATURE_USART_START_FRAME_DECTION
mbed_official 579:53297373a894 602 if (interrupt_status & SERCOM_USART_INTFLAG_RXS) {
mbed_official 579:53297373a894 603 /* Disable interrupts */
mbed_official 579:53297373a894 604 usart_hw->INTENCLR.reg = SERCOM_USART_INTENCLR_RXS;
mbed_official 579:53297373a894 605 /* Clear interrupt flag */
mbed_official 579:53297373a894 606 usart_hw->INTFLAG.reg = SERCOM_USART_INTFLAG_RXS;
mbed_official 579:53297373a894 607
mbed_official 579:53297373a894 608 /* Run callback if registered and enabled */
mbed_official 579:53297373a894 609 if (callback_status & (1 << USART_CALLBACK_START_RECEIVED)) {
mbed_official 579:53297373a894 610 (*(module->callback[USART_CALLBACK_START_RECEIVED]))(module);
mbed_official 579:53297373a894 611 }
mbed_official 579:53297373a894 612 }
mbed_official 579:53297373a894 613 #endif
mbed_official 579:53297373a894 614 }