You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by ma...@apache.org on 2016/02/27 02:26:35 UTC
[33/51] [abbrv] [partial] incubator-mynewt-larva git commit: Arduino
zero BSP and Atmel MCU in a different repository.
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/a280628a/hw/mcu/atmel/samd21xx/src/sam0/drivers/sercom/spi_master_vec/spi_master_vec.c
----------------------------------------------------------------------
diff --git a/hw/mcu/atmel/samd21xx/src/sam0/drivers/sercom/spi_master_vec/spi_master_vec.c b/hw/mcu/atmel/samd21xx/src/sam0/drivers/sercom/spi_master_vec/spi_master_vec.c
deleted file mode 100755
index 39a7327..0000000
--- a/hw/mcu/atmel/samd21xx/src/sam0/drivers/sercom/spi_master_vec/spi_master_vec.c
+++ /dev/null
@@ -1,586 +0,0 @@
-/**
- * \file
- *
- * \brief SERCOM SPI master with vectored I/O driver implementation
- *
- * Copyright (C) 2013-2015 Atmel Corporation. All rights reserved.
- *
- * \asf_license_start
- *
- * \page License
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * 3. The name of Atmel may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * 4. This software may only be redistributed and used in connection with an
- * Atmel microcontroller product.
- *
- * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
- * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- * \asf_license_stop
- *
- */
-/*
- * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
- */
-
-#include "spi_master_vec.h"
-#include <sercom_interrupt.h>
-#include <system.h>
-#include <system_interrupt.h>
-
-/**
- * \ingroup asfdoc_sam0_sercom_spi_master_vec_group
- *
- * @{
- */
-
-/**
- * \name Internal functions
- * @{
- */
-
-/** \cond INTERNAL */
-
-static void _spi_master_vec_int_handler(uint8_t sercom_index);
-
-/**
- * \brief Wait for SERCOM SPI to synchronize
- *
- * \param[in] sercom_spi SERCOM SPI to check for synchronization.
- *
- * \note The implementation of this function depends on the SERCOM revision.
- */
-static inline void _spi_master_vec_wait_for_sync(SercomSpi *const sercom_spi)
-{
-#if defined(FEATURE_SERCOM_SYNCBUSY_SCHEME_VERSION_1)
- while (sercom_spi->STATUS.reg & SERCOM_SPI_STATUS_SYNCBUSY) {
- /* Intentionally left empty */
- }
-#elif defined(FEATURE_SERCOM_SYNCBUSY_SCHEME_VERSION_2)
- while (sercom_spi->SYNCBUSY.reg) {
- /* Intentionally left empty */
- }
-#else
-# error Unknown SERCOM SYNCBUSY scheme!
-#endif
-}
-
-/**
- * \brief Pin MUX configuration helper
- *
- * \param[in] pinmux Pin MUX setting to apply. Special values:
- * \arg \c PINMUX_UNUSED to do nothing.
- * \arg \c PINMUX_DEFAULT to use default pin MUX for the SERCOM pad.
- * \param[in] sercom,padnum SERCOM pad specification, for \ref PINMUX_DEFAULT.
- */
-static inline void _spi_master_vec_pinmux_helper(uint32_t pinmux,
- Sercom *const sercom, uint8_t padnum)
-{
- struct system_pinmux_config pin_conf;
-
- if (pinmux == PINMUX_DEFAULT) {
- pinmux = _sercom_get_default_pad(sercom, padnum);
- }
-
- if (pinmux == PINMUX_UNUSED) {
- return;
- }
-
- system_pinmux_get_config_defaults(&pin_conf);
- pin_conf.mux_position = pinmux & 0xFFFF;
- system_pinmux_pin_set_config(pinmux >> 16, &pin_conf);
-};
-
-/** \endcond */
-
-/** @} */
-
-/**
- * \brief Initialize hardware and driver instance
- *
- * This function configures the clock system for the specified SERCOM module,
- * sets up the related pins and their MUX, initializes the SERCOM in SPI master
- * mode, and prepares the driver instance for operation.
- *
- * \pre \ref system_init() must have been called prior to this function.
- *
- * The SERCOM SPI module is left disabled after initialization, and must be
- * enabled with \ref spi_master_vec_enable() before a transfer can be done.
- *
- * \param[out] module Driver instance to initialize.
- * \param[in,out] sercom SERCOM module to initialize and associate driver
- * instance with.
- * \param[in] config Driver configuration to use.
- *
- * \return Status of initialization.
- * \retval STATUS_OK if initialization succeeded.
- * \retval STATUS_ERR_INVALID_ARG if driver has been misconfigured.
- */
-enum status_code spi_master_vec_init(struct spi_master_vec_module *const module,
- Sercom *const sercom, const struct spi_master_vec_config *const config)
-{
- Assert(module);
- Assert(sercom);
- Assert(config);
-
- enum status_code status;
- SercomSpi *const spi_hw = &(sercom->SPI);
- struct system_gclk_chan_config gclk_chan_conf;
- uint16_t tmp_baud;
- uint32_t sercom_index = _sercom_get_sercom_inst_index((Sercom *)spi_hw);
-#if (SAML21) || (SAML22) || (SAMC20) || (SAMC21)
- uint32_t pm_index = sercom_index + MCLK_APBCMASK_SERCOM0_Pos;
-#else
- uint32_t pm_index = sercom_index + PM_APBCMASK_SERCOM0_Pos;
-#endif
- uint32_t gclk_index = sercom_index + SERCOM0_GCLK_ID_CORE;
- uint32_t gclk_hz;
-
- module->sercom = sercom;
-
- /* Enable clock for the module interface */
- system_apb_clock_set_mask(SYSTEM_CLOCK_APB_APBC, 1 << pm_index);
-
- /* Set up the GCLK for the module */
- system_gclk_chan_get_config_defaults(&gclk_chan_conf);
- gclk_chan_conf.source_generator = config->gclk_generator;
- system_gclk_chan_set_config(gclk_index, &gclk_chan_conf);
- system_gclk_chan_enable(gclk_index);
- sercom_set_gclk_generator(config->gclk_generator, false);
-
- _spi_master_vec_wait_for_sync(spi_hw);
-
- /* Set up the SERCOM SPI module as master */
- spi_hw->CTRLA.reg = SERCOM_SPI_CTRLA_MODE(0x3);
- spi_hw->CTRLA.reg |= (uint32_t)config->mux_setting
- | config->transfer_mode
- | config->data_order
- | ((config->run_in_standby || system_is_debugger_present()) ?
- SERCOM_SPI_CTRLA_RUNSTDBY : 0);
-
- /* Get baud value from configured baudrate and internal clock rate */
- gclk_hz = system_gclk_chan_get_hz(gclk_index);
- status = _sercom_get_sync_baud_val(config->baudrate, gclk_hz, &tmp_baud);
-
- if (status != STATUS_OK) {
- /* Baud rate calculation error! */
- return STATUS_ERR_INVALID_ARG;
- }
-
- spi_hw->BAUD.reg = (uint8_t)tmp_baud;
-
- /* Configure the pin multiplexers */
- _spi_master_vec_pinmux_helper(config->pinmux_pad0, sercom, 0);
- _spi_master_vec_pinmux_helper(config->pinmux_pad3, sercom, 3);
-
- /* SERCOM PAD1 and PAD2 are used for slave SS.
- * This is a SPI master driver, so control of slave SS must be left to
- * the PORT module, i.e., peripheral MUX should not be set for that pin.
- * DOPO controls which PAD is used for slave SS:
- * If DOPO is odd, SERCOM_PAD1 is SS: SERCOM_PAD2 can be MUXed.
- * If DOPO is even, SERCOM_PAD2 is SS: SERCOM_PAD1 can be MUXed.
- */
- if (config->mux_setting & (1 << SERCOM_SPI_CTRLA_DOPO_Pos)) {
- _spi_master_vec_pinmux_helper(config->pinmux_pad2, sercom, 2);
- } else {
- _spi_master_vec_pinmux_helper(config->pinmux_pad1, sercom, 1);
- }
-
- /* Initialize our instance and register interrupt handler + data */
- module->rx_bufdesc_ptr = NULL;
- module->tx_bufdesc_ptr = NULL;
- module->direction = SPI_MASTER_VEC_DIRECTION_IDLE;
- module->status = STATUS_OK;
-#ifdef CONF_SPI_MASTER_VEC_OS_SUPPORT
- CONF_SPI_MASTER_VEC_CREATE_SEMAPHORE(module->busy_semaphore);
-#endif
-
- _sercom_set_handler(sercom_index, _spi_master_vec_int_handler);
- _sercom_instances[sercom_index] = module;
-
- return STATUS_OK;
-}
-
-/**
- * \brief Enable the SERCOM SPI module
- *
- * This function must be called after \ref spi_master_vec_init() before a
- * transfer can be started.
- *
- * \param[in,out] module Driver instance to operate on.
- */
-void spi_master_vec_enable(const struct spi_master_vec_module *const module)
-{
- Assert(module);
- Assert(module->sercom);
-
- SercomSpi *const spi_hw = &(module->sercom->SPI);
-
- spi_hw->INTENCLR.reg = SERCOM_SPI_INTFLAG_DRE | SERCOM_SPI_INTFLAG_RXC
- | SERCOM_SPI_INTFLAG_TXC;
-
- _spi_master_vec_wait_for_sync(spi_hw);
-
- spi_hw->CTRLA.reg |= SERCOM_SPI_CTRLA_ENABLE;
-
- system_interrupt_enable(_sercom_get_interrupt_vector(module->sercom));
-}
-
-/**
- * \brief Disable the SERCOM SPI module
- *
- * \param[in,out] module Driver instance to operate on.
- */
-void spi_master_vec_disable(struct spi_master_vec_module *const module)
-{
- Assert(module);
- Assert(module->sercom);
-
- SercomSpi *const spi_hw = &(module->sercom->SPI);
-
- system_interrupt_disable(_sercom_get_interrupt_vector(module->sercom));
-
- _spi_master_vec_wait_for_sync(spi_hw);
-
- spi_hw->CTRLB.reg = 0;
- spi_hw->CTRLA.reg &= ~SERCOM_SPI_CTRLA_ENABLE;
- module->rx_bufdesc_ptr = NULL;
- module->tx_bufdesc_ptr = NULL;
- module->direction = SPI_MASTER_VEC_DIRECTION_IDLE;
- module->status = STATUS_OK;
-}
-
-/**
- * \brief Reset the SERCOM SPI module
- *
- * This function will disable and reset the SPI module to its power on default
- * values.
- *
- * \param[in,out] module Pointer to a driver instance.
- */
-void spi_master_vec_reset(struct spi_master_vec_module *const module)
-{
- /* Sanity check arguments */
- Assert(module);
- Assert(module->sercom);
-
- SercomSpi *const spi_hw = &(module->sercom->SPI);
-
- /* Disable the module */
- spi_master_vec_disable(module);
-
- _spi_master_vec_wait_for_sync(spi_hw);
-
- /* Software reset the module */
- spi_hw->CTRLA.reg |= SERCOM_SPI_CTRLA_SWRST;
-
-#ifdef CONF_SPI_MASTER_VEC_OS_SUPPORT
- CONF_SPI_MASTER_VEC_DELETE_SEMAPHORE(module->busy_semaphore);
-#endif
-}
-
-/**
- * \brief Start vectored I/O transfer
- *
- * This function initiates a uni- or bidirectional SPI transfer from/to any
- * number of data buffers. The transfer is interrupt-driven and will run in the
- * background, after this function has returned.
- *
- * The buffers to transmit from or receive into must be described in arrays of
- * buffer descriptors. These arrays \e must end with descriptors that specify
- * zero buffer length. The first descriptor in an array can \e not specify zero
- * length. The number of bytes to transmit and to receive do not have to be
- * equal.
- *
- * If the address for a receive buffer is set to \c NULL, the received bytes
- * corresponding to that buffer descriptor will be discarded. This is useful if
- * slave is already set up to transfer a number of bytes, but the master has no
- * available buffer to receive them into. As an example, to receive the two
- * first bytes and discard the 128 following, the buffer descriptors could be:
-\code
- struct spi_master_vec_bufdesc rx_buffers[3] = {
- // Read two status bytes
- {.data = status_buffer, .length = 2},
- // Discard 128 data bytes
- {.data = NULL, .length = 128},
- // End of reception
- {.length = 0},
- };
-\endcode
- *
- * To initiate a unidirectional transfer, pass \c NULL as the address of either
- * buffer descriptor array, like this:
-\code
- // Transmit some buffers
- spi_master_vec_transceive_buffer_job(&module, tx_buffers, NULL);
-
- // Receive some buffers
- spi_master_vec_transceive_buffer_job(&module, NULL, rx_buffers);
-\endcode
- *
- * \pre \ref spi_master_vec_init() and \ref spi_master_vec_enable() must have
- * been called before this function.
- *
- * \param[in,out] module Driver instance to operate on.
- * \param[in] tx_bufdescs address of buffer descriptor array for bytes to
- * transmit.
- * \arg \c NULL if the transfer is a simplex read.
- * \param[in,out] rx_bufdescs address of buffer descriptor array for storing
- * received bytes.
- * \arg \c NULL if the transfer is a simplex write.
- *
- * \return Status of transfer start.
- * \retval STATUS_OK if transfer was started.
- * \retval STATUS_BUSY if a transfer is already on-going.
- */
-enum status_code spi_master_vec_transceive_buffer_job(
- struct spi_master_vec_module *const module,
- struct spi_master_vec_bufdesc tx_bufdescs[],
- struct spi_master_vec_bufdesc rx_bufdescs[])
-{
- Assert(module);
- Assert(module->sercom);
- Assert(tx_bufdescs || rx_bufdescs);
-
- SercomSpi *const spi_hw = &(module->sercom->SPI);
- uint32_t tmp_ctrlb;
- uint8_t tmp_intenset;
-
- system_interrupt_enter_critical_section();
- if (module->status == STATUS_BUSY) {
- system_interrupt_leave_critical_section();
- return STATUS_BUSY;
- } else {
- module->status = STATUS_BUSY;
- system_interrupt_leave_critical_section();
- }
-
-#ifdef CONF_SPI_MASTER_VEC_OS_SUPPORT
- CONF_SPI_MASTER_VEC_TAKE_SEMAPHORE(module->busy_semaphore);
-#endif
-
- module->tx_bufdesc_ptr = tx_bufdescs;
- module->rx_bufdesc_ptr = rx_bufdescs;
-
- if (tx_bufdescs && rx_bufdescs) {
- Assert(tx_bufdescs[0].length);
- Assert(rx_bufdescs[0].length);
-
- module->direction = SPI_MASTER_VEC_DIRECTION_BOTH;
- module->tx_length = tx_bufdescs[0].length;
- module->tx_head_ptr = tx_bufdescs[0].data;
- module->rx_length = rx_bufdescs[0].length;
- module->rx_head_ptr = rx_bufdescs[0].data;
- module->tx_lead_on_rx = 0;
- tmp_ctrlb = SERCOM_SPI_CTRLB_RXEN;
- tmp_intenset = SERCOM_SPI_INTFLAG_DRE | SERCOM_SPI_INTFLAG_RXC;
- } else {
- if (tx_bufdescs) {
- Assert(tx_bufdescs[0].length);
-
- module->direction = SPI_MASTER_VEC_DIRECTION_WRITE;
- module->tx_length = tx_bufdescs[0].length;
- module->tx_head_ptr = tx_bufdescs[0].data;
- tmp_ctrlb = 0;
- tmp_intenset = SERCOM_SPI_INTFLAG_DRE;
- } else {
- Assert(rx_bufdescs[0].length);
-
- module->direction = SPI_MASTER_VEC_DIRECTION_READ;
- module->rx_length = rx_bufdescs[0].length;
- module->rx_head_ptr = rx_bufdescs[0].data;
- module->tx_lead_on_rx = 0;
- tmp_ctrlb = SERCOM_SPI_CTRLB_RXEN;
- tmp_intenset = SERCOM_SPI_INTFLAG_DRE | SERCOM_SPI_INTFLAG_RXC;
- }
- }
-
- /* Ensure the SERCOM is sync'ed before writing these registers */
- _spi_master_vec_wait_for_sync(spi_hw);
-
- spi_hw->CTRLB.reg = tmp_ctrlb;
- spi_hw->INTENSET.reg = tmp_intenset;
-
- return STATUS_OK;
-}
-
-/**
- * \brief Interrupt handler
- *
- * \param[in] sercom_index SERCOM instance number passed from the master SERCOM
- * driver.
- */
-static void _spi_master_vec_int_handler(uint8_t sercom_index)
-{
- struct spi_master_vec_module *const module =
- _sercom_instances[sercom_index];
- enum _spi_master_vec_direction dir = module->direction;
- SercomSpi *const spi_hw = &(module->sercom->SPI);
- uint8_t int_status;
-
- int_status = spi_hw->INTFLAG.reg ;
- int_status &= spi_hw->INTENSET.reg;
-
- if (int_status & SERCOM_SPI_INTFLAG_DRE) {
- uint_fast8_t tx_lead_on_rx = module->tx_lead_on_rx;
-
- /* If TX is ahead of RX by 2+ bytes, allow RX to catch up.
- * Note: will only happen _once_ per READ or BOTH.
- */
- if ((tx_lead_on_rx >= 2) && (dir != SPI_MASTER_VEC_DIRECTION_WRITE)) {
- Assert((dir == SPI_MASTER_VEC_DIRECTION_READ)
- || (dir == SPI_MASTER_VEC_DIRECTION_BOTH));
- Assert(int_status & SERCOM_SPI_INTFLAG_RXC);
- /* Otherwise, we can send more bytes */
- } else {
- module->tx_lead_on_rx = ++tx_lead_on_rx;
-
- /* If doing a READ, just send 0 to trigger the transfer */
- if (dir == SPI_MASTER_VEC_DIRECTION_READ) {
- uint32_t tx_lead_limit;
-
- spi_hw->DATA.reg = 0;
-
-check_for_read_end:
- /* With current TX'ed bytes, will we get the last RX byte?
- * If so, we can disable the DRE interrupt to stop transmitting.
- *
- * Since a buffer can have minimum 1 byte length, this check is
- * simplified by first checking if the RX end is so close that
- * the max. 2 byte lead of TX may actually fill the buffers.
- */
- tx_lead_limit = (module->rx_bufdesc_ptr + 1)->length;
-
- if (!tx_lead_limit || !(module->rx_bufdesc_ptr + 2)->length) {
- tx_lead_limit += module->rx_length;
-
- if (tx_lead_on_rx >= tx_lead_limit) {
- spi_hw->INTENCLR.reg = SERCOM_SPI_INTFLAG_DRE;
- }
- }
- /* For WRITE and BOTH, output current byte */
- } else {
- spi_master_vec_buflen_t tx_length;
- uint8_t *tx_head_ptr;
-
- tx_head_ptr = module->tx_head_ptr;
- spi_hw->DATA.reg = *(tx_head_ptr++);
-
- /* Check if this was the last byte to send */
- tx_length = module->tx_length - 1;
-
- if (tx_length) {
- module->tx_head_ptr = tx_head_ptr;
- module->tx_length = tx_length;
- } else {
- /* Any more buffers left to send, perhaps? */
- tx_length = (++module->tx_bufdesc_ptr)->length;
-
- if (tx_length) {
- module->tx_head_ptr = module->tx_bufdesc_ptr->data;
- module->tx_length = tx_length;
- } else {
- if (dir == SPI_MASTER_VEC_DIRECTION_WRITE) {
- /* Disable DRE and enable TXC to end WRITE */
- spi_hw->INTENCLR.reg = SERCOM_SPI_INTFLAG_DRE;
- spi_hw->INTENSET.reg = SERCOM_SPI_INTFLAG_TXC;
- } else {
- /* For BOTH, check if we still have bytes to read */
- dir = SPI_MASTER_VEC_DIRECTION_READ;
- module->direction = dir;
- goto check_for_read_end;
- }
- }
- }
- }
- }
- }
-
- /* For READ and BOTH, store the received byte */
- if (int_status & SERCOM_SPI_INTFLAG_RXC) {
- spi_master_vec_buflen_t rx_length;
- uint8_t *rx_head_ptr;
-
- rx_head_ptr = module->rx_head_ptr;
- if (rx_head_ptr != NULL) {
- *(rx_head_ptr++) = spi_hw->DATA.reg;
- } else {
- uint8_t dummy;
- dummy = spi_hw->DATA.reg;
- UNUSED(dummy);
- }
- module->tx_lead_on_rx--;
-
- /* Check if this was the last byte to receive */
- rx_length = module->rx_length - 1;
-
- if (rx_length) {
- module->rx_head_ptr = rx_head_ptr;
- module->rx_length = rx_length;
- } else {
- /* Any more buffers left to receive into? */
- rx_length = (++module->rx_bufdesc_ptr)->length;
-
- if (rx_length) {
- module->rx_head_ptr = module->rx_bufdesc_ptr->data;
- module->rx_length = rx_length;
- } else {
- /* Disable the SPI receiver (instant effect) and RX interrupt */
- spi_hw->CTRLB.reg = 0;
- spi_hw->INTENCLR.reg = SERCOM_SPI_INTFLAG_RXC;
-
- if (dir == SPI_MASTER_VEC_DIRECTION_READ) {
- /* If doing READ, end the transaction here */
- dir = SPI_MASTER_VEC_DIRECTION_IDLE;
- module->direction = dir;
- module->status = STATUS_OK;
-#ifdef CONF_SPI_MASTER_VEC_OS_SUPPORT
- CONF_SPI_MASTER_VEC_GIVE_SEMAPHORE_FROM_ISR(module->busy_semaphore);
-#endif
- } else {
- /* If doing BOTH, change direction to WRITE */
- dir = SPI_MASTER_VEC_DIRECTION_WRITE;
- module->direction = dir;
- }
- }
- }
- }
-
- /* For WRITE */
- if (int_status & SERCOM_SPI_INTFLAG_TXC) {
- /* End transaction here, since last byte has been sent */
- spi_hw->INTENCLR.reg = SERCOM_SPI_INTFLAG_TXC;
-
- dir = SPI_MASTER_VEC_DIRECTION_IDLE;
- module->direction = dir;
- module->status = STATUS_OK;
-#ifdef CONF_SPI_MASTER_VEC_OS_SUPPORT
- CONF_SPI_MASTER_VEC_GIVE_SEMAPHORE_FROM_ISR(module->busy_semaphore);
-#endif
- }
-}
-
-/**
- * @}
- */
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/a280628a/hw/mcu/atmel/samd21xx/src/sam0/drivers/sercom/spi_master_vec/spi_master_vec.h
----------------------------------------------------------------------
diff --git a/hw/mcu/atmel/samd21xx/src/sam0/drivers/sercom/spi_master_vec/spi_master_vec.h b/hw/mcu/atmel/samd21xx/src/sam0/drivers/sercom/spi_master_vec/spi_master_vec.h
deleted file mode 100755
index a10ae22..0000000
--- a/hw/mcu/atmel/samd21xx/src/sam0/drivers/sercom/spi_master_vec/spi_master_vec.h
+++ /dev/null
@@ -1,692 +0,0 @@
-/**
- * \file
- *
- * \brief SERCOM SPI master with vectored I/O driver include
- *
- * Copyright (C) 2013-2015 Atmel Corporation. All rights reserved.
- *
- * \asf_license_start
- *
- * \page License
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * 3. The name of Atmel may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * 4. This software may only be redistributed and used in connection with an
- * Atmel microcontroller product.
- *
- * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
- * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- * \asf_license_stop
- *
- */
-/*
- * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
- */
-
-#ifndef SPI_MASTER_VEC_H
-#define SPI_MASTER_VEC_H
-
-#include <compiler.h>
-#include <gclk.h>
-#include <port.h>
-#include <spi.h>
-#include <status_codes.h>
-#include <conf_spi_master_vec.h>
-
-/**
- * \defgroup asfdoc_sam0_sercom_spi_master_vec_group SAM Serial Peripheral Interface Master Driver w/ Vectored I/O (SERCOM SPI)
- *
- * This driver for Atmel® | SMART SAM devices provides an interface for the configuration
- * and operation of the SERCOM module in SPI master mode and uses vectored I/O
- * for data transfers.
- *
- * The following peripherals are used by this driver:
- * - SERCOM (Serial Communication Interface)
- *
- * The following devices can use this driver:
- * - Atmel | SMART SAM D20/D21
- * - Atmel | SMART SAM R21
- * - Atmel | SMART SAM D09/D10/D11
- * - Atmel | SMART SAM L21/L22
- * - Atmel | SMART SAM DA1
- * - Atmel | SMART SAM C20/C21
- *
- * The reader is assumed to be familiar with the regular SERCOM SPI driver, and
- * how it is configured and operated. Configuration of this driver is done a
- * similar way and actually re-uses several enumerations (configuration values)
- * from the regular SERCOM SPI driver.
- *
- * The outline of this documentation is as follows:
- * - \ref asfdoc_sam0_sercom_spi_master_vec_prerequisites
- * - \ref asfdoc_sam0_sercom_spi_master_vec_module_overview
- * - \ref asfdoc_sam0_sercom_spi_master_vec_special_considerations
- * - \ref asfdoc_sam0_sercom_spi_master_vec_extra_info
- * - \ref asfdoc_sam0_sercom_spi_master_vec_examples
- * - \ref asfdoc_sam0_sercom_spi_master_vec_api_overview
- *
- *
- * \section asfdoc_sam0_sercom_spi_master_vec_prerequisites Prerequisites
- *
- * This driver uses the \ref asfdoc_sam0_system_clock_group "SYSTEM clock driver"
- * to select the SERCOM's clock source and to configure the SERCOM for the
- * desired baud rate. Ensure that the selected clock source is configured and
- * that the clock system is initialized. This is typically done indirectly with
- * \ref system_init(), or directly with \ref system_clock_init().
- *
- * According to the datasheet, the minimum and maximum limits for the baud rate
- * is given by: \f$ \frac{1}{2^{17}} \times f_{clk} \le f_{baud}
- * \le \frac{1}{2} \times f_{clk} \f$.
- *
- *
- * \section asfdoc_sam0_sercom_spi_master_vec_module_overview Module Overview
- *
- * This SERCOM SPI master driver supports uni- and bidirectional transfers of
- * 8-bit data with vectored I/O, also know as scatter/gather.
- * It does not implement control of SS or slave addressing since the intended
- * usage is in stacks which usually have their own protocols and handshaking
- * schemes.
- *
- *
- * \subsection asfdoc_sam0_sercom_spi_master_vectored_io Vectored I/O
- *
- * Vectored I/O enables the transfer of data from/to any number of buffers with
- * arbitrary memory locations without having to do several transfers, i.e., one
- * buffer at a time. This feature is useful in stacks because it allows each
- * layer of the stack to have a dedicated data buffer, thus avoiding the need
- * for a centralized data buffer that the different layers must use in
- * cooperation.
- *
- * The vectored I/O relies on arrays of buffer descriptors which must be passed
- * to the driver to start a transfer. These buffer descriptors specify where in
- * memory each buffer is, and how large they are.
- * \ref asfdoc_sam0_vectored_io_example "The figure below" illustrates this
- * for an example with three buffers of varying sizes that are transmitted.
- *
- * \anchor asfdoc_sam0_vectored_io_example
- * \dot
-digraph bufptr_to_spiord {
- rankdir=LR;
- subgraph cluster_bufptr {
- style=invis;
- bufptr_label [shape=none, label="Buffer descriptors"];
- bufptrs [shape=record, label="<bf1> [0]|<bf2> [1]|<bf3> [2]|<bf4> [3]"];
- }
- subgraph cluster_buf {
- style=invis;
- buf_label [shape=none, label="Memory layout"];
- bufs [shape=record, label="...|<b1>"yy"|...|<b3>"z"|<b2>"xxx"|..."];
- }
- subgraph cluster_spiord {
- style=invis;
- spiord_label [shape=none, label="SPI transmission"];
- spiord [shape=record, label="<s1>"yy"|<s2>"xxx"|<s3>"z""];
- }
- bufptrs:bf1 -> bufs:b1 -> spiord:s1;
- bufptrs:bf2 -> bufs:b2 -> spiord:s2;
- bufptrs:bf3 -> bufs:b3 -> spiord:s3;
- bufptrs:bf4 -> "none";
-}
- * \enddot
- *
- * Note that the last descriptor \e must indicate no next buffer in order for
- * the driver to detect that the end of the buffer list has been reached. This
- * means that for \c N buffers, \c N+1 buffer descriptors are needed.
- *
- * Bidirectional transfers are supported without any restrictions on the buffer
- * descriptors, so the number of bytes and buffers to receive and transmit do
- * \e not have to be the same.
- *
- * \sa spi_master_vec_transceive_buffer_job() for details on starting transfers.
- *
- *
- * \subsection asfdoc_sam0_sercom_spi_master_os_support OS support
- *
- * Since this driver is interrupt-driven, it is possible for the MCU to run
- * other code while a transfer is on-going.
- *
- * In a single-threaded application, this can be achieved by starting a transfer
- * and then avoid any waiting for completion until absolutely required, e.g.,
- * when a new transfer is needed.
- *
- * But in a multi-threaded application, for example based on FreeRTOS, one can
- * utilize \e semaphores to let the OS know when a function is waiting and thus
- * blocking the thread, and that other threads can be run instead. Put another
- * way, the waiting can be made efficient.
- *
- * This driver has an internal semaphore which is used to signal to the OS
- * whenever a function is waiting for a transfer to complete. And since the
- * semaphore datatypes and functions are OS-specific, the support has been made
- * configurable by the use of macros. Note that support for FreeRTOS is already
- * implemented, but must be enabled.
- *
- * \sa CONF_SPI_MASTER_VEC_OS_SUPPORT for more on the configurable OS support.
- *
- *
- * \section asfdoc_sam0_sercom_spi_master_vec_special_considerations Special Considerations
- *
- * \subsection asfdoc_sam0_sercom_spi_master_vec_special_isr Interrupt safety
- *
- * This driver should not be used within interrupt contexts. The reason for this
- * is that the driver itself is interrupt driven. Further, the configurable OS
- * support is implemented with the assumption that transfers are only started
- * in threads, not in interrupt service routines, because it gives the simplest
- * API.
- *
- *
- * \subsection asfdoc_sam0_sercom_spi_master_vec_special_mux Signal MUX
- *
- * The SERCOM module has two layers of signal multiplexing in SPI mode:
- * -# SERCOM pad MUX: This routes the SPI signals to internal lines.
- * -# PORT pin MUX: This routes the internal line to a device pin.
- *
- * Both of these layers are configured in the \ref spi_master_vec_config
- * "configuration structure", using the members named \c mux_setting and
- * \c pinmux_padN. These must be set in combination.
- *
- * The driver supplies values for the
- * \ref spi_master_vec_config::mux_setting "SERCOM pad MUX" from the standard
- * ASF SERCOM SPI driver. For the PORT pin MUX configuration, refer to the
- * peripheral include file for the device (\c pio_samd20XNN.h ) and use the
- * macros that are prefixed with \c PINMUX_, such as
- * \c PINMUX_PA04D_SERCOM0_PAD0. It is also possible to use the default pin MUX
- * setting for a SERCOM pad by using the \ref PINMUX_DEFAULT macro. The defaults
- * are defined in the file \ref sercom_pinout.h.
- *
- * Note that for \ref spi_master_vec_init() to function properly with the macro
- * \ref PINMUX_DEFAULT, the order of the values in \c pinmux_padN \e must be
- * correct, i.e., \c pinmux_pad0 must contain the pin MUX setting for
- * multiplexing SERCOM pad 0, and so on.
- *
- *
- * \section asfdoc_sam0_sercom_spi_master_vec_extra_info Extra Information
- *
- * For extra information, see
- * \subpage asfdoc_sam0_sercom_spi_master_vec_extra. This includes:
- * - \ref asfdoc_sam0_sercom_spi_master_vec_extra_acronyms
- * - \ref asfdoc_sam0_sercom_spi_master_vec_extra_dependencies
- * - \ref asfdoc_sam0_sercom_spi_master_vec_extra_errata
- * - \ref asfdoc_sam0_sercom_spi_master_vec_extra_history
- *
- *
- * \section asfdoc_sam0_sercom_spi_master_vec_examples Examples
- *
- * For a list of examples related to this driver, see
- * \ref asfdoc_sam0_sercom_spi_master_vec_exqsg.
- *
- *
- * \section asfdoc_sam0_sercom_spi_master_vec_api_overview API Overview
- *
- * @{
- */
-
-/**
- * Driver configuration structure
- *
- * \sa asfdoc_sam0_sercom_spi_master_vec_special_considerations for more
- * information regarding SERCOM pad and pin MUX.
- */
-struct spi_master_vec_config {
- /** Baud rate in Hertz. */
- uint32_t baudrate;
- /** GCLK generator to use for the SERCOM. */
- enum gclk_generator gclk_generator;
- /** Enabled in sleep modes. */
- bool run_in_standby;
- /** SERCOM pad MUX setting. */
- enum spi_signal_mux_setting mux_setting;
- /** Transfer mode. */
- enum spi_transfer_mode transfer_mode;
- /** Data order. */
- enum spi_data_order data_order;
- /** Pin MUX setting for SERCOM pad 0. */
- uint32_t pinmux_pad0;
- /** Pin MUX setting for SERCOM pad 1. */
- uint32_t pinmux_pad1;
- /** Pin MUX setting for SERCOM pad 2. */
- uint32_t pinmux_pad2;
- /** Pin MUX setting for SERCOM pad 4. */
- uint32_t pinmux_pad3;
-};
-
-/** Buffer length container. */
-typedef uint16_t spi_master_vec_buflen_t;
-
-/** Buffer descriptor structure. */
-struct spi_master_vec_bufdesc {
- /** Pointer to buffer start. */
- void *data;
- /** Length of buffer. */
- spi_master_vec_buflen_t length;
-};
-
-/** Transfer direction */
-enum _spi_master_vec_direction {
- SPI_MASTER_VEC_DIRECTION_READ,
- SPI_MASTER_VEC_DIRECTION_WRITE,
- SPI_MASTER_VEC_DIRECTION_BOTH,
- SPI_MASTER_VEC_DIRECTION_IDLE,
-};
-
-/** Driver instance. */
-struct spi_master_vec_module {
-#if !defined(__DOXYGEN__)
- Sercom *volatile sercom;
- volatile bool locked;
- volatile enum _spi_master_vec_direction direction;
- volatile enum status_code status;
- volatile spi_master_vec_buflen_t rx_length;
- volatile spi_master_vec_buflen_t tx_length;
- uint8_t *volatile rx_head_ptr;
- uint8_t *volatile tx_head_ptr;
- volatile uint_fast8_t tx_lead_on_rx;
- struct spi_master_vec_bufdesc *volatile rx_bufdesc_ptr;
- struct spi_master_vec_bufdesc *volatile tx_bufdesc_ptr;
-# ifdef CONF_SPI_MASTER_VEC_OS_SUPPORT
- CONF_SPI_MASTER_VEC_SEMAPHORE_TYPE busy_semaphore;
-# endif
-#endif
-};
-
-/**
- * \name Configuration and Initialization
- * @{
- */
-
-/**
- * \brief Initialize configuration with default values.
- *
- * \param[out] config Configuration struct to initialize.
- */
-static inline void spi_master_vec_get_config_defaults(
- struct spi_master_vec_config *const config)
-{
- config->baudrate = 100000;
- config->gclk_generator = GCLK_GENERATOR_0;
- config->run_in_standby = false;
- config->mux_setting = SPI_SIGNAL_MUX_SETTING_D;
- config->transfer_mode = SPI_TRANSFER_MODE_0;
- config->data_order = SPI_DATA_ORDER_MSB;
- config->pinmux_pad0 = PINMUX_DEFAULT;
- config->pinmux_pad1 = PINMUX_DEFAULT;
- config->pinmux_pad2 = PINMUX_DEFAULT;
- config->pinmux_pad3 = PINMUX_DEFAULT;
-}
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-enum status_code spi_master_vec_init(struct spi_master_vec_module *const module,
- Sercom *const sercom, const struct spi_master_vec_config *const config);
-
-/** @} */
-
-/**
- * \name Enable/Disable and Reset
- * @{
- */
-
-void spi_master_vec_enable(const struct spi_master_vec_module *const module);
-void spi_master_vec_disable(struct spi_master_vec_module *const module);
-void spi_master_vec_reset(struct spi_master_vec_module *const module);
-
-/** @} */
-
-/**
- * \name Lock/Unlock
- * @{
- */
-
-/**
- * \brief Attempt to get lock on driver instance
- *
- * This function checks the instance's lock, which indicates whether or not it
- * is currently in use, and sets the lock if it was not already set.
- *
- * The purpose of this is to enable exclusive access to driver instances, so
- * that, e.g., transactions by different services will not interfere with each
- * other.
- *
- * \param[in,out] module Pointer to the driver instance to lock.
- *
- * \retval STATUS_OK if the module was locked.
- * \retval STATUS_BUSY if the module was already locked.
- */
-static inline enum status_code spi_master_vec_lock(
- struct spi_master_vec_module *const module)
-{
- enum status_code status;
-
- system_interrupt_enter_critical_section();
-
- if (module->locked) {
- status = STATUS_BUSY;
- } else {
- module->locked = true;
- status = STATUS_OK;
- }
-
- system_interrupt_leave_critical_section();
-
- return status;
-}
-
-/**
- * \brief Unlock driver instance
- *
- * This function clears the instance lock, indicating that it is available for
- * use.
- *
- * \param[in,out] module Pointer to the driver instance to lock.
- */
-static inline void spi_master_vec_unlock(
- struct spi_master_vec_module *const module)
-{
- module->locked = false;
-}
-
-/** @} */
-
-/**
- * \name Read/Write and Status
- * @{
- */
-
-enum status_code spi_master_vec_transceive_buffer_job(
- struct spi_master_vec_module *const module,
- struct spi_master_vec_bufdesc tx_bufdescs[],
- struct spi_master_vec_bufdesc rx_bufdescs[]);
-
-/**
- * \brief Get current status of transfer.
- *
- * \param[in] module Driver instance to operate on.
- *
- * \return Current status of driver instance.
- * \retval STATUS_OK if idle and previous transfer succeeded.
- * \retval STATUS_BUSY if a transfer is ongoing.
- * \retval <other> if previous transfer failed.
- */
-static inline enum status_code spi_master_vec_get_job_status(
- const struct spi_master_vec_module *const module)
-{
- return module->status;
-}
-
-/**
- * \brief Get status of transfer upon job end.
- *
- * \param[in] module Driver instance to operate on.
- *
- * \return Current status of driver instance.
- * \retval STATUS_OK if idle and previous transfer succeeded.
- * \retval <other> if previous transfer failed.
- */
-static inline enum status_code spi_master_vec_get_job_status_wait(
- const struct spi_master_vec_module *const module)
-{
- enum status_code status;
-
-#ifdef CONF_SPI_MASTER_VEC_OS_SUPPORT
- CONF_SPI_MASTER_VEC_TAKE_SEMAPHORE(module->busy_semaphore);
- status = spi_master_vec_get_job_status(module);
- CONF_SPI_MASTER_VEC_GIVE_SEMAPHORE(module->busy_semaphore);
-#else
- do {
- status = spi_master_vec_get_job_status(module);
- } while (status == STATUS_BUSY);
-#endif
-
- return status;
-}
-
-
-/**
- * \brief Start vectored I/O transfer, wait for it to end.
- *
- * \param[in,out] module Driver instance to operate on.
- * \param[in] tx_bufdescs address of buffer descriptor array for bytes to
- * transmit.
- * \arg \c NULL if the transfer is a simplex read.
- * \param[in,out] rx_bufdescs address of buffer descriptor array for storing
- * received bytes.
- * \arg \c NULL if the transfer is a simplex write.
- *
- * \return Status of transfer start.
- * \retval STATUS_OK if transfer succeeded.
- * \retval STATUS_BUSY if a transfer was already on-going.
- * \retval <other> if transfer failed.
- */
-static inline enum status_code spi_master_vec_transceive_buffer_wait(
- struct spi_master_vec_module *const module,
- struct spi_master_vec_bufdesc tx_bufdescs[],
- struct spi_master_vec_bufdesc rx_bufdescs[])
-{
- enum status_code status;
-
- status = spi_master_vec_transceive_buffer_job(module, tx_bufdescs,
- rx_bufdescs);
-
- if (status == STATUS_BUSY) {
- return status;
- }
-
- return spi_master_vec_get_job_status_wait(module);
-}
-
-/** @} */
-
-#ifdef __cplusplus
-}
-#endif
-
-/**
- * \name OS Support Configuration
- * @{
- */
-
-/**
- * \def CONF_SPI_MASTER_VEC_OS_SUPPORT
- * \brief Enable support for OS
- *
- * Defining this symbol will enable support for an OS, e.g., FreeRTOS, by using
- * the macros in this group:
- * - \ref CONF_SPI_MASTER_VEC_SEMAPHORE_TYPE
- * - \ref CONF_SPI_MASTER_VEC_CREATE_SEMAPHORE
- * - \ref CONF_SPI_MASTER_VEC_DELETE_SEMAPHORE
- * - \ref CONF_SPI_MASTER_VEC_TAKE_SEMAPHORE
- * - \ref CONF_SPI_MASTER_VEC_GIVE_SEMAPHORE
- * - \ref CONF_SPI_MASTER_VEC_GIVE_SEMAPHORE_FROM_ISR
- *
- * The user must ensure that these macros map to the implementation for the OS
- * that is used. Further, required includes must be added alongside these macros
- * in \ref conf_spi_master_vec.h.
- *
- * The purpose of this configuration is to enable usage of the OS' semaphore
- * system to wait for transfers to end rather than continuously polling the
- * transfer status, which is an inefficient approach.
- */
-
-/**
- * \def CONF_SPI_MASTER_VEC_SEMAPHORE_TYPE
- * \brief Semaphore datatype
- */
-
-/**
- * \def CONF_SPI_MASTER_VEC_CREATE_SEMAPHORE
- * \brief Create/initialize semaphore
- *
- * \param semaphore Semaphore member in driver instance.
- */
-
-/**
- * \def CONF_SPI_MASTER_VEC_DELETE_SEMAPHORE
- * \brief Delete semaphore
- *
- * \param semaphore Semaphore member in driver instance.
- */
-
-/**
- * \def CONF_SPI_MASTER_VEC_TAKE_SEMAPHORE
- * \brief Wait for and take semaphore
- *
- * \param semaphore Semaphore member in driver instance.
- */
-
-/**
- * \def CONF_SPI_MASTER_VEC_GIVE_SEMAPHORE
- * \brief Give semaphore back
- *
- * \param semaphore Semaphore member in driver instance.
- */
-
-/**
- * \def CONF_SPI_MASTER_VEC_GIVE_SEMAPHORE_FROM_ISR
- * \brief Give semaphore back from an ISR
- *
- * \param semaphore Semaphore member in driver instance.
- */
-
-/** @} */
-
-/**
- * @}
- */
-
-/**
- * \page asfdoc_sam0_sercom_spi_master_vec_extra Extra Information for SERCOM SPI Master Driver w/ Vectored I/O
- *
- *
- * \section asfdoc_sam0_sercom_spi_master_vec_extra_acronyms Acronyms
- *
- * The table below presents the acronyms used in this module.
- *
- * <table>
- * <tr>
- * <th>Acronym</td>
- * <th>Description</td>
- * </tr>
- * <tr>
- * <td>GCLK</td>
- * <td>Generic Clock</td>
- * </tr>
- * <tr>
- * <td>MISO</td>
- * <td>Master Input, Slave Output</td>
- * </tr>
- * <tr>
- * <td>MOSI</td>
- * <td>Master Output, Slave Input</td>
- * </tr>
- * <tr>
- * <td>SCK</td>
- * <td>Serial Clock</td>
- * </tr>
- * <tr>
- * <td>SPI</td>
- * <td>Serial Peripheral Interface</td>
- * </tr>
- * <tr>
- * <td>SS</td>
- * <td>Slave Select</td>
- * </tr>
- * </table>
- *
- *
- * \section asfdoc_sam0_sercom_spi_master_vec_extra_dependencies Dependencies
- *
- * This driver has the following dependencies:
- * - \ref asfdoc_sam0_system_group "System driver"
- * - \ref group_sam0_utils "Compiler driver"
- * - \ref asfdoc_sam0_port_group "Port driver"
- * - \ref Common SERCOM driver base
- *
- *
- * \section asfdoc_sam0_sercom_spi_master_vec_extra_errata Errata
- *
- * There are no errata related to this driver.
- *
- *
- * \section asfdoc_sam0_sercom_spi_master_vec_extra_history Module History
- *
- * An overview of the module history is presented in the table below, with
- * details on the enhancements and fixes made to the module since its first
- * release. The current version of this corresponds to the newest version in the
- * table.
- *
- * <table>
- * <tr>
- * <th>Changelog</th>
- * </tr>
- * <tr>
- * <td>Initial Release</td>
- * </tr>
- * </table>
- */
-
-/**
- * \page asfdoc_sam0_sercom_spi_master_vec_exqsg Examples for SERCOM SPI Master Driver w/ Vectored I/O
- *
- * This is a list of the available Quick Start guides (QSGs) and example
- * applications for \ref asfdoc_sam0_sercom_spi_master_vec_group. QSGs are
- * simple examples with step-by-step instructions to configure and use this
- * driver in a selection of use cases. Note that QSGs can be compiled as a
- * standalone application or be added to the user application.
- *
- * - \subpage asfdoc_sam0_sercom_spi_master_vec_basic
- */
-
- /**
- * \page asfdoc_sam0_sercom_spi_master_vec_document_revision_history Document Revision History
- *
- * <table>
- * <tr>
- * <th>Doc. Rev.</td>
- * <th>Date</td>
- * <th>Comments</td>
- * </tr>
- * <tr>
- * <td>D</td>
- * <td>12/2014</td>
- * <td>Add SAM L21/C21 support.</td>
- * </tr>
- * <tr>
- * <td>C</td>
- * <td>04/2014</td>
- * <td>Add SAM D10/D11 support.</td>
- * </tr>
- * <tr>
- * <td>B</td>
- * <td>03/2014</td>
- * <td>Add SAMR21 support.</td>
- * </tr>
- * <tr>
- * <td>A</td>
- * <td>01/2014</td>
- * <td>Initial release</td>
- * </tr>
- * </table>
- */
-
-#endif /* SPI_MASTER_VEC_H */
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/a280628a/hw/mcu/atmel/samd21xx/src/sam0/drivers/sercom/usart/usart.c
----------------------------------------------------------------------
diff --git a/hw/mcu/atmel/samd21xx/src/sam0/drivers/sercom/usart/usart.c b/hw/mcu/atmel/samd21xx/src/sam0/drivers/sercom/usart/usart.c
deleted file mode 100755
index 5772ae0..0000000
--- a/hw/mcu/atmel/samd21xx/src/sam0/drivers/sercom/usart/usart.c
+++ /dev/null
@@ -1,811 +0,0 @@
-/**
- * \file
- *
- * \brief SAM SERCOM USART Driver
- *
- * Copyright (C) 2012-2015 Atmel Corporation. All rights reserved.
- *
- * \asf_license_start
- *
- * \page License
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * 3. The name of Atmel may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * 4. This software may only be redistributed and used in connection with an
- * Atmel microcontroller product.
- *
- * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
- * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- * \asf_license_stop
- *
- */
-/*
- * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
- */
-#include "usart.h"
-#include <pinmux.h>
-#if USART_CALLBACK_MODE == true
-# include "usart_interrupt.h"
-#endif
-
-/**
- * \internal
- * Set Configuration of the USART module
- */
-static enum status_code _usart_set_config(
- struct usart_module *const module,
- const struct usart_config *const config)
-{
- /* Sanity check arguments */
- Assert(module);
- Assert(module->hw);
-
- /* Get a pointer to the hardware module instance */
- SercomUsart *const usart_hw = &(module->hw->USART);
-
- /* Index for generic clock */
- uint32_t sercom_index = _sercom_get_sercom_inst_index(module->hw);
- uint32_t gclk_index = sercom_index + SERCOM0_GCLK_ID_CORE;
-
- /* Cache new register values to minimize the number of register writes */
- uint32_t ctrla = 0;
- uint32_t ctrlb = 0;
-#ifdef FEATURE_USART_ISO7816
- uint32_t ctrlc = 0;
-#endif
- uint16_t baud = 0;
- uint32_t transfer_mode;
-
- enum sercom_asynchronous_operation_mode mode = SERCOM_ASYNC_OPERATION_MODE_ARITHMETIC;
- enum sercom_asynchronous_sample_num sample_num = SERCOM_ASYNC_SAMPLE_NUM_16;
-
-#ifdef FEATURE_USART_OVER_SAMPLE
- switch (config->sample_rate) {
- case USART_SAMPLE_RATE_16X_ARITHMETIC:
- mode = SERCOM_ASYNC_OPERATION_MODE_ARITHMETIC;
- sample_num = SERCOM_ASYNC_SAMPLE_NUM_16;
- break;
- case USART_SAMPLE_RATE_8X_ARITHMETIC:
- mode = SERCOM_ASYNC_OPERATION_MODE_ARITHMETIC;
- sample_num = SERCOM_ASYNC_SAMPLE_NUM_8;
- break;
- case USART_SAMPLE_RATE_3X_ARITHMETIC:
- mode = SERCOM_ASYNC_OPERATION_MODE_ARITHMETIC;
- sample_num = SERCOM_ASYNC_SAMPLE_NUM_3;
- break;
- case USART_SAMPLE_RATE_16X_FRACTIONAL:
- mode = SERCOM_ASYNC_OPERATION_MODE_FRACTIONAL;
- sample_num = SERCOM_ASYNC_SAMPLE_NUM_16;
- break;
- case USART_SAMPLE_RATE_8X_FRACTIONAL:
- mode = SERCOM_ASYNC_OPERATION_MODE_FRACTIONAL;
- sample_num = SERCOM_ASYNC_SAMPLE_NUM_8;
- break;
- }
-#endif
-
- /* Set data order, internal muxing, and clock polarity */
- ctrla = (uint32_t)config->data_order |
- (uint32_t)config->mux_setting |
- #ifdef FEATURE_USART_OVER_SAMPLE
- config->sample_adjustment |
- config->sample_rate |
- #endif
- #ifdef FEATURE_USART_IMMEDIATE_BUFFER_OVERFLOW_NOTIFICATION
- (config->immediate_buffer_overflow_notification << SERCOM_USART_CTRLA_IBON_Pos) |
- #endif
- (config->clock_polarity_inverted << SERCOM_USART_CTRLA_CPOL_Pos);
-
- enum status_code status_code = STATUS_OK;
-
- transfer_mode = (uint32_t)config->transfer_mode;
-#ifdef FEATURE_USART_ISO7816
- if(config->iso7816_config.enabled) {
- transfer_mode = config->iso7816_config.protocol_t;
- }
-#endif
- /* Get baud value from mode and clock */
-#ifdef FEATURE_USART_ISO7816
- if(config->iso7816_config.enabled) {
- baud = config->baudrate;
- } else {
-#endif
- switch (transfer_mode)
- {
- case USART_TRANSFER_SYNCHRONOUSLY:
- if (!config->use_external_clock) {
- status_code = _sercom_get_sync_baud_val(config->baudrate,
- system_gclk_chan_get_hz(gclk_index), &baud);
- }
-
- break;
-
- case USART_TRANSFER_ASYNCHRONOUSLY:
- if (config->use_external_clock) {
- status_code =
- _sercom_get_async_baud_val(config->baudrate,
- config->ext_clock_freq, &baud, mode, sample_num);
- } else {
- status_code =
- _sercom_get_async_baud_val(config->baudrate,
- system_gclk_chan_get_hz(gclk_index), &baud, mode, sample_num);
- }
-
- break;
- }
-
- /* Check if calculating the baudrate failed */
- if (status_code != STATUS_OK) {
- /* Abort */
- return status_code;
- }
-#ifdef FEATURE_USART_ISO7816
- }
-#endif
-
-#ifdef FEATURE_USART_IRDA
- if(config->encoding_format_enable) {
- usart_hw->RXPL.reg = config->receive_pulse_length;
- }
-#endif
-
- /* Wait until synchronization is complete */
- _usart_wait_for_sync(module);
-
- /*Set baud val */
- usart_hw->BAUD.reg = baud;
-
- /* Set sample mode */
- ctrla |= transfer_mode;
-
- if (config->use_external_clock == false) {
- ctrla |= SERCOM_USART_CTRLA_MODE(0x1);
- }
- else {
- ctrla |= SERCOM_USART_CTRLA_MODE(0x0);
- }
-
- /* Set stopbits and enable transceivers */
- ctrlb =
- #ifdef FEATURE_USART_IRDA
- (config->encoding_format_enable << SERCOM_USART_CTRLB_ENC_Pos) |
- #endif
- #ifdef FEATURE_USART_START_FRAME_DECTION
- (config->start_frame_detection_enable << SERCOM_USART_CTRLB_SFDE_Pos) |
- #endif
- #ifdef FEATURE_USART_COLLISION_DECTION
- (config->collision_detection_enable << SERCOM_USART_CTRLB_COLDEN_Pos) |
- #endif
- (config->receiver_enable << SERCOM_USART_CTRLB_RXEN_Pos) |
- (config->transmitter_enable << SERCOM_USART_CTRLB_TXEN_Pos);
-
-#ifdef FEATURE_USART_ISO7816
- if(config->iso7816_config.enabled) {
- ctrla |= SERCOM_USART_CTRLA_FORM(0x07);
- if (config->iso7816_config.enable_inverse) {
- ctrla |= SERCOM_USART_CTRLA_TXINV | SERCOM_USART_CTRLA_RXINV;
- }
- ctrlb |= USART_CHARACTER_SIZE_8BIT;
-
- switch(config->iso7816_config.protocol_t) {
- case ISO7816_PROTOCOL_T_0:
- ctrlb |= (uint32_t)config->stopbits;
- ctrlc |= SERCOM_USART_CTRLC_GTIME(config->iso7816_config.guard_time) | \
- (config->iso7816_config.inhibit_nack) | \
- (config->iso7816_config.successive_recv_nack) | \
- SERCOM_USART_CTRLC_MAXITER(config->iso7816_config.max_iterations);
- break;
- case ISO7816_PROTOCOL_T_1:
- ctrlb |= USART_STOPBITS_1;
- break;
- }
- } else {
-#endif
- ctrlb |= (uint32_t)config->character_size;
- /* Check parity mode bits */
- if (config->parity != USART_PARITY_NONE) {
- ctrla |= SERCOM_USART_CTRLA_FORM(1);
- ctrlb |= config->parity;
- } else {
-#ifdef FEATURE_USART_LIN_SLAVE
- if(config->lin_slave_enable) {
- ctrla |= SERCOM_USART_CTRLA_FORM(0x4);
- } else {
- ctrla |= SERCOM_USART_CTRLA_FORM(0);
- }
-#else
- ctrla |= SERCOM_USART_CTRLA_FORM(0);
-#endif
- }
-#ifdef FEATURE_USART_ISO7816
- }
-#endif
-
-#ifdef FEATURE_USART_LIN_MASTER
- usart_hw->CTRLC.reg = ((usart_hw->CTRLC.reg) & SERCOM_USART_CTRLC_GTIME_Msk)
- | config->lin_header_delay
- | config->lin_break_length;
-
- if (config->lin_node != LIN_INVALID_MODE) {
- ctrla &= ~(SERCOM_USART_CTRLA_FORM(0xf));
- ctrla |= config->lin_node;
- }
-#endif
-
- /* Set whether module should run in standby. */
- if (config->run_in_standby || system_is_debugger_present()) {
- ctrla |= SERCOM_USART_CTRLA_RUNSTDBY;
- }
-
- /* Wait until synchronization is complete */
- _usart_wait_for_sync(module);
-
- /* Write configuration to CTRLB */
- usart_hw->CTRLB.reg = ctrlb;
-
- /* Wait until synchronization is complete */
- _usart_wait_for_sync(module);
-
- /* Write configuration to CTRLA */
- usart_hw->CTRLA.reg = ctrla;
-
-#ifdef FEATURE_USART_RS485
- if ((usart_hw->CTRLA.reg & SERCOM_USART_CTRLA_FORM_Msk) != \
- SERCOM_USART_CTRLA_FORM(0x07)) {
- usart_hw->CTRLC.reg &= ~(SERCOM_USART_CTRLC_GTIME(0x7));
- usart_hw->CTRLC.reg |= SERCOM_USART_CTRLC_GTIME(config->rs485_guard_time);
- }
-#endif
-
-#ifdef FEATURE_USART_ISO7816
- if(config->iso7816_config.enabled) {
- _usart_wait_for_sync(module);
- usart_hw->CTRLC.reg = ctrlc;
- }
-#endif
-
- return STATUS_OK;
-}
-
-/**
- * \brief Initializes the device
- *
- * Initializes the USART device based on the setting specified in the
- * configuration struct.
- *
- * \param[out] module Pointer to USART device
- * \param[in] hw Pointer to USART hardware instance
- * \param[in] config Pointer to configuration struct
- *
- * \return Status of the initialization.
- *
- * \retval STATUS_OK The initialization was successful
- * \retval STATUS_BUSY The USART module is busy
- * resetting
- * \retval STATUS_ERR_DENIED The USART has not been disabled in
- * advance of initialization
- * \retval STATUS_ERR_INVALID_ARG The configuration struct contains
- * invalid configuration
- * \retval STATUS_ERR_ALREADY_INITIALIZED The SERCOM instance has already been
- * initialized with different clock
- * configuration
- * \retval STATUS_ERR_BAUD_UNAVAILABLE The BAUD rate given by the
- * configuration
- * struct cannot be reached with
- * the current clock configuration
- */
-enum status_code usart_init(
- struct usart_module *const module,
- Sercom *const hw,
- const struct usart_config *const config)
-{
- /* Sanity check arguments */
- Assert(module);
- Assert(hw);
- Assert(config);
-
- enum status_code status_code = STATUS_OK;
-
- /* Assign module pointer to software instance struct */
- module->hw = hw;
-
- /* Get a pointer to the hardware module instance */
- SercomUsart *const usart_hw = &(module->hw->USART);
-
- uint32_t sercom_index = _sercom_get_sercom_inst_index(module->hw);
- uint32_t pm_index, gclk_index;
-#if (SAML21) || (SAML22) || (SAMC20) || (SAMC21)
-#if (SAML21)
- if (sercom_index == 5) {
- pm_index = MCLK_APBDMASK_SERCOM5_Pos;
- gclk_index = SERCOM5_GCLK_ID_CORE;
- } else {
- pm_index = sercom_index + MCLK_APBCMASK_SERCOM0_Pos;
- gclk_index = sercom_index + SERCOM0_GCLK_ID_CORE;
- }
-#else
- pm_index = sercom_index + MCLK_APBCMASK_SERCOM0_Pos;
- gclk_index = sercom_index + SERCOM0_GCLK_ID_CORE;
-#endif
-#else
- pm_index = sercom_index + PM_APBCMASK_SERCOM0_Pos;
- gclk_index = sercom_index + SERCOM0_GCLK_ID_CORE;
-#endif
-
- if (usart_hw->CTRLA.reg & SERCOM_USART_CTRLA_SWRST) {
- /* The module is busy resetting itself */
- return STATUS_BUSY;
- }
-
- if (usart_hw->CTRLA.reg & SERCOM_USART_CTRLA_ENABLE) {
- /* Check the module is enabled */
- return STATUS_ERR_DENIED;
- }
-
- /* Turn on module in PM */
-#if (SAML21)
- if (sercom_index == 5) {
- system_apb_clock_set_mask(SYSTEM_CLOCK_APB_APBD, 1 << pm_index);
- } else {
- system_apb_clock_set_mask(SYSTEM_CLOCK_APB_APBC, 1 << pm_index);
- }
-#else
- system_apb_clock_set_mask(SYSTEM_CLOCK_APB_APBC, 1 << pm_index);
-#endif
-
- /* Set up the GCLK for the module */
- struct system_gclk_chan_config gclk_chan_conf;
- system_gclk_chan_get_config_defaults(&gclk_chan_conf);
- gclk_chan_conf.source_generator = config->generator_source;
- system_gclk_chan_set_config(gclk_index, &gclk_chan_conf);
- system_gclk_chan_enable(gclk_index);
- sercom_set_gclk_generator(config->generator_source, false);
-
- /* Set character size */
- module->character_size = config->character_size;
-
- /* Set transmitter and receiver status */
- module->receiver_enabled = config->receiver_enable;
- module->transmitter_enabled = config->transmitter_enable;
-
-#ifdef FEATURE_USART_LIN_SLAVE
- module->lin_slave_enabled = config->lin_slave_enable;
-#endif
-#ifdef FEATURE_USART_START_FRAME_DECTION
- module->start_frame_detection_enabled = config->start_frame_detection_enable;
-#endif
-#ifdef FEATURE_USART_ISO7816
- module->iso7816_mode_enabled = config->iso7816_config.enabled;
-#endif
- /* Set configuration according to the config struct */
- status_code = _usart_set_config(module, config);
- if(status_code != STATUS_OK) {
- return status_code;
- }
-
- struct system_pinmux_config pin_conf;
- system_pinmux_get_config_defaults(&pin_conf);
- pin_conf.direction = SYSTEM_PINMUX_PIN_DIR_INPUT;
- pin_conf.input_pull = SYSTEM_PINMUX_PIN_PULL_NONE;
-
- uint32_t pad_pinmuxes[] = {
- config->pinmux_pad0, config->pinmux_pad1,
- config->pinmux_pad2, config->pinmux_pad3
- };
-
- /* Configure the SERCOM pins according to the user configuration */
- for (uint8_t pad = 0; pad < 4; pad++) {
- uint32_t current_pinmux = pad_pinmuxes[pad];
-
- if (current_pinmux == PINMUX_DEFAULT) {
- current_pinmux = _sercom_get_default_pad(hw, pad);
- }
-
- if (current_pinmux != PINMUX_UNUSED) {
- pin_conf.mux_position = current_pinmux & 0xFFFF;
- system_pinmux_pin_set_config(current_pinmux >> 16, &pin_conf);
- }
- }
-
-#if USART_CALLBACK_MODE == true
- /* Initialize parameters */
- for (uint32_t i = 0; i < USART_CALLBACK_N; i++) {
- module->callback[i] = NULL;
- }
-
- module->tx_buffer_ptr = NULL;
- module->rx_buffer_ptr = NULL;
- module->remaining_tx_buffer_length = 0x0000;
- module->remaining_rx_buffer_length = 0x0000;
- module->callback_reg_mask = 0x00;
- module->callback_enable_mask = 0x00;
- module->rx_status = STATUS_OK;
- module->tx_status = STATUS_OK;
-
- /* Set interrupt handler and register USART software module struct in
- * look-up table */
- uint8_t instance_index = _sercom_get_sercom_inst_index(module->hw);
- _sercom_set_handler(instance_index, _usart_interrupt_handler);
- _sercom_instances[instance_index] = module;
-#endif
-
- return status_code;
-}
-
-/**
- * \brief Transmit a character via the USART
- *
- * This blocking function will transmit a single character via the
- * USART.
- *
- * \param[in] module Pointer to the software instance struct
- * \param[in] tx_data Data to transfer
- *
- * \return Status of the operation.
- * \retval STATUS_OK If the operation was completed
- * \retval STATUS_BUSY If the 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_wait(
- struct usart_module *const module,
- const uint16_t tx_data)
-{
- /* Sanity check arguments */
- Assert(module);
- Assert(module->hw);
-
- /* Get a pointer to the hardware module instance */
- SercomUsart *const usart_hw = &(module->hw->USART);
-
- /* Check that the transmitter is enabled */
- if (!(module->transmitter_enabled)) {
- return STATUS_ERR_DENIED;
- }
-
-#if USART_CALLBACK_MODE == true
- /* Check if the USART is busy doing asynchronous operation. */
- if (module->remaining_tx_buffer_length > 0) {
- return STATUS_BUSY;
- }
-
-#else
- /* Check if USART is ready for new data */
- if (!(usart_hw->INTFLAG.reg & SERCOM_USART_INTFLAG_DRE)) {
- /* Return error code */
- return STATUS_BUSY;
- }
-#endif
-
- /* Wait until synchronization is complete */
- _usart_wait_for_sync(module);
-
- /* Write data to USART module */
- usart_hw->DATA.reg = tx_data;
-
- while (!(usart_hw->INTFLAG.reg & SERCOM_USART_INTFLAG_TXC)) {
- /* Wait until data is sent */
- }
-
- return STATUS_OK;
-}
-
-/**
- * \brief Receive a character via the USART
- *
- * This blocking function will receive a character via the USART.
- *
- * \param[in] module Pointer to the software instance struct
- * \param[out] rx_data Pointer to received data
- *
- * \return Status of the operation.
- * \retval STATUS_OK If the operation was completed
- * \retval STATUS_BUSY If the operation was not completed,
- * due to the USART module being busy
- * \retval STATUS_ERR_BAD_FORMAT If the operation was not completed,
- * due to configuration mismatch between USART
- * and the sender
- * \retval STATUS_ERR_BAD_OVERFLOW If the operation was not completed,
- * due to the baudrate being too low or the
- * system frequency being too high
- * \retval STATUS_ERR_BAD_DATA If the operation was not completed, due to
- * data being corrupted
- * \retval STATUS_ERR_DENIED If the receiver is not enabled
- */
-enum status_code usart_read_wait(
- struct usart_module *const module,
- uint16_t *const rx_data)
-{
- /* Sanity check arguments */
- Assert(module);
- Assert(module->hw);
-
- /* Error variable */
- uint8_t error_code;
-
- /* Get a pointer to the hardware module instance */
- SercomUsart *const usart_hw = &(module->hw->USART);
-
- /* Check that the receiver is enabled */
- if (!(module->receiver_enabled)) {
- return STATUS_ERR_DENIED;
- }
-
-#if USART_CALLBACK_MODE == true
- /* Check if the USART is busy doing asynchronous operation. */
- if (module->remaining_rx_buffer_length > 0) {
- return STATUS_BUSY;
- }
-#endif
-
- /* Check if USART has new data */
- if (!(usart_hw->INTFLAG.reg & SERCOM_USART_INTFLAG_RXC)) {
- /* Return error code */
- return STATUS_BUSY;
- }
-
- /* Wait until synchronization is complete */
- _usart_wait_for_sync(module);
-
- /* Read out the status code and mask away all but the 3 LSBs*/
- error_code = (uint8_t)(usart_hw->STATUS.reg & SERCOM_USART_STATUS_MASK);
-
- /* Check if an error has occurred during the receiving */
- if (error_code) {
- /* Check which error occurred */
- if (error_code & SERCOM_USART_STATUS_FERR) {
- /* Clear flag by writing a 1 to it and
- * return with an error code */
- usart_hw->STATUS.reg = SERCOM_USART_STATUS_FERR;
-
- return STATUS_ERR_BAD_FORMAT;
- } else if (error_code & SERCOM_USART_STATUS_BUFOVF) {
- /* Clear flag by writing a 1 to it and
- * return with an error code */
- usart_hw->STATUS.reg = SERCOM_USART_STATUS_BUFOVF;
-
- return STATUS_ERR_OVERFLOW;
- } else if (error_code & SERCOM_USART_STATUS_PERR) {
- /* Clear flag by writing a 1 to it and
- * return with an error code */
- usart_hw->STATUS.reg = SERCOM_USART_STATUS_PERR;
-
- return STATUS_ERR_BAD_DATA;
- }
-#ifdef FEATURE_USART_LIN_SLAVE
- else if (error_code & SERCOM_USART_STATUS_ISF) {
- /* Clear flag by writing 1 to it and
- * return with an error code */
- usart_hw->STATUS.reg |= SERCOM_USART_STATUS_ISF;
-
- return STATUS_ERR_PROTOCOL;
- }
-#endif
-#ifdef FEATURE_USART_COLLISION_DECTION
- else if (error_code & SERCOM_USART_STATUS_COLL) {
- /* Clear flag by writing 1 to it
- * return with an error code */
- usart_hw->STATUS.reg |= SERCOM_USART_STATUS_COLL;
-
- return STATUS_ERR_PACKET_COLLISION;
- }
-#endif
- }
-
- /* Read data from USART module */
- *rx_data = usart_hw->DATA.reg;
-
- return STATUS_OK;
-}
-
-/**
- * \brief Transmit a buffer of characters via the USART
- *
- * This blocking function will transmit a block of \c length characters
- * via the USART.
- *
- * \note Using this function in combination with the interrupt (\c _job) functions is
- * not recommended as it has no functionality to check if there is an
- * ongoing interrupt driven operation running or not.
- *
- * \param[in] module Pointer to USART software instance struct
- * \param[in] tx_data Pointer to data to transmit
- * \param[in] length Number of characters 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_wait(&module, (uint8_t*)tx_buf, TX_LEN);
- \endcode
- *
- * \return Status of the operation.
- * \retval STATUS_OK If operation was completed
- * \retval STATUS_ERR_INVALID_ARG If operation was not completed, due to invalid
- * arguments
- * \retval STATUS_ERR_TIMEOUT If operation was not completed, due to USART
- * module timing out
- * \retval STATUS_ERR_DENIED If the transmitter is not enabled
- */
-enum status_code usart_write_buffer_wait(
- struct usart_module *const module,
- const uint8_t *tx_data,
- uint16_t length)
-{
- /* Sanity check arguments */
- Assert(module);
- Assert(module->hw);
-
- /* Check if the buffer length is valid */
- if (length == 0) {
- return STATUS_ERR_INVALID_ARG;
- }
-
- /* Check that the transmitter is enabled */
- if (!(module->transmitter_enabled)) {
- return STATUS_ERR_DENIED;
- }
-
- /* Get a pointer to the hardware module instance */
- SercomUsart *const usart_hw = &(module->hw->USART);
-
- /* Wait until synchronization is complete */
- _usart_wait_for_sync(module);
-
- uint16_t tx_pos = 0;
-
- /* Blocks while buffer is being transferred */
- while (length--) {
- /* Wait for the USART to be ready for new data and abort
- * operation if it doesn't get ready within the timeout*/
- for (uint32_t i = 0; i <= USART_TIMEOUT; i++) {
- if (usart_hw->INTFLAG.reg & SERCOM_USART_INTFLAG_DRE) {
- break;
- } else if (i == USART_TIMEOUT) {
- return STATUS_ERR_TIMEOUT;
- }
- }
-
- /* Data to send is at least 8 bits long */
- uint16_t data_to_send = tx_data[tx_pos++];
-
- /* Check if the character size exceeds 8 bit */
- if (module->character_size == USART_CHARACTER_SIZE_9BIT) {
- data_to_send |= (tx_data[tx_pos++] << 8);
- }
-
- /* Send the data through the USART module */
- usart_write_wait(module, data_to_send);
- }
-
- /* Wait until Transmit is complete or timeout */
- for (uint32_t i = 0; i <= USART_TIMEOUT; i++) {
- if (usart_hw->INTFLAG.reg & SERCOM_USART_INTFLAG_TXC) {
- break;
- } else if (i == USART_TIMEOUT) {
- return STATUS_ERR_TIMEOUT;
- }
- }
-
- return STATUS_OK;
-}
-
-/**
- * \brief Receive a buffer of \c length characters via the USART
- *
- * This blocking function will receive a block of \c length characters
- * via the USART.
- *
- * \note Using this function in combination with the interrupt (\c *_job)
- * functions is not recommended as it has no functionality to check if
- * there is an ongoing interrupt driven operation running or not.
- *
- * \param[in] module Pointer to USART software instance struct
- * \param[out] rx_data Pointer to receive buffer
- * \param[in] length Number of characters to receive
- *
- * \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_wait(&module, (uint8_t*)rx_buf, RX_LEN);
- \endcode
- *
- * \return Status of the operation.
- * \retval STATUS_OK If operation was completed
- * \retval STATUS_ERR_INVALID_ARG If operation was not completed, due to an
- * invalid argument being supplied
- * \retval STATUS_ERR_TIMEOUT If operation was not completed, due
- * to USART module timing out
- * \retval STATUS_ERR_BAD_FORMAT If the operation was not completed,
- * due to a configuration mismatch
- * between USART and the sender
- * \retval STATUS_ERR_BAD_OVERFLOW If the operation was not completed,
- * due to the baudrate being too low or the
- * system frequency being too high
- * \retval STATUS_ERR_BAD_DATA If the operation was not completed, due
- * to data being corrupted
- * \retval STATUS_ERR_DENIED If the receiver is not enabled
- */
-enum status_code usart_read_buffer_wait(
- struct usart_module *const module,
- uint8_t *rx_data,
- uint16_t length)
-{
- /* Sanity check arguments */
- Assert(module);
- Assert(module->hw);
-
- /* Check if the buffer length is valid */
- if (length == 0) {
- return STATUS_ERR_INVALID_ARG;
- }
-
- /* Check that the receiver is enabled */
- if (!(module->receiver_enabled)) {
- return STATUS_ERR_DENIED;
- }
-
- /* Get a pointer to the hardware module instance */
- SercomUsart *const usart_hw = &(module->hw->USART);
-
- uint16_t rx_pos = 0;
-
- /* Blocks while buffer is being received */
- while (length--) {
- /* Wait for the USART to have new data and abort operation if it
- * doesn't get ready within the timeout*/
- for (uint32_t i = 0; i <= USART_TIMEOUT; i++) {
- if (usart_hw->INTFLAG.reg & SERCOM_USART_INTFLAG_RXC) {
- break;
- } else if (i == USART_TIMEOUT) {
- return STATUS_ERR_TIMEOUT;
- }
- }
-
- enum status_code retval;
- uint16_t received_data = 0;
-
- retval = usart_read_wait(module, &received_data);
-
- if (retval != STATUS_OK) {
- /* Overflow, abort */
- return retval;
- }
-
- /* Read value will be at least 8-bits long */
- rx_data[rx_pos++] = received_data;
-
- /* If 9-bit data, write next received byte to the buffer */
- if (module->character_size == USART_CHARACTER_SIZE_9BIT) {
- rx_data[rx_pos++] = (received_data >> 8);
- }
- }
-
- return STATUS_OK;
-}