Modified version of the mbed library for use with the Nucleo boards.

Dependents:   EEPROMWrite Full-Project

Fork of mbed-src by mbed official

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
-}