mbed library sources

Fork of mbed-src by mbed official

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 }