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.

Revision:
613:bc40b8d2aec4
Parent:
612:fba1c7dc54c0
Child:
614:9d86c2ae5de0
--- a/targets/hal/TARGET_Atmel/TARGET_SAM21/drivers/sercom/usart/usart_interrupt.c	Tue Aug 18 15:00:09 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,614 +0,0 @@
-#include "usart_interrupt.h"
-
-/**
- * \internal
- * Asynchronous write of a buffer with a given length
- *
- * \param[in]  module   Pointer to USART software instance struct
- * \param[in]  tx_data  Pointer to data to be transmitted
- * \param[in]  length   Length of data buffer
- *
- */
-void _usart_write_buffer(
-    struct usart_module *const module,
-    uint8_t *tx_data,
-    uint16_t length)
-{
-    /* Sanity check arguments */
-    Assert(module);
-    Assert(module->hw);
-
-    /* Get a pointer to the hardware module instance */
-    SercomUsart *const usart_hw = &(module->hw->USART);
-
-    /* Write parameters to the device instance */
-    module->remaining_tx_buffer_length = length;
-    module->tx_buffer_ptr              = tx_data;
-    module->tx_status                  = STATUS_BUSY;
-
-    /* Enable the Data Register Empty Interrupt */
-    usart_hw->INTENSET.reg = SERCOM_USART_INTFLAG_DRE;
-}
-
-/**
- * \internal
- * Asynchronous read of a buffer with a given length
- *
- * \param[in]  module   Pointer to USART software instance struct
- * \param[in]  rx_data  Pointer to data to be received
- * \param[in]  length   Length of data buffer
- *
- */
-void _usart_read_buffer(
-    struct usart_module *const module,
-    uint8_t *rx_data,
-    uint16_t length)
-{
-    /* Sanity check arguments */
-    Assert(module);
-    Assert(module->hw);
-
-    /* Get a pointer to the hardware module instance */
-    SercomUsart *const usart_hw = &(module->hw->USART);
-
-    /* Set length for the buffer and the pointer, and let
-     * the interrupt handler do the rest */
-    module->remaining_rx_buffer_length = length;
-    module->rx_buffer_ptr              = rx_data;
-    module->rx_status                  = STATUS_BUSY;
-
-    /* Enable the RX Complete Interrupt */
-    usart_hw->INTENSET.reg = SERCOM_USART_INTFLAG_RXC;
-
-#ifdef FEATURE_USART_LIN_SLAVE
-    /* Enable the break character is received Interrupt */
-    if(module->lin_slave_enabled) {
-        usart_hw->INTENSET.reg = SERCOM_USART_INTFLAG_RXBRK;
-    }
-#endif
-
-#ifdef FEATURE_USART_START_FRAME_DECTION
-    /* Enable a start condition is detected Interrupt */
-    if(module->start_frame_detection_enabled) {
-        usart_hw->INTENSET.reg = SERCOM_USART_INTFLAG_RXS;
-    }
-#endif
-}
-
-/**
- * \brief Registers a callback
- *
- * Registers a callback function which is implemented by the user.
- *
- * \note The callback must be enabled by \ref usart_enable_callback,
- *       in order for the interrupt handler to call it when the conditions for
- *       the callback type are met.
- *
- * \param[in]  module         Pointer to USART software instance struct
- * \param[in]  callback_func  Pointer to callback function
- * \param[in]  callback_type  Callback type given by an enum
- *
- */
-void usart_register_callback(
-    struct usart_module *const module,
-    usart_callback_t callback_func,
-    enum usart_callback callback_type)
-{
-    /* Sanity check arguments */
-    Assert(module);
-    Assert(callback_func);
-
-    /* Register callback function */
-    module->callback[callback_type] = callback_func;
-
-    /* Set the bit corresponding to the callback_type */
-    module->callback_reg_mask |= (1 << callback_type);
-}
-
-/**
- * \brief Unregisters a callback
- *
- * Unregisters a callback function which is implemented by the user.
- *
- * \param[in,out]  module         Pointer to USART software instance struct
- * \param[in]      callback_type  Callback type given by an enum
- *
- */
-void usart_unregister_callback(
-    struct usart_module *const module,
-    enum usart_callback callback_type)
-{
-    /* Sanity check arguments */
-    Assert(module);
-
-    /* Unregister callback function */
-    module->callback[callback_type] = NULL;
-
-    /* Clear the bit corresponding to the callback_type */
-    module->callback_reg_mask &= ~(1 << callback_type);
-}
-
-/**
- * \brief Asynchronous write a single char
- *
- * Sets up the driver to write the data given. If registered and enabled,
- * a callback function will be called when the transmit is completed.
- *
- * \param[in]  module   Pointer to USART software instance struct
- * \param[in]  tx_data  Data to transfer
- *
- * \returns Status of the operation.
- * \retval STATUS_OK         If operation was completed
- * \retval STATUS_BUSY       If operation was not completed, due to the
- *                           USART module being busy
- * \retval STATUS_ERR_DENIED If the transmitter is not enabled
- */
-enum status_code usart_write_job(
-    struct usart_module *const module,
-    const uint16_t *tx_data)
-{
-    /* Sanity check arguments */
-    Assert(module);
-    Assert(tx_data);
-
-    /* Check if the USART transmitter is busy */
-    if (module->remaining_tx_buffer_length > 0) {
-        return STATUS_BUSY;
-    }
-
-    /* Check that the transmitter is enabled */
-    if (!(module->transmitter_enabled)) {
-        return STATUS_ERR_DENIED;
-    }
-
-    /* Call internal write buffer function with length 1 */
-    _usart_write_buffer(module, (uint8_t *)tx_data, 1);
-
-    return STATUS_OK;
-}
-
-/**
- * \brief Asynchronous read a single char
- *
- * Sets up the driver to read data from the USART module to the data
- * pointer given. If registered and enabled, a callback will be called
- * when the receiving is completed.
- *
- * \param[in]   module   Pointer to USART software instance struct
- * \param[out]  rx_data  Pointer to where received data should be put
- *
- * \returns Status of the operation.
- * \retval  STATUS_OK    If operation was completed
- * \retval  STATUS_BUSY  If operation was not completed
- */
-enum status_code usart_read_job(
-    struct usart_module *const module,
-    uint16_t *const rx_data)
-{
-    /* Sanity check arguments */
-    Assert(module);
-    Assert(rx_data);
-
-    /* Check if the USART receiver is busy */
-    if (module->remaining_rx_buffer_length > 0) {
-        return STATUS_BUSY;
-    }
-
-    /* Call internal read buffer function with length 1 */
-    _usart_read_buffer(module, (uint8_t *)rx_data, 1);
-
-    return STATUS_OK;
-}
-
-/**
- * \brief Asynchronous buffer write
- *
- * Sets up the driver to write a given buffer over the USART. If registered and
- * enabled, a callback function will be called.
- *
- * \param[in]  module   Pointer to USART software instance struct
- * \param[in]  tx_data  Pointer do data buffer to transmit
- * \param[in]  length   Length of the data to transmit
- *
- * \note if using 9-bit data, the array that *tx_data point to should be defined
- *       as uint16_t array and should be casted to uint8_t* pointer. Because it
- *       is an address pointer, the highest byte is not discarded. For example:
- *   \code
-          #define TX_LEN 3
-          uint16_t tx_buf[TX_LEN] = {0x0111, 0x0022, 0x0133};
-          usart_write_buffer_job(&module, (uint8_t*)tx_buf, TX_LEN);
-    \endcode
- *
- * \returns Status of the operation.
- * \retval STATUS_OK              If operation was completed successfully.
- * \retval STATUS_BUSY            If operation was not completed, due to the
- *                                USART module being busy
- * \retval STATUS_ERR_INVALID_ARG If operation was not completed, due to invalid
- *                                arguments
- * \retval STATUS_ERR_DENIED      If the transmitter is not enabled
- */
-enum status_code usart_write_buffer_job(
-    struct usart_module *const module,
-    uint8_t *tx_data,
-    uint16_t length)
-{
-    /* Sanity check arguments */
-    Assert(module);
-    Assert(tx_data);
-
-    if (length == 0) {
-        return STATUS_ERR_INVALID_ARG;
-    }
-
-    /* Check if the USART transmitter is busy */
-    if (module->remaining_tx_buffer_length > 0) {
-        return STATUS_BUSY;
-    }
-
-    /* Check that the receiver is enabled */
-    if (!(module->transmitter_enabled)) {
-        return STATUS_ERR_DENIED;
-    }
-
-    /* Issue internal asynchronous write */
-    _usart_write_buffer(module, tx_data, length);
-
-    return STATUS_OK;
-}
-
-/**
- * \brief Asynchronous buffer read
- *
- * Sets up the driver to read from the USART to a given buffer. If registered
- * and enabled, a callback function will be called.
- *
- * \param[in]  module   Pointer to USART software instance struct
- * \param[out] rx_data  Pointer to data buffer to receive
- * \param[in]  length   Data buffer length
- *
- * \note if using 9-bit data, the array that *rx_data point to should be defined
- *       as uint16_t array and should be casted to uint8_t* pointer. Because it
- *       is an address pointer, the highest byte is not discarded. For example:
- *   \code
-           #define RX_LEN 3
-           uint16_t rx_buf[RX_LEN] = {0x0,};
-           usart_read_buffer_job(&module, (uint8_t*)rx_buf, RX_LEN);
-    \endcode
- *
- * \returns Status of the operation.
- * \retval STATUS_OK              If operation was completed
- * \retval STATUS_BUSY            If operation was not completed, due to the
- *                                USART module being busy
- * \retval STATUS_ERR_INVALID_ARG If operation was not completed, due to invalid
- *                                arguments
- * \retval STATUS_ERR_DENIED      If the transmitter is not enabled
- */
-enum status_code usart_read_buffer_job(
-    struct usart_module *const module,
-    uint8_t *rx_data,
-    uint16_t length)
-{
-    /* Sanity check arguments */
-    Assert(module);
-    Assert(rx_data);
-
-    if (length == 0) {
-        return STATUS_ERR_INVALID_ARG;
-    }
-
-    /* Check that the receiver is enabled */
-    if (!(module->receiver_enabled)) {
-        return STATUS_ERR_DENIED;
-    }
-
-    /* Check if the USART receiver is busy */
-    if (module->remaining_rx_buffer_length > 0) {
-        return STATUS_BUSY;
-    }
-
-    /* Issue internal asynchronous read */
-    _usart_read_buffer(module, rx_data, length);
-
-    return STATUS_OK;
-}
-
-/**
- * \brief Cancels ongoing read/write operation
- *
- * Cancels the ongoing read/write operation modifying parameters in the
- * USART software struct.
- *
- * \param[in]  module            Pointer to USART software instance struct
- * \param[in]  transceiver_type  Transfer type to cancel
- */
-void usart_abort_job(
-    struct usart_module *const module,
-    enum usart_transceiver_type transceiver_type)
-{
-    /* Sanity check arguments */
-    Assert(module);
-    Assert(module->hw);
-
-    /* Get a pointer to the hardware module instance */
-    SercomUsart *const usart_hw = &(module->hw->USART);
-
-    switch(transceiver_type) {
-        case USART_TRANSCEIVER_RX:
-            /* Clear the interrupt flag in order to prevent the receive
-             * complete callback to fire */
-            usart_hw->INTFLAG.reg = SERCOM_USART_INTFLAG_RXC;
-
-            /* Clear the software reception buffer */
-            module->remaining_rx_buffer_length = 0;
-
-            break;
-
-        case USART_TRANSCEIVER_TX:
-            /* Clear the interrupt flag in order to prevent the receive
-             * complete callback to fire */
-            usart_hw->INTFLAG.reg = SERCOM_USART_INTFLAG_TXC;
-
-            /* Clear the software reception buffer */
-            module->remaining_tx_buffer_length = 0;
-
-            break;
-    }
-}
-
-/**
- * \brief Get status from the ongoing or last asynchronous transfer operation
- *
- * Returns the error from a given ongoing or last asynchronous transfer operation.
- * Either from a read or write transfer.
- *
- * \param[in]  module            Pointer to USART software instance struct
- * \param[in]  transceiver_type  Transfer type to check
-  *
- * \return Status of the given job.
- * \retval STATUS_OK               No error occurred during the last transfer
- * \retval STATUS_BUSY             A transfer is ongoing
- * \retval STATUS_ERR_BAD_DATA     The last operation was aborted due to a
- *                                 parity error. The transfer could be affected
- *                                 by external noise
- * \retval STATUS_ERR_BAD_FORMAT   The last operation was aborted due to a
- *                                 frame error
- * \retval STATUS_ERR_OVERFLOW     The last operation was aborted due to a
- *                                 buffer overflow
- * \retval STATUS_ERR_INVALID_ARG  An invalid transceiver enum given
- */
-enum status_code usart_get_job_status(
-    struct usart_module *const module,
-    enum usart_transceiver_type transceiver_type)
-{
-    /* Sanity check arguments */
-    Assert(module);
-
-    /* Variable for status code */
-    enum status_code status_code;
-
-    switch(transceiver_type) {
-        case USART_TRANSCEIVER_RX:
-            status_code = module->rx_status;
-            break;
-
-        case USART_TRANSCEIVER_TX:
-            status_code = module->tx_status;
-            break;
-
-        default:
-            status_code = STATUS_ERR_INVALID_ARG;
-            break;
-    }
-
-    return status_code;
-}
-
-/**
- * \internal
- * Handles interrupts as they occur, and it will run callback functions
- * which are registered and enabled.
- *
- * \param[in]  instance  ID of the SERCOM instance calling the interrupt
- *                       handler.
- */
-void _usart_interrupt_handler(
-    uint8_t instance)
-{
-    /* Temporary variables */
-    uint16_t interrupt_status;
-    uint16_t callback_status;
-    uint8_t error_code;
-
-
-    /* Get device instance from the look-up table */
-    struct usart_module *module
-        = (struct usart_module *)_sercom_instances[instance];
-
-    /* Pointer to the hardware module instance */
-    SercomUsart *const usart_hw
-        = &(module->hw->USART);
-
-    /* Wait for the synchronization to complete */
-    _usart_wait_for_sync(module);
-
-    /* Read and mask interrupt flag register */
-    interrupt_status = usart_hw->INTFLAG.reg;
-    interrupt_status &= usart_hw->INTENSET.reg;
-    callback_status = module->callback_reg_mask &
-                      module->callback_enable_mask;
-
-    /* Check if a DATA READY interrupt has occurred,
-     * and if there is more to transfer */
-    if (interrupt_status & SERCOM_USART_INTFLAG_DRE) {
-        if (module->remaining_tx_buffer_length) {
-            /* Write value will be at least 8-bits long */
-            uint16_t data_to_send = *(module->tx_buffer_ptr);
-            /* Increment 8-bit pointer */
-            (module->tx_buffer_ptr)++;
-
-            if (module->character_size == USART_CHARACTER_SIZE_9BIT) {
-                data_to_send |= (*(module->tx_buffer_ptr) << 8);
-                /* Increment 8-bit pointer */
-                (module->tx_buffer_ptr)++;
-            }
-            /* Write the data to send */
-            usart_hw->DATA.reg = (data_to_send & SERCOM_USART_DATA_MASK);
-
-            if (--(module->remaining_tx_buffer_length) == 0) {
-                /* Disable the Data Register Empty Interrupt */
-                usart_hw->INTENCLR.reg = SERCOM_USART_INTFLAG_DRE;
-                /* Enable Transmission Complete interrupt */
-                usart_hw->INTENSET.reg = SERCOM_USART_INTFLAG_TXC;
-
-            }
-        } else {
-            usart_hw->INTENCLR.reg = SERCOM_USART_INTFLAG_DRE;
-        }
-
-        /* Check if the Transmission Complete interrupt has occurred and
-         * that the transmit buffer is empty */
-    }
-
-    if (interrupt_status & SERCOM_USART_INTFLAG_TXC) {
-
-        /* Disable TX Complete Interrupt, and set STATUS_OK */
-        usart_hw->INTENCLR.reg = SERCOM_USART_INTFLAG_TXC;
-        module->tx_status = STATUS_OK;
-
-        /* Run callback if registered and enabled */
-        if (callback_status & (1 << USART_CALLBACK_BUFFER_TRANSMITTED)) {
-            (*(module->callback[USART_CALLBACK_BUFFER_TRANSMITTED]))(module);
-        }
-
-        /* Check if the Receive Complete interrupt has occurred, and that
-         * there's more data to receive */
-    }
-
-    if (interrupt_status & SERCOM_USART_INTFLAG_RXC) {
-
-        if (module->remaining_rx_buffer_length) {
-            /* Read out the status code and mask away all but the 4 LSBs*/
-            error_code = (uint8_t)(usart_hw->STATUS.reg & SERCOM_USART_STATUS_MASK);
-#if !SAMD20
-            /* CTS status should not be considered as an error */
-            if(error_code & SERCOM_USART_STATUS_CTS) {
-                error_code &= ~SERCOM_USART_STATUS_CTS;
-            }
-#endif
-            /* Check if an error has occurred during the receiving */
-            if (error_code) {
-                /* Check which error occurred */
-                if (error_code & SERCOM_USART_STATUS_FERR) {
-                    /* Store the error code and clear flag by writing 1 to it */
-                    module->rx_status = STATUS_ERR_BAD_FORMAT;
-                    usart_hw->STATUS.reg |= SERCOM_USART_STATUS_FERR;
-                } else if (error_code & SERCOM_USART_STATUS_BUFOVF) {
-                    /* Store the error code and clear flag by writing 1 to it */
-                    module->rx_status = STATUS_ERR_OVERFLOW;
-                    usart_hw->STATUS.reg |= SERCOM_USART_STATUS_BUFOVF;
-                } else if (error_code & SERCOM_USART_STATUS_PERR) {
-                    /* Store the error code and clear flag by writing 1 to it */
-                    module->rx_status = STATUS_ERR_BAD_DATA;
-                    usart_hw->STATUS.reg |= SERCOM_USART_STATUS_PERR;
-                }
-#ifdef FEATURE_USART_LIN_SLAVE
-                else if (error_code & SERCOM_USART_STATUS_ISF) {
-                    /* Store the error code and clear flag by writing 1 to it */
-                    module->rx_status = STATUS_ERR_PROTOCOL;
-                    usart_hw->STATUS.reg |= SERCOM_USART_STATUS_ISF;
-                }
-#endif
-#ifdef FEATURE_USART_COLLISION_DECTION
-                else if (error_code & SERCOM_USART_STATUS_COLL) {
-                    /* Store the error code and clear flag by writing 1 to it */
-                    module->rx_status = STATUS_ERR_PACKET_COLLISION;
-                    usart_hw->STATUS.reg |= SERCOM_USART_STATUS_COLL;
-                }
-#endif
-
-                /* Run callback if registered and enabled */
-                if (callback_status
-                        & (1 << USART_CALLBACK_ERROR)) {
-                    (*(module->callback[USART_CALLBACK_ERROR]))(module);
-                }
-
-            } else {
-
-                /* Read current packet from DATA register,
-                 * increment buffer pointer and decrement buffer length */
-                uint16_t received_data = (usart_hw->DATA.reg & SERCOM_USART_DATA_MASK);
-
-                /* Read value will be at least 8-bits long */
-                *(module->rx_buffer_ptr) = received_data;
-                /* Increment 8-bit pointer */
-                module->rx_buffer_ptr += 1;
-
-                if (module->character_size == USART_CHARACTER_SIZE_9BIT) {
-                    /* 9-bit data, write next received byte to the buffer */
-                    *(module->rx_buffer_ptr) = (received_data >> 8);
-                    /* Increment 8-bit pointer */
-                    module->rx_buffer_ptr += 1;
-                }
-
-                /* Check if the last character have been received */
-                if(--(module->remaining_rx_buffer_length) == 0) {
-                    /* Disable RX Complete Interrupt,
-                     * and set STATUS_OK */
-                    usart_hw->INTENCLR.reg = SERCOM_USART_INTFLAG_RXC;
-                    module->rx_status = STATUS_OK;
-
-                    /* Run callback if registered and enabled */
-                    if (callback_status
-                            & (1 << USART_CALLBACK_BUFFER_RECEIVED)) {
-                        (*(module->callback[USART_CALLBACK_BUFFER_RECEIVED]))(module);
-                    }
-                }
-            }
-        } else {
-            /* This should not happen. Disable Receive Complete interrupt. */
-            usart_hw->INTENCLR.reg = SERCOM_USART_INTFLAG_RXC;
-        }
-    }
-
-#ifdef FEATURE_USART_HARDWARE_FLOW_CONTROL
-    if (interrupt_status & SERCOM_USART_INTFLAG_CTSIC) {
-        /* Disable interrupts */
-        usart_hw->INTENCLR.reg = SERCOM_USART_INTENCLR_CTSIC;
-        /* Clear interrupt flag */
-        usart_hw->INTFLAG.reg = SERCOM_USART_INTFLAG_CTSIC;
-
-        /* Run callback if registered and enabled */
-        if (callback_status & (1 << USART_CALLBACK_CTS_INPUT_CHANGE)) {
-            (*(module->callback[USART_CALLBACK_CTS_INPUT_CHANGE]))(module);
-        }
-    }
-#endif
-
-#ifdef FEATURE_USART_LIN_SLAVE
-    if (interrupt_status & SERCOM_USART_INTFLAG_RXBRK) {
-        /* Disable interrupts */
-        usart_hw->INTENCLR.reg = SERCOM_USART_INTENCLR_RXBRK;
-        /* Clear interrupt flag */
-        usart_hw->INTFLAG.reg = SERCOM_USART_INTFLAG_RXBRK;
-
-        /* Run callback if registered and enabled */
-        if (callback_status & (1 << USART_CALLBACK_BREAK_RECEIVED)) {
-            (*(module->callback[USART_CALLBACK_BREAK_RECEIVED]))(module);
-        }
-    }
-#endif
-
-#ifdef FEATURE_USART_START_FRAME_DECTION
-    if (interrupt_status & SERCOM_USART_INTFLAG_RXS) {
-        /* Disable interrupts */
-        usart_hw->INTENCLR.reg = SERCOM_USART_INTENCLR_RXS;
-        /* Clear interrupt flag */
-        usart_hw->INTFLAG.reg = SERCOM_USART_INTFLAG_RXS;
-
-        /* Run callback if registered and enabled */
-        if (callback_status & (1 << USART_CALLBACK_START_RECEIVED)) {
-            (*(module->callback[USART_CALLBACK_START_RECEIVED]))(module);
-        }
-    }
-#endif
-}