diff --git a/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/TARGET_SAMR21G18A/SAMR21_XPLAINED_PRO/mbed_overrides.c b/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/TARGET_SAMR21G18A/SAMR21_XPLAINED_PRO/mbed_overrides.c
index 074e99efea..9b9f384ae6 100644
--- a/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/TARGET_SAMR21G18A/SAMR21_XPLAINED_PRO/mbed_overrides.c
+++ b/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/TARGET_SAMR21G18A/SAMR21_XPLAINED_PRO/mbed_overrides.c
@@ -16,11 +16,13 @@
#include "mbed_assert.h"
#include "compiler.h"
+#include "system.h"
+
//called before main - implement here if board needs it ortherwise, let
// the application override this if necessary
//TODO: To be implemented by adding system init and board init
void mbed_sdk_init()
{
-
+ system_init();
}
/***************************************************************/
diff --git a/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/TARGET_SAMR21G18A/device.h b/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/TARGET_SAMR21G18A/device.h
index cdbedf818a..a9f626e0d8 100644
--- a/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/TARGET_SAMR21G18A/device.h
+++ b/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/TARGET_SAMR21G18A/device.h
@@ -31,8 +31,9 @@
#define DEVICE_I2C 0
#define DEVICE_I2CSLAVE 0
-#define DEVICE_SPI 0
+#define DEVICE_SPI 1
#define DEVICE_SPISLAVE 0
+#define DEVICE_SPI_ASYNCH 1
#define DEVICE_CAN 0
diff --git a/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/drivers/sercom/spi/quick_start_dma/qs_spi_dma_use.h b/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/drivers/sercom/spi/quick_start_dma/qs_spi_dma_use.h
deleted file mode 100644
index 06a5061ef2..0000000000
--- a/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/drivers/sercom/spi/quick_start_dma/qs_spi_dma_use.h
+++ /dev/null
@@ -1,240 +0,0 @@
-/**
- * \file
- *
- * \brief SAM D21/R21/L21 Quick Start Guide for Using SPI driver with DMA
- *
- * Copyright (C) 2014 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
- *
- */
-
-/**
- * \page asfdoc_sam0_sercom_spi_dma_use_case Quick Start Guide for Using DMA with SERCOM SPI
- *
- * The supported board list:
- * - SAMD21 Xplained Pro
- * - SAMR21 Xplained Pro
- * - SAML21 Xplained Pro
- *
- * This quick start will transmit a buffer data from master to slave through DMA.
- * In this use case the SPI master will be configured with the following
- * settings on SAM Xplained Pro:
- * - Master Mode enabled
- * - MSB of the data is transmitted first
- * - Transfer mode 0
- * - 8-bit character size
- * - Not enabled in sleep mode
- * - Baudrate 100000
- * - GLCK generator 0
- *
- * The SPI slave will be configured with the following settings:
- * - Slave mode enabled
- * - Preloading of shift register enabled
- * - MSB of the data is transmitted first
- * - Transfer mode 0
- * - 8-bit character size
- * - Not enabled in sleep mode
- * - GLCK generator 0
- *
- * Note that the pinouts on other boards may different, see next sector for
- * details.
- *
- * \section asfdoc_sam0_sercom_spi_dma_use_case_setup Setup
- *
- * \subsection asfdoc_sam0_sercom_spi_dma_use_case_prereq Prerequisites
- * The following connections has to be made using wires:
- * - SAM D21 Xplained Pro.
- * - \b SS_0: EXT1 PIN15 (PA05) <--> EXT2 PIN15 (PA17)
- * - \b DO/DI: EXT1 PIN16 (PA06) <--> EXT2 PIN17 (PA16)
- * - \b DI/DO: EXT1 PIN17 (PA04) <--> EXT2 PIN16 (PA18)
- * - \b SCK: EXT1 PIN18 (PA07) <--> EXT2 PIN18 (PA19)
- * - SAM R21 Xplained Pro.
- * - \b SS_0: EXT1 PIN15 (PB03) <--> EXT1 PIN10 (PA23)
- * - \b DO/DI: EXT1 PIN16 (PB22) <--> EXT1 PIN9 (PA22)
- * - \b DI/DO: EXT1 PIN17 (PB02) <--> EXT1 PIN7 (PA18)
- * - \b SCK: EXT1 PIN18 (PB23) <--> EXT1 PIN8 (PA19)
- * - SAM L21 Xplained Pro.
- * - \b SS_0: EXT1 PIN15 (PA05) <--> EXT1 PIN12 (PA09)
- * - \b DO/DI: EXT1 PIN16 (PA06) <--> EXT1 PIN11 (PA08)
- * - \b DI/DO: EXT1 PIN17 (PA04) <--> EXT2 PIN03 (PA10)
- * - \b SCK: EXT1 PIN18 (PA07) <--> EXT2 PIN04 (PA11)
- *
- * \subsection asfdoc_sam0_spi_dma_use_case_setup_code Code
- *
- * Add to the main application source file, before user definitions and
- * functions according to your board:
- *
- * For SAMD21 Xplained Pro:
- * \snippet samd21_xplained_pro/conf_quick_start.h definition_master
- * \snippet samd21_xplained_pro/conf_quick_start.h definition_slave
- * \snippet samd21_xplained_pro/conf_quick_start.h definition_peripheral_trigger
- * For SAMR21 Xplained Pro:
- * \snippet samr21_xplained_pro/conf_quick_start.h definition_master
- * \snippet samr21_xplained_pro/conf_quick_start.h definition_slave
- * \snippet samr21_xplained_pro/conf_quick_start.h definition_peripheral_trigger
- * For SAML21 Xplained Pro:
- * \snippet saml21_xplained_pro/conf_quick_start.h definition_master
- * \snippet saml21_xplained_pro/conf_quick_start.h definition_slave
- * \snippet saml21_xplained_pro/conf_quick_start.h definition_peripheral_trigger
-
- * Add to the main application source file, outside of any functions:
- * \snippet qs_spi_dma_use.c buf_length
- * \snippet qs_spi_dma_use.c spi_baudrate
- * \snippet qs_spi_dma_use.c slave_select_pin
- * \snippet qs_spi_dma_use.c spi_buffer
- * \snippet qs_spi_dma_use.c spi_module_inst
- * \snippet qs_spi_dma_use.c dma_transfer_done_flag
- * \snippet qs_spi_dma_use.c slave_dev_inst
- * \snippet qs_spi_dma_use.c dma_transfer_descriptor
- *
- * Copy-paste the following setup code to your user application:
- * \snippet qs_spi_dma_use.c setup
- *
- * Add to user application initialization (typically the start of \c main()):
- * \snippet qs_spi_dma_use.c setup_init
- *
- * \subsection asfdoc_sam0_spi_dma_use_case_setup_flow Workflow
- * -# Create a module software instance structure for the SPI module to store
- * the SPI driver state while it is in use.
- * \snippet qs_spi_dma_use.c spi_module_inst
- * \note This should never go out of scope as long as the module is in use.
- * In most cases, this should be global.
- *
- * -# Create a module software instance structure for DMA resource to store
- * the DMA resource state while it is in use.
- * \snippet qs_spi_dma_use.c dma_resource
- * \note This should never go out of scope as long as the module is in use.
- * In most cases, this should be global.
- *
- * -# Create transfer done flag to indication DMA transfer done.
- * \snippet qs_spi_dma_use.c dma_transfer_done_flag
- * -# Define the buffer length for TX/RX.
- * \snippet qs_spi_dma_use.c buf_length
- * -# Create buffer to store the data to be transferred.
- * \snippet qs_spi_dma_use.c spi_buffer
- * -# Create SPI module configuration struct, which can be filled out to
- * adjust the configuration of a physical SPI peripheral.
- * \snippet qs_spi_dma_use.c spi_master_config
- * \snippet qs_spi_dma_use.c spi_slave_config
- * -# Initialize the SPI configuration struct with the module's default values.
- * \snippet qs_spi_dma_use.c spi_master_conf_defaults
- * \snippet qs_spi_dma_use.c spi_slave_conf_defaults
- * \note This should always be performed before using the configuration
- * struct to ensure that all values are initialized to known default
- * settings.
- *
- * -# Alter the SPI settings to configure the physical pinout, baudrate and
- * other relevant parameters.
- * \snippet qs_spi_dma_use.c spi_master_mux_setting
- * \snippet qs_spi_dma_use.c spi_slave_mux_setting
- * -# Configure the SPI module with the desired settings, retrying while the
- * driver is busy until the configuration is stressfully set.
- * \snippet qs_spi_dma_use.c spi_master_init
- * \snippet qs_spi_dma_use.c spi_slave_init
- * -# Enable the SPI module.
- * \snippet qs_spi_dma_use.c spi_master_enable
- * \snippet qs_spi_dma_use.c spi_slave_enable
- *
- * -# Create DMA resource configuration structure, which can be filled out to
- * adjust the configuration of a single DMA transfer.
- * \snippet qs_spi_dma_use.c dma_tx_setup_1
- * \snippet qs_spi_dma_use.c dma_rx_setup_1
- *
- * -# Initialize the DMA resource configuration struct with the module's
- * default values.
- * \snippet qs_spi_dma_use.c dma_tx_setup_2
- * \snippet qs_spi_dma_use.c dma_rx_setup_2
- * \note This should always be performed before using the configuration
- * struct to ensure that all values are initialized to known default
- * settings.
- *
- * -# Set extra configurations for the DMA resource. It is using peripheral
- * trigger. SERCOM TX empty and RX complete trigger causes a beat transfer in
- * this example.
- * \snippet qs_spi_dma_use.c dma_tx_setup_3
- * \snippet qs_spi_dma_use.c dma_rx_setup_3
- *
- * -# Allocate a DMA resource with the configurations.
- * \snippet qs_spi_dma_use.c dma_tx_setup_4
- * \snippet qs_spi_dma_use.c dma_rx_setup_4
- *
- * -# Create a DMA transfer descriptor configuration structure, which can be
- * filled out to adjust the configuration of a single DMA transfer.
- * \snippet qs_spi_dma_use.c dma_tx_setup_5
- * \snippet qs_spi_dma_use.c dma_rx_setup_5
- *
- * -# Initialize the DMA transfer descriptor configuration struct with the module's
- * default values.
- * \snippet qs_spi_dma_use.c dma_tx_setup_6
- * \snippet qs_spi_dma_use.c dma_rx_setup_6
- * \note This should always be performed before using the configuration
- * struct to ensure that all values are initialized to known default
- * settings.
- *
- * -# Set the specific parameters for a DMA transfer with transfer size, source
- * address, and destination address.
- * \snippet qs_spi_dma_use.c dma_tx_setup_7
- * \snippet qs_spi_dma_use.c dma_rx_setup_7
- *
- * -# Create the DMA transfer descriptor.
- * \snippet qs_spi_dma_use.c dma_tx_setup_8
- * \snippet qs_spi_dma_use.c dma_rx_setup_8
- *
- * \section asfdoc_sam0_spi_dma_use_case_main Use Case
- *
- * \subsection asfdoc_sam0_spi_dma_use_case_main_code Code
- * Copy-paste the following code to your user application:
- * \snippet qs_spi_dma_use.c main
- *
- * \subsection asfdoc_sam0_spi_dma_use_case_main_flow Workflow
- * -# Select the slave.
- * \snippet qs_spi_dma_use.c select_slave
- *
- * -# Start the transfer job.
- * \snippet qs_spi_dma_use.c main_1
- *
- * -# Wait for transfer done.
- * \snippet qs_spi_dma_use.c main_2
- *
- * -# Deselect the slave.
- * \snippet qs_spi_dma_use.c deselect_slave
- *
- * -# Enter endless loop.
- * \snippet qs_spi_dma_use.c endless_loop
- */
- /**
- * Support and FAQ: visit Atmel Support
- */
diff --git a/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/drivers/sercom/spi/quick_start_master/qs_spi_master_basic.h b/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/drivers/sercom/spi/quick_start_master/qs_spi_master_basic.h
deleted file mode 100644
index d404556dc2..0000000000
--- a/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/drivers/sercom/spi/quick_start_master/qs_spi_master_basic.h
+++ /dev/null
@@ -1,133 +0,0 @@
-/**
- * \file
- *
- * \brief SAM SPI Quick Start
- *
- * Copyright (C) 2012-2014 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
- *
- */
-
-/**
- * \page asfdoc_sam0_sercom_spi_master_basic_use Quick Start Guide for SERCOM SPI Master - Polled
- *
- * In this use case, the SPI on extension header 1 of the Xplained Pro board
- * will configured with the following settings:
- * - Master Mode enabled
- * - MSB of the data is transmitted first
- * - Transfer mode 0
- * - 8-bit character size
- * - Not enabled in sleep mode
- * - Baudrate 100000
- * - GLCK generator 0
- *
- *
- * \section asfdoc_sam0_sercom_spi_master_basic_use_setup Setup
- *
- * \subsection asfdoc_sam0_sercom_spi_master_basic_use_prereq Prerequisites
- * There are no special setup requirements for this use-case.
- *
- * \subsection asfdoc_sam0_sercom_spi_master_basic_use_setup_code Code
- * The following must be added to the user application:
- *
- * A sample buffer to send via SPI.
- * \snippet qs_spi_master_basic.c buffer
- * Number of entries in the sample buffer.
- * \snippet qs_spi_master_basic.c buf_length
- * GPIO pin to use as Slave Select.
- * \snippet qs_spi_master_basic.c slave_select_pin
- * A globally available software device instance struct to store the SPI driver
- * state while it is in use.
- * \snippet qs_spi_master_basic.c dev_inst
- * A globally available peripheral slave software device instance struct.
- * \snippet qs_spi_master_basic.c slave_dev_inst
- * A function for configuring the SPI.
- * \snippet qs_spi_master_basic.c configure_spi
- *
- * Add to user application \c main().
- * \snippet qs_spi_master_basic.c main_setup
- *
- * \section asfdoc_sam0_sercom_spi_master_basic_use_workflow Workflow
- * -# Initialize system.
- * \snippet qs_spi_master_basic.c system_init
- * -# Setup the SPI.
- * \snippet qs_spi_master_basic.c run_config
- * -# Create configuration struct.
- * \snippet qs_spi_master_basic.c config
- * -# Create peripheral slave configuration struct.
- * \snippet qs_spi_master_basic.c slave_config
- * -# Create peripheral slave software device instance struct.
- * \snippet qs_spi_master_basic.c slave_dev_inst
- * -# Get default peripheral slave configuration.
- * \snippet qs_spi_master_basic.c slave_conf_defaults
- * -# Set Slave Select pin.
- * \snippet qs_spi_master_basic.c ss_pin
- * -# Initialize peripheral slave software instance with configuration.
- * \snippet qs_spi_master_basic.c slave_init
- * -# Get default configuration to edit.
- * \snippet qs_spi_master_basic.c conf_defaults
- * -# Set MUX setting E.
- * \snippet qs_spi_master_basic.c mux_setting
- * -# Set pinmux for pad 0 (data in (MISO)).
- * \snippet qs_spi_master_basic.c di
- * -# Set pinmux for pad 1 as unused, so the pin can be used for other purposes.
- * \snippet qs_spi_master_basic.c ss
- * -# Set pinmux for pad 2 (data out (MOSI)).
- * \snippet qs_spi_master_basic.c do
- * -# Set pinmux for pad 3 (SCK).
- * \snippet qs_spi_master_basic.c sck
- * -# Initialize SPI module with configuration.
- * \snippet qs_spi_master_basic.c init
- * -# Enable SPI module.
- * \snippet qs_spi_master_basic.c enable
- *
- * \section asfdoc_sam0_sercom_spi_master_basic_use_case Use Case
- * \subsection asfdoc_sam0_sercom_spi_master_basic_use_case_code Code
- * Add the following to your user application \c main().
- * \snippet qs_spi_master_basic.c main_use_case
- * \subsection asfdoc_sam0_sercom_spi_master_basic_use_case_workflow Workflow
- * -# Select slave.
- * \snippet qs_spi_master_basic.c select_slave
- * -# Write buffer to SPI slave.
- * \snippet qs_spi_master_basic.c write
- * -# Deselect slave.
- * \snippet qs_spi_master_basic.c deselect_slave
- * -# Infinite loop.
- * \snippet qs_spi_master_basic.c inf_loop
- */
- /**
- * Support and FAQ: visit Atmel Support
- */
diff --git a/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/drivers/sercom/spi/quick_start_slave/qs_spi_slave_basic.h b/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/drivers/sercom/spi/quick_start_slave/qs_spi_slave_basic.h
deleted file mode 100644
index 7aa6e5183c..0000000000
--- a/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/drivers/sercom/spi/quick_start_slave/qs_spi_slave_basic.h
+++ /dev/null
@@ -1,123 +0,0 @@
-/**
- * \file
- *
- * \brief SAM SPI Quick Start
- *
- * Copyright (C) 2012-2014 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
- *
- */
-
-/**
- * \page asfdoc_sam0_sercom_spi_slave_basic_use Quick Start Guide for SERCOM SPI Slave - Polled
- *
- * In this use case, the SPI on extension header 1 of the Xplained Pro board
- * will configured with the following settings:
- * - Slave mode enabled
- * - Preloading of shift register enabled
- * - MSB of the data is transmitted first
- * - Transfer mode 0
- * - 8-bit character size
- * - Not enabled in sleep mode
- * - GLCK generator 0
- *
- *
- * \section asfdoc_sam0_sercom_spi_slave_basic_use_setup Setup
- *
- * \subsection asfdoc_sam0_sercom_spi_slave_basic_use_prereq Prerequisites
- * The device must be connected to a SPI master which must read from the device.
- *
- * \subsection asfdoc_sam0_sercom_spi_slave_basic_use_setup_code Code
- * The following must be added to the user application source file, outside
- * any functions:
- *
- * A sample buffer to send via SPI.
- * \snippet qs_spi_slave_basic.c buffer
- * Number of entries in the sample buffer.
- * \snippet qs_spi_slave_basic.c buf_length
- * A globally available software device instance struct to store the SPI driver
- * state while it is in use.
- * \snippet qs_spi_slave_basic.c dev_inst
- * A function for configuring the SPI.
- * \snippet qs_spi_slave_basic.c configure_spi
- *
- * Add to user application \c main().
- * \snippet qs_spi_slave_basic.c main_start
- *
- * \subsection asfdoc_sam0_sercom_spi_slave_basic_use_workflow Workflow
- * -# Initialize system.
- * \snippet qs_spi_slave_basic.c system_init
- * -# Setup the SPI.
- * \snippet qs_spi_slave_basic.c run_config
- * -# Create configuration struct.
- * \snippet qs_spi_slave_basic.c config
- * -# Get default configuration to edit.
- * \snippet qs_spi_slave_basic.c conf_defaults
- * -# Set the SPI in slave mode.
- * \snippet qs_spi_slave_basic.c conf_spi_slave_instance
- * -# Enable preloading of shift register.
- * \snippet qs_spi_slave_basic.c conf_preload
- * -# Set frame format to SPI frame.
- * \snippet qs_spi_slave_basic.c conf_format
- * -# Set MUX setting E.
- * \snippet qs_spi_slave_basic.c mux_setting
- * -# Set pinmux for pad 0 (data in (MOSI)).
- * \snippet qs_spi_slave_basic.c di
- * -# Set pinmux for pad 1 (slave select).
- * \snippet qs_spi_slave_basic.c ss
- * -# Set pinmux for pad 2 (data out (MISO)).
- * \snippet qs_spi_slave_basic.c do
- * -# Set pinmux for pad 3 (SCK).
- * \snippet qs_spi_slave_basic.c sck
- * -# Initialize SPI module with configuration.
- * \snippet qs_spi_slave_basic.c init
- * -# Enable SPI module.
- * \snippet qs_spi_slave_basic.c enable
- *
- * \section asfdoc_sam0_sercom_spi_slave_basic_use_case Use Case
- * \subsection asfdoc_sam0_sercom_spi_slave_basic_use_case_code Code
- * Add the following to your user application \c main().
- * \snippet qs_spi_slave_basic.c main_use_case
- * \subsection asfdoc_sam0_sercom_spi_slave_basic_use_case_workflow Workflow
- * -# Write buffer to SPI master. Placed in a loop to retry in case of a
- * timeout before a master initiates a transaction.
- * \snippet qs_spi_slave_basic.c write
- * -# Infinite loop.
- * \snippet qs_spi_slave_basic.c inf_loop
- */
- /**
- * Support and FAQ: visit Atmel Support
- */
diff --git a/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/drivers/sercom/spi/spi.c b/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/drivers/sercom/spi/spi.c
deleted file mode 100644
index 941e243993..0000000000
--- a/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/drivers/sercom/spi/spi.c
+++ /dev/null
@@ -1,1242 +0,0 @@
-/**
- * \file
- *
- * \brief SAM Serial Peripheral Interface Driver
- *
- * Copyright (C) 2012-2014 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 Atmel Support
- */
-#include "spi.h"
-
-/**
- * \brief Resets the SPI module
- *
- * This function will reset the SPI module to its power on default values and
- * disable it.
- *
- * \param[in,out] module Pointer to the software instance struct
- */
-void spi_reset(
- struct spi_module *const module)
-{
- /* Sanity check arguments */
- Assert(module);
- Assert(module->hw);
-
- SercomSpi *const spi_module = &(module->hw->SPI);
-
- /* Disable the module */
- spi_disable(module);
-
- while (spi_is_syncing(module)) {
- /* Wait until the synchronization is complete */
- }
-
- /* Software reset the module */
- spi_module->CTRLA.reg |= SERCOM_SPI_CTRLA_SWRST;
-}
-
-/**
- * \brief Set the baudrate of the SPI module
- *
- * This function will set the baudrate of the SPI module.
- *
- * \param[in] module Pointer to the software instance struct
- * \param[in] baudrate The baudrate wanted
- *
- * \return The status of the configuration.
- * \retval STATUS_ERR_INVALID_ARG If invalid argument(s) were provided
- * \retval STATUS_OK If the configuration was written
- */
-enum status_code spi_set_baudrate(
- struct spi_module *const module,
- uint32_t baudrate)
-{
- /* Sanity check arguments */
- Assert(module);
- Assert(baudrate);
- Assert(module->hw);
-
- /* Value to write to BAUD register */
- uint16_t baud = 0;
-
- SercomSpi *const spi_module = &(module->hw->SPI);
-
- /* Disable the module */
- spi_disable(module);
-
- while (spi_is_syncing(module)) {
- /* Wait until the synchronization is complete */
- }
-
- /* Find frequency of the internal SERCOMi_GCLK_ID_CORE */
- uint32_t sercom_index = _sercom_get_sercom_inst_index(module->hw);
- uint32_t gclk_index = sercom_index + SERCOM0_GCLK_ID_CORE;
- uint32_t internal_clock = system_gclk_chan_get_hz(gclk_index);
-
- /* Get baud value, based on baudrate and the internal clock frequency */
- enum status_code error_code = _sercom_get_sync_baud_val(
- baudrate, internal_clock, &baud);
-
- if (error_code != STATUS_OK) {
- /* Baud rate calculation error, return status code */
- return STATUS_ERR_INVALID_ARG;
- }
-
- spi_module->BAUD.reg = (uint8_t)baud;
-
- while (spi_is_syncing(module)) {
- /* Wait until the synchronization is complete */
- }
-
- /* Enable the module */
- spi_enable(module);
-
- while (spi_is_syncing(module)) {
- /* Wait until the synchronization is complete */
- }
-
- return STATUS_OK;
-}
-
-# if CONF_SPI_SLAVE_ENABLE == true
-/**
- * \internal Clears the Transmit Complete interrupt flag.
- *
- * \param[in] module Pointer to the software instance struct
- */
-static void _spi_clear_tx_complete_flag(
- struct spi_module *const module)
-{
- /* Sanity check arguments */
- Assert(module);
- Assert(module->hw);
-
- SercomSpi *const spi_module = &(module->hw->SPI);
-
- /* Clear interrupt flag */
- spi_module->INTFLAG.reg = SPI_INTERRUPT_FLAG_TX_COMPLETE;
-}
-# endif
-
-/**
- * \internal Writes an SPI SERCOM configuration to the hardware module.
- *
- * This function will write out a given configuration to the hardware module.
- * Can only be done when the module is disabled.
- *
- * \param[in] module Pointer to the software instance struct
- * \param[in] config Pointer to the configuration struct
- *
- * \return The status of the configuration.
- * \retval STATUS_ERR_INVALID_ARG If invalid argument(s) were provided
- * \retval STATUS_OK If the configuration was written
- */
-static enum status_code _spi_set_config(
- struct spi_module *const module,
- const struct spi_config *const config)
-{
- /* Sanity check arguments */
- Assert(module);
- Assert(config);
- Assert(module->hw);
-
- SercomSpi *const spi_module = &(module->hw->SPI);
- Sercom *const hw = module->hw;
-
- struct system_pinmux_config pin_conf;
- system_pinmux_get_config_defaults(&pin_conf);
- pin_conf.direction = SYSTEM_PINMUX_PIN_DIR_INPUT;
- if(config->mode == SPI_MODE_SLAVE) {
- 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);
- }
- }
-
- module->mode = config->mode;
- module->character_size = config->character_size;
- module->receiver_enabled = config->receiver_enable;
-# ifdef FEATURE_SPI_HARDWARE_SLAVE_SELECT
- module->master_slave_select_enable = config->master_slave_select_enable;
-# endif
-
-# if CONF_SPI_MASTER_ENABLE == true
- /* Value to write to BAUD register */
- uint16_t baud = 0;
-# endif
- /* Value to write to CTRLA register */
- uint32_t ctrla = 0;
- /* Value to write to CTRLB register */
- uint32_t ctrlb = 0;
-
-# if CONF_SPI_MASTER_ENABLE == true
- /* Find baud value and write it */
- if (config->mode == SPI_MODE_MASTER) {
- /* Find frequency of the internal SERCOMi_GCLK_ID_CORE */
- uint32_t sercom_index = _sercom_get_sercom_inst_index(module->hw);
- uint32_t gclk_index = sercom_index + SERCOM0_GCLK_ID_CORE;
- uint32_t internal_clock = system_gclk_chan_get_hz(gclk_index);
-
- /* Get baud value, based on baudrate and the internal clock frequency */
- enum status_code error_code = _sercom_get_sync_baud_val(
- config->mode_specific.master.baudrate,
- internal_clock, &baud);
-
- if (error_code != STATUS_OK) {
- /* Baud rate calculation error, return status code */
- return STATUS_ERR_INVALID_ARG;
- }
-
- spi_module->BAUD.reg = (uint8_t)baud;
- }
-# endif
-# if CONF_SPI_SLAVE_ENABLE == true
- if (config->mode == SPI_MODE_SLAVE) {
- /* Set frame format */
- ctrla = config->mode_specific.slave.frame_format;
-
- /* Set address mode */
- ctrlb = config->mode_specific.slave.address_mode;
-
- /* Set address and address mask*/
- spi_module->ADDR.reg |=
- (config->mode_specific.slave.address << SERCOM_SPI_ADDR_ADDR_Pos) |
- (config->mode_specific.slave.address_mask << SERCOM_SPI_ADDR_ADDRMASK_Pos);
-
- if (config->mode_specific.slave.preload_enable) {
- /* Enable pre-loading of shift register */
- ctrlb |= SERCOM_SPI_CTRLB_PLOADEN;
- }
- }
-# endif
- /* Set data order */
- ctrla |= config->data_order;
-
- /* Set clock polarity and clock phase */
- ctrla |= config->transfer_mode;
-
- /* Set MUX setting */
- ctrla |= config->mux_setting;
-
- /* Set SPI character size */
- ctrlb |= config->character_size;
-
- /* Set whether module should run in standby. */
- if (config->run_in_standby || system_is_debugger_present()) {
- ctrla |= SERCOM_SPI_CTRLA_RUNSTDBY;
- }
-
- if (config->receiver_enable) {
- /* Enable receiver */
- ctrlb |= SERCOM_SPI_CTRLB_RXEN;
- }
-# ifdef FEATURE_SPI_SLAVE_SELECT_LOW_DETECT
- if (config->select_slave_low_detect_enable) {
- /* Enable Slave Select Low Detect */
- ctrlb |= SERCOM_SPI_CTRLB_SSDE;
- }
-# endif
-# ifdef FEATURE_SPI_HARDWARE_SLAVE_SELECT
- if (config->master_slave_select_enable) {
- /* Enable Master Slave Select */
- ctrlb |= SERCOM_SPI_CTRLB_MSSEN;
- }
-# endif
- /* Write CTRLA register */
- spi_module->CTRLA.reg |= ctrla;
-
- /* Write CTRLB register */
- spi_module->CTRLB.reg |= ctrlb;
-
- return STATUS_OK;
-}
-
-#if SPI_CALLBACK_MODE == false
-/**
- * \internal Checks an SPI config against current set config
- *
- * This function will check that the config does not alter the
- * configuration of the module. If the new config changes any
- * setting, the initialization will be discarded.
- *
- * \param[in] module Pointer to the software instance struct
- * \param[in] config Pointer to the configuration struct
- *
- * \return The status of the configuration.
- * \retval STATUS_ERR_INVALID_ARG If invalid argument(s) were provided
- * \retval STATUS_ERR_DENIED If configuration was different from previous
- * \retval STATUS_OK If the configuration was written
- */
-static enum status_code _spi_check_config(
- struct spi_module *const module,
- const struct spi_config *const config)
-{
- /* Sanity check arguments */
- Assert(module);
- Assert(config);
- Assert(module->hw);
-
- SercomSpi *const spi_module = &(module->hw->SPI);
- Sercom *const hw = module->hw;
-
- uint32_t pad_pinmuxes[] = {
- config->pinmux_pad0, config->pinmux_pad1,
- config->pinmux_pad2, config->pinmux_pad3
- };
-
- /* Compare the current SERCOM pins against 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) {
- continue;
- }
-
- if ((current_pinmux & 0xFFFF) !=
- system_pinmux_pin_get_mux_position(current_pinmux >> 16)) {
- module->hw = NULL;
- return STATUS_ERR_DENIED;
- }
- }
-
-# if CONF_SPI_MASTER_ENABLE == true
- /* Value to read BAUD register */
- uint16_t baud;
- uint32_t external_clock = system_gclk_chan_get_hz(SERCOM_GCLK_ID);
-# endif
- /* Value to read CTRLA, CTRLB and ADDR register */
- uint32_t ctrla = 0;
- uint32_t ctrlb = 0;
-# if CONF_SPI_SLAVE_ENABLE == true
- uint32_t addr = 0;
-# endif
-
-# if CONF_SPI_MASTER_ENABLE == true
- /* Find baud value and compare it */
- if (config->mode == SPI_MODE_MASTER) {
- enum status_code error_code = _sercom_get_sync_baud_val(
- config->mode_specific.master.baudrate,
- external_clock, &baud);
-
- if (error_code != STATUS_OK) {
- /* Baud rate calculation error, return status code */
- return STATUS_ERR_INVALID_ARG;
- }
-
- if (spi_module->BAUD.reg != (uint8_t)baud) {
- return STATUS_ERR_DENIED;
- }
-
- ctrla |= SERCOM_SPI_CTRLA_MODE(0x3);
- }
-# endif
-
-# if CONF_SPI_SLAVE_ENABLE == true
- if (config->mode == SPI_MODE_SLAVE) {
-
- /* Set frame format */
- ctrla |= config->mode_specific.slave.frame_format;
-
- /* Set address mode */
- ctrlb |= config->mode_specific.slave.address_mode;
-
- /* Set address and address mask*/
- addr |= (config->mode_specific.slave.address << SERCOM_SPI_ADDR_ADDR_Pos) |
- (config->mode_specific.slave.address_mask << SERCOM_SPI_ADDR_ADDRMASK_Pos);
- if (spi_module->CTRLA.reg != addr) {
- return STATUS_ERR_DENIED;
- }
-
- if (config->mode_specific.slave.preload_enable) {
- /* Enable pre-loading of shift register */
- ctrlb |= SERCOM_SPI_CTRLB_PLOADEN;
- }
- ctrla |= SERCOM_SPI_CTRLA_MODE(0x2);
- }
-# endif
- /* Set data order */
- ctrla |= config->data_order;
-
- /* Set clock polarity and clock phase */
- ctrla |= config->transfer_mode;
-
- /* Set MUX setting */
- ctrla |= config->mux_setting;
-
- /* Set SPI character size */
- ctrlb |= config->character_size;
-
- if (config->run_in_standby) {
- /* Enable in sleep mode */
- ctrla |= SERCOM_SPI_CTRLA_RUNSTDBY;
- }
-
- if (config->receiver_enable) {
- /* Enable receiver */
- ctrlb |= SERCOM_SPI_CTRLB_RXEN;
- }
-
-# ifdef FEATURE_SPI_SLAVE_SELECT_LOW_DETECT
- if (config->select_slave_low_detect_enable) {
- /* Enable Slave Select Low Detect */
- ctrlb |= SERCOM_SPI_CTRLB_SSDE;
- }
-# endif
-# ifdef FEATURE_SPI_HARDWARE_SLAVE_SELECT
- if (config->master_slave_select_enable) {
- /* Enable Master Slave Select */
- ctrlb |= SERCOM_SPI_CTRLB_MSSEN;
- }
-# endif
-
- ctrla |= SERCOM_SPI_CTRLA_ENABLE;
-
- /* Check that same config is set */
- if (spi_module->CTRLA.reg == ctrla &&
- spi_module->CTRLB.reg == ctrlb) {
- module->mode = config->mode;
- module->character_size = config->character_size;
- return STATUS_OK;
- }
-
- /* Not same config, wipe module pointer and return */
- module->hw = NULL;
-
- return STATUS_ERR_DENIED;
-}
-#endif
-
-/**
- * \brief Initializes the SERCOM SPI module
- *
- * This function will initialize the SERCOM SPI module, based on the values
- * of the config struct.
- *
- * \param[out] module Pointer to the software instance struct
- * \param[in] hw Pointer to hardware instance
- * \param[in] config Pointer to the config struct
- *
- * \return Status of the initialization.
- * \retval STATUS_OK Module initiated correctly
- * \retval STATUS_ERR_DENIED If module is enabled
- * \retval STATUS_BUSY If module is busy resetting
- * \retval STATUS_ERR_INVALID_ARG If invalid argument(s) were provided
- */
-enum status_code spi_init(
- struct spi_module *const module,
- Sercom *const hw,
- const struct spi_config *const config)
-{
-
- /* Sanity check arguments */
- Assert(module);
- Assert(hw);
- Assert(config);
-
- /* Initialize device instance */
- module->hw = hw;
-
- SercomSpi *const spi_module = &(module->hw->SPI);
-
- /* Check if module is enabled. */
- if (spi_module->CTRLA.reg & SERCOM_SPI_CTRLA_ENABLE) {
-# if SPI_CALLBACK_MODE == false
- /* Check if config is valid */
- return _spi_check_config(module, config);
-# else
- return STATUS_ERR_DENIED;
-# endif
- }
-
- /* Check if reset is in progress. */
- if (spi_module->CTRLA.reg & SERCOM_SPI_CTRLA_SWRST){
- return STATUS_BUSY;
- }
-
- uint32_t sercom_index = _sercom_get_sercom_inst_index(module->hw);
- uint32_t pm_index, gclk_index;
-#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 + PM_APBCMASK_SERCOM0_Pos;
- gclk_index = sercom_index + SERCOM0_GCLK_ID_CORE;
-#endif
-
- /* 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);
-
-# if CONF_SPI_MASTER_ENABLE == true
- if (config->mode == SPI_MODE_MASTER) {
- /* Set the SERCOM in SPI master mode */
- spi_module->CTRLA.reg |= SERCOM_SPI_CTRLA_MODE(0x3);
- }
-# endif
-
-# if CONF_SPI_SLAVE_ENABLE == true
- if (config->mode == SPI_MODE_SLAVE) {
- /* Set the SERCOM in SPI slave mode */
- spi_module->CTRLA.reg |= SERCOM_SPI_CTRLA_MODE(0x2);
- }
-# endif
-
-#if SPI_CALLBACK_MODE == true
- /* Temporary variables */
- uint8_t i;
- uint8_t instance_index;
-
- /* Initialize parameters */
- for (i = 0; i < SPI_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->registered_callback = 0x00;
- module->enabled_callback = 0x00;
- module->status = STATUS_OK;
- module->dir = SPI_DIRECTION_IDLE;
- module->locked = false;
- /*
- * Set interrupt handler and register SPI software module struct in
- * look-up table
- */
- instance_index = _sercom_get_sercom_inst_index(module->hw);
- _sercom_set_handler(instance_index, _spi_interrupt_handler);
- _sercom_instances[instance_index] = module;
-#endif
-
- /* Write configuration to module and return status code */
- return _spi_set_config(module, config);
-}
-
-/**
- * \brief Reads buffer of \c length SPI characters
- *
- * This function will read a buffer of data from an SPI peripheral by sending
- * dummy SPI character if in master mode, or by waiting for data in slave mode.
- *
- * \note If address matching is enabled for the slave, the first character
- * received and placed in the buffer will be the address.
- *
- * \param[in] module Pointer to the software instance struct
- * \param[out] rx_data Data buffer for received data
- * \param[in] length Length of data to receive
- * \param[in] dummy 8- or 9-bit dummy byte to shift out in master mode
- *
- * \return Status of the read operation.
- * \retval STATUS_OK If the read was completed
- * \retval STATUS_ABORTED If transaction was ended by master before
- * entire buffer was transferred
- * \retval STATUS_ERR_INVALID_ARG If invalid argument(s) were provided
- * \retval STATUS_ERR_TIMEOUT If the operation was not completed within the
- * timeout in slave mode
- * \retval STATUS_ERR_DENIED If the receiver is not enabled
- * \retval STATUS_ERR_OVERFLOW If the data is overflown
- */
-enum status_code spi_read_buffer_wait(
- struct spi_module *const module,
- uint8_t *rx_data,
- uint16_t length,
- uint16_t dummy)
-{
- /* Sanity check arguments */
- Assert(module);
- Assert(module->hw);
-
-# if SPI_CALLBACK_MODE == true
- if (module->status == STATUS_BUSY) {
- /* Check if the SPI module is busy with a job */
- return STATUS_BUSY;
- }
-# endif
-
- /* Sanity check arguments */
- if (length == 0) {
- return STATUS_ERR_INVALID_ARG;
- }
-
- if (!(module->receiver_enabled)) {
- return STATUS_ERR_DENIED;
- }
-# if CONF_SPI_SLAVE_ENABLE == true
- if ((module->mode == SPI_MODE_SLAVE) && (spi_is_write_complete(module))) {
- /* Clear TX complete flag */
- _spi_clear_tx_complete_flag(module);
- }
-# endif
- uint16_t rx_pos = 0;
-
- while (length--) {
-# if CONF_SPI_MASTER_ENABLE == true
- if (module->mode == SPI_MODE_MASTER) {
- /* Wait until the module is ready to write a character */
- while (!spi_is_ready_to_write(module)) {
- }
-
- /* Send dummy SPI character to read in master mode */
- spi_write(module, dummy);
- }
-# endif
-
-# if CONF_SPI_SLAVE_ENABLE == true
- /* Start timeout period for slave */
- if (module->mode == SPI_MODE_SLAVE) {
- for (uint32_t i = 0; i <= SPI_TIMEOUT; i++) {
- if (spi_is_ready_to_read(module)) {
- break;
- }
- }
- /* Check if master has ended the transaction */
- if (spi_is_write_complete(module)) {
- _spi_clear_tx_complete_flag(module);
- return STATUS_ABORTED;
- }
-
- if (!spi_is_ready_to_read(module)) {
- /* Not ready to read data within timeout period */
- return STATUS_ERR_TIMEOUT;
- }
- }
-# endif
-
- /* Wait until the module is ready to read a character */
- while (!spi_is_ready_to_read(module)) {
- }
-
- uint16_t received_data = 0;
- enum status_code retval = spi_read(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 == SPI_CHARACTER_SIZE_9BIT) {
- rx_data[rx_pos++] = (received_data >> 8);
- }
- }
-
- return STATUS_OK;
-}
-
-/**
- * \brief Sends and reads a single SPI character
- *
- * This function will transfer a single SPI character via SPI and return the
- * SPI character that is shifted into the shift register.
- *
- * In master mode the SPI character will be sent immediately and the received
- * SPI character will be read as soon as the shifting of the data is
- * complete.
- *
- * In slave mode this function will place the data to be sent into the transmit
- * buffer. It will then block until an SPI master has shifted a complete
- * SPI character, and the received data is available.
- *
- * \note The data to be sent might not be sent before the next transfer, as
- * loading of the shift register is dependent on SCK.
- * \note If address matching is enabled for the slave, the first character
- * received and placed in the buffer will be the address.
- *
- * \param[in] module Pointer to the software instance struct
- * \param[in] tx_data SPI character to transmit
- * \param[out] rx_data Pointer to store the received SPI character
- *
- * \return Status of the operation.
- * \retval STATUS_OK If the operation was completed
- * \retval STATUS_ERR_TIMEOUT If the operation was not completed within the
- * timeout in slave mode
- * \retval STATUS_ERR_DENIED If the receiver is not enabled
- * \retval STATUS_ERR_OVERFLOW If the incoming data is overflown
- */
-enum status_code spi_transceive_wait(
- struct spi_module *const module,
- uint16_t tx_data,
- uint16_t *rx_data)
-{
- /* Sanity check arguments */
- Assert(module);
-
- if (!(module->receiver_enabled)) {
- return STATUS_ERR_DENIED;
- }
-
-# if SPI_CALLBACK_MODE == true
- if (module->status == STATUS_BUSY) {
- /* Check if the SPI module is busy with a job */
- return STATUS_BUSY;
- }
-# endif
-
-# if CONF_SPI_SLAVE_ENABLE == true
- uint16_t j;
-# endif
- enum status_code retval = STATUS_OK;
-
-# if CONF_SPI_SLAVE_ENABLE == true
- /* Start timeout period for slave */
- if (module->mode == SPI_MODE_SLAVE) {
- for (j = 0; j <= SPI_TIMEOUT; j++) {
- if (spi_is_ready_to_write(module)) {
- break;
- } else if (j == SPI_TIMEOUT) {
- /* Not ready to write data within timeout period */
- return STATUS_ERR_TIMEOUT;
- }
- }
- }
-# endif
- /* Wait until the module is ready to write the character */
- while (!spi_is_ready_to_write(module)) {
- }
-
- /* Write data */
- spi_write(module, tx_data);
-
-# if CONF_SPI_SLAVE_ENABLE == true
- /* Start timeout period for slave */
- if (module->mode == SPI_MODE_SLAVE) {
- for (j = 0; j <= SPI_TIMEOUT; j++) {
- if (spi_is_ready_to_read(module)) {
- break;
- } else if (j == SPI_TIMEOUT) {
- /* Not ready to read data within timeout period */
- return STATUS_ERR_TIMEOUT;
- }
- }
- }
-# endif
-
- /* Wait until the module is ready to read the character */
- while (!spi_is_ready_to_read(module)) {
- }
-
- /* Read data */
- retval = spi_read(module, rx_data);
-
- return retval;
-}
-
- /**
- * \brief Selects slave device
- *
- * This function will drive the slave select pin of the selected device low or
- * high depending on the select Boolean.
- * If slave address recognition is enabled, the address will be sent to the
- * slave when selecting it.
- *
- * \param[in] module Pointer to the software module struct
- * \param[in] slave Pointer to the attached slave
- * \param[in] select Boolean stating if the slave should be selected or
- * deselected
- *
- * \return Status of the operation.
- * \retval STATUS_OK If the slave device was selected
- * \retval STATUS_ERR_UNSUPPORTED_DEV If the SPI module is operating in slave
- * mode
- * \retval STATUS_BUSY If the SPI module is not ready to write
- * the slave address
- */
-enum status_code spi_select_slave(
- struct spi_module *const module,
- struct spi_slave_inst *const slave,
- const bool select)
-{
- /* Sanity check arguments */
- Assert(module);
- Assert(module->hw);
- Assert(slave);
-
- /* Check that the SPI module is operating in master mode */
- if (module->mode != SPI_MODE_MASTER) {
- return STATUS_ERR_UNSUPPORTED_DEV;
- }
-# ifdef FEATURE_SPI_HARDWARE_SLAVE_SELECT
- if(!(module->master_slave_select_enable))
-# endif
- {
- if (select) {
- /* Check if address recognition is enabled */
- if (slave->address_enabled) {
- /* Check if the module is ready to write the address */
- if (!spi_is_ready_to_write(module)) {
- /* Not ready, do not select slave and return */
- port_pin_set_output_level(slave->ss_pin, true);
- return STATUS_BUSY;
- }
-
- /* Drive Slave Select low */
- port_pin_set_output_level(slave->ss_pin, false);
-
- /* Write address to slave */
- spi_write(module, slave->address);
-
- if (!(module->receiver_enabled)) {
- /* Flush contents of shift register shifted back from slave */
- while (!spi_is_ready_to_read(module)) {
- }
- uint16_t flush = 0;
- spi_read(module, &flush);
- }
- } else {
- /* Drive Slave Select low */
- port_pin_set_output_level(slave->ss_pin, false);
- }
- } else {
- /* Drive Slave Select high */
- port_pin_set_output_level(slave->ss_pin, true);
- }
- }
- return STATUS_OK;
-}
-
-/**
- * \brief Sends a buffer of \c length SPI characters
- *
- * This function will send a buffer of SPI characters via the SPI
- * and discard any data that is received. To both send and receive a buffer of
- * data, use the \ref spi_transceive_buffer_wait function.
- *
- * Note that this function does not handle the _SS (slave select) pin(s) in
- * master mode; this must be handled by the user application.
- *
- * \param[in] module Pointer to the software instance struct
- * \param[in] tx_data Pointer to the buffer to transmit
- * \param[in] length Number of SPI characters to transfer
- *
- * \return Status of the write operation.
- * \retval STATUS_OK If the write was completed
- * \retval STATUS_ABORTED If transaction was ended by master before
- * entire buffer was transferred
- * \retval STATUS_ERR_INVALID_ARG If invalid argument(s) were provided
- * \retval STATUS_ERR_TIMEOUT If the operation was not completed within the
- * timeout in slave mode
- */
-enum status_code spi_write_buffer_wait(
- struct spi_module *const module,
- const uint8_t *tx_data,
- uint16_t length)
-{
- /* Sanity check arguments */
- Assert(module);
-
-# if SPI_CALLBACK_MODE == true
- if (module->status == STATUS_BUSY) {
- /* Check if the SPI module is busy with a job */
- return STATUS_BUSY;
- }
-# endif
-
- if (length == 0) {
- return STATUS_ERR_INVALID_ARG;
- }
-
-# if CONF_SPI_SLAVE_ENABLE == true
- if ((module->mode == SPI_MODE_SLAVE) && (spi_is_write_complete(module))) {
- /* Clear TX complete flag */
- _spi_clear_tx_complete_flag(module);
- }
-# endif
-
- uint16_t tx_pos = 0;
- uint16_t flush_length = length;
-
- /* Write block */
- while (length--) {
-# if CONF_SPI_SLAVE_ENABLE == true
- /* Start timeout period for slave */
- if (module->mode == SPI_MODE_SLAVE) {
- for (uint32_t i = 0; i <= SPI_TIMEOUT; i++) {
- if (spi_is_ready_to_write(module)) {
- break;
- }
- }
- /* Check if master has ended the transaction */
- if (spi_is_write_complete(module)) {
- _spi_clear_tx_complete_flag(module);
- return STATUS_ABORTED;
- }
-
- if (!spi_is_ready_to_write(module)) {
- /* Not ready to write data within timeout period */
- return STATUS_ERR_TIMEOUT;
- }
- }
-# endif
-
- /* Wait until the module is ready to write a character */
- while (!spi_is_ready_to_write(module)) {
- }
-
- /* Write value will be at least 8-bits long */
- uint16_t data_to_send = tx_data[tx_pos++];
-
- /* If 9-bit data, get next byte to send from the buffer */
- if (module->character_size == SPI_CHARACTER_SIZE_9BIT) {
- data_to_send |= (tx_data[tx_pos++] << 8);
- }
-
- /* Write the data to send */
- spi_write(module, data_to_send);
-
- if (module->receiver_enabled) {
-# if CONF_SPI_SLAVE_ENABLE == true
- /* Start timeout period for slave */
- if (module->mode == SPI_MODE_SLAVE) {
- for (uint32_t i = 0; i <= SPI_TIMEOUT; i++) {
- if (spi_is_ready_to_write(module)) {
- data_to_send = tx_data[tx_pos++];
- /* If 9-bit data, get next byte to send from the buffer */
- if (module->character_size == SPI_CHARACTER_SIZE_9BIT) {
- data_to_send |= (tx_data[tx_pos++] << 8);
- }
-
- /* Write the data to send */
- spi_write(module, data_to_send);
- length--;
- }
- if (spi_is_ready_to_read(module)) {
- break;
- }
- }
-
- /* Check if master has ended the transaction */
- if (spi_is_write_complete(module)) {
- _spi_clear_tx_complete_flag(module);
- return STATUS_ABORTED;
- }
-
- if (!spi_is_ready_to_read(module)) {
- /* Not ready to read data within timeout period */
- return STATUS_ERR_TIMEOUT;
- }
- }
-# endif
-
- while (!spi_is_ready_to_read(module)) {
- }
-
- /* Flush read buffer */
- uint16_t flush;
- spi_read(module, &flush);
- flush_length--;
- }
- }
-
-# if CONF_SPI_MASTER_ENABLE == true
- if (module->mode == SPI_MODE_MASTER) {
- /* Wait for last byte to be transferred */
- while (!spi_is_write_complete(module)) {
- }
- }
-# endif
-
-# if CONF_SPI_SLAVE_ENABLE == true
- if (module->mode == SPI_MODE_SLAVE) {
- if (module->receiver_enabled) {
- while (flush_length) {
- /* Start timeout period for slave */
- for (uint32_t i = 0; i <= SPI_TIMEOUT; i++) {
- if (spi_is_ready_to_read(module)) {
- break;
- }
- }
- if (!spi_is_ready_to_read(module)) {
- /* Not ready to read data within timeout period */
- return STATUS_ERR_TIMEOUT;
- }
- /* Flush read buffer */
- uint16_t flush;
- spi_read(module, &flush);
- flush_length--;
- }
- }
- }
-# endif
- return STATUS_OK;
-}
-
-/**
- * \brief Sends and receives a buffer of \c length SPI characters
- *
- * This function will send and receive a buffer of data via the SPI.
- *
- * In master mode the SPI characters will be sent immediately and the
- * received SPI character will be read as soon as the shifting of the SPI
- * character is complete.
- *
- * In slave mode this function will place the data to be sent into the transmit
- * buffer. It will then block until an SPI master has shifted the complete
- * buffer and the received data is available.
- *
- * \param[in] module Pointer to the software instance struct
- * \param[in] tx_data Pointer to the buffer to transmit
- * \param[out] rx_data Pointer to the buffer where received data will be stored
- * \param[in] length Number of SPI characters to transfer
- *
- * \return Status of the operation.
- * \retval STATUS_OK If the operation was completed
- * \retval STATUS_ERR_INVALID_ARG If invalid argument(s) were provided
- * \retval STATUS_ERR_TIMEOUT If the operation was not completed within the
- * timeout in slave mode
- * \retval STATUS_ERR_DENIED If the receiver is not enabled
- * \retval STATUS_ERR_OVERFLOW If the data is overflown
- */
-enum status_code spi_transceive_buffer_wait(
- struct spi_module *const module,
- uint8_t *tx_data,
- uint8_t *rx_data,
- uint16_t length)
-{
- /* Sanity check arguments */
- Assert(module);
-
-# if SPI_CALLBACK_MODE == true
- if (module->status == STATUS_BUSY) {
- /* Check if the SPI module is busy with a job */
- return STATUS_BUSY;
- }
-# endif
-
- /* Sanity check arguments */
- if (length == 0) {
- return STATUS_ERR_INVALID_ARG;
- }
-
- if (!(module->receiver_enabled)) {
- return STATUS_ERR_DENIED;
- }
-
-# if CONF_SPI_SLAVE_ENABLE == true
- if ((module->mode == SPI_MODE_SLAVE) && (spi_is_write_complete(module))) {
- /* Clear TX complete flag */
- _spi_clear_tx_complete_flag(module);
- }
-# endif
-
- uint16_t tx_pos = 0;
- uint16_t rx_pos = 0;
- uint16_t rx_length = length;
-
- /* Send and receive buffer */
- while (length--) {
-# if CONF_SPI_SLAVE_ENABLE == true
- /* Start timeout period for slave */
- if (module->mode == SPI_MODE_SLAVE) {
- for (uint32_t i = 0; i <= SPI_TIMEOUT; i++) {
- if (spi_is_ready_to_write(module)) {
- break;
- }
- }
- /* Check if master has ended the transaction */
- if (spi_is_write_complete(module)) {
- _spi_clear_tx_complete_flag(module);
- return STATUS_ABORTED;
- }
-
- if (!spi_is_ready_to_write(module)) {
- /* Not ready to write data within timeout period */
- return STATUS_ERR_TIMEOUT;
- }
- }
-# endif
-
- /* Wait until the module is ready to write a character */
- while (!spi_is_ready_to_write(module)) {
- }
-
- /* Write value will be at least 8-bits long */
- uint16_t data_to_send = tx_data[tx_pos++];
-
- /* If 9-bit data, get next byte to send from the buffer */
- if (module->character_size == SPI_CHARACTER_SIZE_9BIT) {
- data_to_send |= (tx_data[tx_pos++] << 8);
- }
-
- /* Write the data to send */
- spi_write(module, data_to_send);
-
-# if CONF_SPI_SLAVE_ENABLE == true
- /* Start timeout period for slave */
- if (module->mode == SPI_MODE_SLAVE) {
- for (uint32_t i = 0; i <= SPI_TIMEOUT; i++) {
- if (spi_is_ready_to_write(module)) {
- data_to_send = tx_data[tx_pos++];
- /* If 9-bit data, get next byte to send from the buffer */
- if (module->character_size == SPI_CHARACTER_SIZE_9BIT) {
- data_to_send |= (tx_data[tx_pos++] << 8);
- }
-
- /* Write the data to send */
- spi_write(module, data_to_send);
- length--;
- }
- if (spi_is_ready_to_read(module)) {
- break;
- }
- }
- /* Check if master has ended the transaction */
- if (spi_is_write_complete(module)) {
- _spi_clear_tx_complete_flag(module);
- return STATUS_ABORTED;
- }
-
- if (!spi_is_ready_to_read(module)) {
- /* Not ready to read data within timeout period */
- return STATUS_ERR_TIMEOUT;
- }
- }
-# endif
-
- /* Wait until the module is ready to read a character */
- while (!spi_is_ready_to_read(module)) {
- }
-
- enum status_code retval;
- uint16_t received_data = 0;
- rx_length--;
-
- retval = spi_read(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 == SPI_CHARACTER_SIZE_9BIT) {
- rx_data[rx_pos++] = (received_data >> 8);
- }
- }
-
-# if CONF_SPI_MASTER_ENABLE == true
- if (module->mode == SPI_MODE_MASTER) {
- /* Wait for last byte to be transferred */
- while (!spi_is_write_complete(module)) {
- }
- }
-# endif
-
-# if CONF_SPI_SLAVE_ENABLE == true
- if (module->mode == SPI_MODE_SLAVE) {
- while (rx_length) {
- /* Start timeout period for slave */
- for (uint32_t i = 0; i <= SPI_TIMEOUT; i++) {
- if (spi_is_ready_to_read(module)) {
- break;
- }
- }
- if (!spi_is_ready_to_read(module)) {
- /* Not ready to read data within timeout period */
- return STATUS_ERR_TIMEOUT;
- }
- enum status_code retval;
- uint16_t received_data = 0;
- rx_length--;
-
- retval = spi_read(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 == SPI_CHARACTER_SIZE_9BIT) {
- rx_data[rx_pos++] = (received_data >> 8);
- }
- }
- }
-# endif
- return STATUS_OK;
-}
diff --git a/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/drivers/sercom/spi/spi.h b/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/drivers/sercom/spi/spi.h
deleted file mode 100644
index 27a7f0869c..0000000000
--- a/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/drivers/sercom/spi/spi.h
+++ /dev/null
@@ -1,1763 +0,0 @@
-/**
- * \file
- *
- * \brief SAM Serial Peripheral Interface Driver
- *
- * Copyright (C) 2012-2014 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 Atmel Support
- */
-
-#ifndef SPI_H_INCLUDED
-#define SPI_H_INCLUDED
-
-/**
- * \defgroup asfdoc_sam0_sercom_spi_group SAM Serial Peripheral Interface Driver (SERCOM SPI)
- *
- * This driver for Atmelåº | SMART SAM devices provides an interface for the configuration
- * and management of the SERCOM module in its SPI mode to transfer SPI data
- * frames. The following driver API modes are covered by this manual:
- *
- * - Polled APIs
- * \if SPI_CALLBACK_MODE
- * - Callback APIs
- * \endif
- *
- * The following peripherals are used by this module:
- * - SERCOM (Serial Communication Interface)
- *
- * The following devices can use this module:
- * - Atmel | SMART SAM D20/D21
- * - Atmel | SMART SAM R21
- * - Atmel | SMART SAM D10/D11
- * - Atmel | SMART SAM L21
- *
- * The outline of this documentation is as follows:
- * - \ref asfdoc_sam0_sercom_spi_prerequisites
- * - \ref asfdoc_sam0_sercom_spi_module_overview
- * - \ref asfdoc_sam0_sercom_spi_special_considerations
- * - \ref asfdoc_sam0_sercom_spi_extra_info
- * - \ref asfdoc_sam0_sercom_spi_examples
- * - \ref asfdoc_sam0_sercom_spi_api_overview
- *
- * \section asfdoc_sam0_sercom_spi_prerequisites Prerequisites
- * There are no prerequisites.
- *
- *
- * \section asfdoc_sam0_sercom_spi_module_overview Module Overview
- * The Serial Peripheral Interface (SPI) is a high-speed synchronous data
- * transfer interface using three or four pins. It allows fast communication
- * between a master device and one or more peripheral devices.
- *
- * A device connected to the bus must act as a master or a slave. The master
- * initiates and controls all data transactions.
- * The SPI master initiates a communication cycle by pulling low the Slave
- * Select (SS) pin of the desired slave. The Slave Select pin is active low.
- * Master and slave prepare data to be sent in their respective shift
- * registers, and the master generates the required clock pulses on the SCK
- * line to interchange data. Data is always shifted from master to slave on
- * the Master Out - Slave In (MOSI) line, and from slave to master on the
- * Master In - Slave Out (MISO) line. After each data transfer, the master can
- * synchronize to the slave by pulling the SS line high.
- *
- * \subsection asfdoc_sam0_sercom_spi_module_features Driver Feature Macro Definition
- *
- *
- * Driver Feature Macro |
- * Supported devices |
- *
- *
- * FEATURE_SPI_SLAVE_SELECT_LOW_DETECT |
- * SAM D21/R21/D10/D11/L21 |
- *
- *
- * FEATURE_SPI_HARDWARE_SLAVE_SELECT |
- * SAM D21/R21/D10/D11/L21 |
- *
- *
- * FEATURE_SPI_ERROR_INTERRUPT |
- * SAM D21/R21/D10/D11/L21 |
- *
- *
- * FEATURE_SPI_SYNC_SCHEME_VERSION_2 |
- * SAM D21/R21/D10/D11/L21 |
- *
- *
- * \note The specific features are only available in the driver when the
- * selected device supports those features.
- *
- * \subsection asfdoc_sam0_sercom_spi_bus SPI Bus Connection
- * In \ref asfdoc_sam0_spi_connection_example "the figure below", the
- * connection between one master and one slave is shown.
- *
- * \anchor asfdoc_sam0_spi_connection_example
- * \dot
- * digraph spi_slaves_par {
- * subgraph cluster_spi_master {
- * shift_reg [label="Shift register", shape=box];
- * mosi_m [label="MOSI", shape=none];
- * miso_m [label="MISO", shape=none];
- * sck_m [label="SCK", shape=none];
- * ss_m [label="GPIO pin", shape=none];
- * {rank=same; mosi_m miso_m sck_m ss_m}
- * label="SPI Master";
- * }
- * subgraph cluster_spi_slave {
- * mosi_s [label="MOSI", shape=none];
- * miso_s [label="MISO", shape=none];
- * sck_s [label="SCK", shape=none];
- * ss_s [label="SS", shape=none];
- * shift_reg_s [label="Shift register", shape=box];
- * {rank=same; mosi_s miso_s sck_s ss_s}
- * label="SPI Slave";
- * rankdir=LR;
- * }
- * shift_reg:e -> mosi_m:w [label=""];
- * mosi_m:e -> mosi_s:w [label=""];
- * mosi_s:e -> shift_reg_s:w [label=""];
- * miso_s:w -> miso_m:e [label=""];
- * sck_m -> sck_s;
- * ss_m -> ss_s;
- * shift_reg_s:se -> miso_s:e [label=""];
- * miso_m:w -> shift_reg:sw [label=""];
- * rankdir=LR;
- * }
- * \enddot
- *
- * The different lines are as follows:
- * - \b MISO Master Input Slave Output. The line where the data is shifted
- * out from the slave and in to the master.
- * - \b MOSI Master Output Slave Input. The line where the data is shifted
- * out from the master and in to the slave.
- * - \b SCK Serial Clock. Generated by the master device.
- * - \b SS Slave Select. To initiate a transaction, the master must pull this
- * line low.
- *
- * If the bus consists of several SPI slaves, they can be connected in parallel
- * and the SPI master can use general I/O pins to control separate SS lines to
- * each slave on the bus.
- *
- * It is also possible to connect all slaves in series. In this configuration,
- * a common SS is provided to \c N slaves, enabling them simultaneously. The
- * MISO from the \c N-1 slaves is connected to the MOSI on the next slave. The
- * \c Nth slave connects its MISO back to the master. For a
- * complete transaction, the master must shift \c N+1 characters.
- *
- * \subsection asfdoc_sam0_sercom_spi_chsize SPI Character Size
- * The SPI character size is configurable to eight or nine bits.
- *
- * \subsection asfdoc_sam0_sercom_spi_master_mode Master Mode
- * When configured as a master, the SS pin will be configured as an output.
- *
- * \subsubsection asfdoc_sam0_sercom_spi_master_mode_data_transfer Data Transfer
- * Writing a character will start the SPI clock generator, and
- * the character is transferred to the shift register when the shift
- * register is empty.
- * Once this is done, a new character can be written.
- * As each character is shifted out from the master, a character is shifted in
- * from the slave. If the receiver is enabled, the data is moved to the receive
- * buffer at the completion of the frame and can be read.
- *
- * \subsection asfdoc_sam0_sercom_spi_slave_mode Slave Mode
- * When configured as a slave, the SPI interface will remain inactive with MISO
- * tri-stated as long as the SS pin is driven high.
- *
- * \subsubsection asfdoc_sam0_sercom_spi_slave_mode_data_transfer_slave Data Transfer
- * The data register can be updated at any time.
- * As the SPI slave shift register is clocked by SCK, a minimum of three SCK
- * cycles are needed from the time new data is written, until the character is
- * ready to be shifted out. If the shift register has not been loaded with
- * data, the current contents will be transmitted.
- *
- * If constant transmission of data is needed in SPI slave mode, the system
- * clock should be faster than SCK.
- * If the receiver is enabled, the received character can be read from the.
- * When SS line is driven high, the slave will not receive any additional data.
- *
- * \subsubsection asfdoc_sam0_sercom_spi_slave_mode_addr_recognition Address Recognition
- * When the SPI slave is configured with address recognition, the first
- * character in a transaction is checked for an address match. If there is a
- * match, the MISO output is enabled and the transaction is processed.
- * If the address does not match, the complete transaction is ignored.
- *
- * If the device is asleep, it can be woken up by an address match in order
- * to process the transaction.
- *
- * \note In master mode, an address packet is written by the
- * \ref spi_select_slave function if the address_enabled configuration is
- * set in the \ref spi_slave_inst_config struct.
- *
- * \subsection asfdoc_sam0_sercom_spi_data_modes Data Modes
- * There are four combinations of SCK phase and polarity with respect to
- * serial data. \ref asfdoc_sam0_spi_mode_table "The table below" shows the
- * clock polarity (CPOL) and clock phase (CPHA) in the different modes.
- * Leading edge is the first clock edge in a clock cycle and
- * trailing edge is the last clock edge in a clock cycle.
- *
- * \anchor asfdoc_sam0_spi_mode_table
- *
- * SPI Data Modes
- *
- * Mode |
- * CPOL |
- * CPHA |
- * Leading Edge |
- * Trailing Edge |
- *
- *
- * 0 |
- * 0 |
- * 0 |
- * Rising, Sample |
- * Falling, Setup |
- *
- *
- * 1 |
- * 0 |
- * 1 |
- * Rising, Setup |
- * Falling, Sample |
- *
- *
- * 2 |
- * 1 |
- * 0 |
- * Falling, Sample |
- * Rising, Setup |
- *
- *
- * 3 |
- * 1 |
- * 1 |
- * Falling, Setup |
- * Rising, Sample |
- *
- *
- *
- *
- * \subsection asfdoc_sam0_sercom_spi_pads SERCOM Pads
- * The SERCOM pads are automatically configured as seen in
- * \ref asfdoc_sam0_spi_sercom_pad_table "the table below". If the receiver
- * is disabled, the data input (MISO for master, MOSI for slave) can be used
- * for other purposes.
- *
- * In master mode, the SS pin(s) must be configured using the \ref spi_slave_inst
- * struct.
- *
- * \anchor asfdoc_sam0_spi_sercom_pad_table
- *
- * SERCOM SPI Pad Usages
- *
- * Pin |
- * Master SPI |
- * Slave SPI |
- *
- *
- * MOSI |
- * Output |
- * Input |
- *
- *
- * MISO |
- * Input |
- * Output |
- *
- *
- * SCK |
- * Output |
- * Input |
- *
- *
- * SS |
- * User defined output enable |
- * Input |
- *
- *
- *
- * \subsection asfdoc_sam0_sercom_spi_sleep_modes Operation in Sleep Modes
- * The SPI module can operate in all sleep modes by setting the run_in_standby
- * option in the \ref spi_config struct. The operation in slave and master mode
- * is shown in the table below.
- *
- *
- * run_in_standby |
- * Slave |
- * Master |
- *
- *
- * false |
- * Disabled, all reception is dropped |
- * GCLK disabled when master is idle, wake on transmit complete |
- *
- *
- * true |
- * Wake on reception |
- * GCLK is enabled while in sleep modes, wake on all interrupts |
- *
- *
- *
- * \subsection asfdoc_sam0_sercom_spi_clock_generation Clock Generation
- * In SPI master mode, the clock (SCK) is generated internally using the
- * SERCOM baudrate generator. In SPI slave mode, the clock is provided by
- * an external master on the SCK pin. This clock is used to directly clock
- * the SPI shift register.
- *
- * \section asfdoc_sam0_sercom_spi_special_considerations Special Considerations
- * \subsection pin_mux pinmux Settings
- * The pin MUX settings must be configured properly, as not all settings
- * can be used in different modes of operation.
- *
- * \section asfdoc_sam0_sercom_spi_extra_info Extra Information
- * For extra information, see \ref asfdoc_sam0_sercom_spi_extra. This includes:
- * - \ref asfdoc_sam0_sercom_spi_extra_acronyms
- * - \ref asfdoc_sam0_sercom_spi_extra_dependencies
- * - \ref asfdoc_sam0_sercom_spi_extra_workarounds
- * - \ref asfdoc_sam0_sercom_spi_extra_history
- *
- * \section asfdoc_sam0_sercom_spi_examples Examples
- *
- * For a list of examples related to this driver, see
- * \ref asfdoc_sam0_sercom_spi_exqsg.
- *
- * \section asfdoc_sam0_sercom_spi_api_overview API Overview
- * @{
- */
-
-#include
-#include
-#include
-#include
-#include
-#include
-
-# if SPI_CALLBACK_MODE == true
-# include
-# endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#if (CONF_SPI_MASTER_ENABLE == false) && (CONF_SPI_SLAVE_ENABLE == false)
-#error "Not possible compile SPI driver, invalid driver configuration. Make sure that either/both CONF_SPI_MASTER_ENABLE/CONF_SPI_SLAVE_ENABLE is set to true."
-#endif
-
-/**
- * \name Driver Feature Definition
- * Define SERCOM SPI features set according to different device family.
- * @{
- */
-# if (SAMD21) || (SAMR21) || (SAMD11) || (SAMD10) || (SAML21) || defined(__DOXYGEN__)
-/** SPI slave select low detection. */
-# define FEATURE_SPI_SLAVE_SELECT_LOW_DETECT
-/** Slave select can be controlled by hardware. */
-# define FEATURE_SPI_HARDWARE_SLAVE_SELECT
-/** SPI with error detect feature. */
-# define FEATURE_SPI_ERROR_INTERRUPT
-/** SPI sync scheme version 2. */
-# define FEATURE_SPI_SYNC_SCHEME_VERSION_2
-# endif
-/*@}*/
-
-# ifndef PINMUX_DEFAULT
-/** Default pinmux. */
-# define PINMUX_DEFAULT 0
-# endif
-
-# ifndef PINMUX_UNUSED
-/** Unused pinmux. */
-# define PINMUX_UNUSED 0xFFFFFFFF
-# endif
-
-# ifndef SPI_TIMEOUT
-/** SPI timeout value. */
-# define SPI_TIMEOUT 10000
-# endif
-
-# if SPI_CALLBACK_MODE == true
-/**
- * \brief SPI Callback enum
- *
- * Callbacks for SPI callback driver.
- *
- * \note For slave mode, these callbacks will be called when a transaction
- * is ended by the master pulling Slave Select high.
- *
- */
-enum spi_callback {
- /** Callback for buffer transmitted. */
- SPI_CALLBACK_BUFFER_TRANSMITTED,
- /** Callback for buffer received. */
- SPI_CALLBACK_BUFFER_RECEIVED,
- /** Callback for buffers transceived. */
- SPI_CALLBACK_BUFFER_TRANSCEIVED,
- /** Callback for error. */
- SPI_CALLBACK_ERROR,
- /**
- * Callback for transmission ended by master before entire buffer was
- * read or written from slave.
- */
- SPI_CALLBACK_SLAVE_TRANSMISSION_COMPLETE,
-# ifdef FEATURE_SPI_SLAVE_SELECT_LOW_DETECT
- /** Callback for slave select low. */
- SPI_CALLBACK_SLAVE_SELECT_LOW,
-# endif
-# ifdef FEATURE_SPI_ERROR_INTERRUPT
- /** Callback for combined error happen. */
- SPI_CALLBACK_COMBINED_ERROR,
-# endif
-# if !defined(__DOXYGEN__)
- /** Number of available callbacks. */
- SPI_CALLBACK_N,
-# endif
-};
-# endif
-
-#if SPI_CALLBACK_MODE == true
-# if !defined(__DOXYGEN__)
-/**
- * \internal SPI transfer directions
- */
-enum _spi_direction {
- /** Transfer direction is read. */
- SPI_DIRECTION_READ,
- /** Transfer direction is write. */
- SPI_DIRECTION_WRITE,
- /** Transfer direction is read and write. */
- SPI_DIRECTION_BOTH,
- /** No transfer. */
- SPI_DIRECTION_IDLE,
-};
-# endif
-#endif
-
-/**
- * \brief SPI Interrupt Flags
- *
- * Interrupt flags for the SPI module.
- *
- */
-enum spi_interrupt_flag {
- /**
- * This flag is set when the contents of the data register has been moved
- * to the shift register and the data register is ready for new data.
- */
- SPI_INTERRUPT_FLAG_DATA_REGISTER_EMPTY = SERCOM_SPI_INTFLAG_DRE,
- /**
- * This flag is set when the contents of the shift register has been
- * shifted out.
- */
- SPI_INTERRUPT_FLAG_TX_COMPLETE = SERCOM_SPI_INTFLAG_TXC,
- /** This flag is set when data has been shifted into the data register. */
- SPI_INTERRUPT_FLAG_RX_COMPLETE = SERCOM_SPI_INTFLAG_RXC,
-# ifdef FEATURE_SPI_SLAVE_SELECT_LOW_DETECT
- /** This flag is set when slave select low. */
- SPI_INTERRUPT_FLAG_SLAVE_SELECT_LOW = SERCOM_SPI_INTFLAG_SSL,
-# endif
-# ifdef FEATURE_SPI_ERROR_INTERRUPT
- /** This flag is set when combined error happen. */
- SPI_INTERRUPT_FLAG_COMBINED_ERROR = SERCOM_SPI_INTFLAG_ERROR,
-# endif
-};
-
-/**
- * \brief SPI transfer modes enum
- *
- * SPI transfer mode.
- */
-enum spi_transfer_mode {
- /** Mode 0. Leading edge: rising, sample. Trailing edge: falling, setup. */
- SPI_TRANSFER_MODE_0 = 0,
- /** Mode 1. Leading edge: rising, setup. Trailing edge: falling, sample. */
- SPI_TRANSFER_MODE_1 = SERCOM_SPI_CTRLA_CPHA,
- /** Mode 2. Leading edge: falling, sample. Trailing edge: rising, setup. */
- SPI_TRANSFER_MODE_2 = SERCOM_SPI_CTRLA_CPOL,
- /** Mode 3. Leading edge: falling, setup. Trailing edge: rising, sample. */
- SPI_TRANSFER_MODE_3 = SERCOM_SPI_CTRLA_CPHA | SERCOM_SPI_CTRLA_CPOL,
-};
-
-/**
- * \brief SPI frame format enum
- *
- * Frame format for slave mode.
- */
-enum spi_frame_format {
- /** SPI frame. */
- SPI_FRAME_FORMAT_SPI_FRAME = SERCOM_SPI_CTRLA_FORM(0),
- /** SPI frame with address. */
- SPI_FRAME_FORMAT_SPI_FRAME_ADDR = SERCOM_SPI_CTRLA_FORM(2),
-};
-
-/**
- * \brief SPI signal MUX settings
- *
- * Set the functionality of the SERCOM pins.
- * As not all settings can be used in different modes of operation, proper
- * settings must be chosen according to the rest of the configuration.
- *
- * See \ref asfdoc_sam0_sercom_spi_mux_settings for a description of the
- * various MUX setting options.
- */
-enum spi_signal_mux_setting {
- /** SPI MUX setting A. */
- SPI_SIGNAL_MUX_SETTING_A =
- (0x0 << SERCOM_SPI_CTRLA_DOPO_Pos) |
- (0x0 << SERCOM_SPI_CTRLA_DIPO_Pos),
- /** SPI MUX setting B. */
- SPI_SIGNAL_MUX_SETTING_B =
- (0x0 << SERCOM_SPI_CTRLA_DOPO_Pos) |
- (0x1 << SERCOM_SPI_CTRLA_DIPO_Pos),
- /** SPI MUX setting C. */
- SPI_SIGNAL_MUX_SETTING_C =
- (0x0 << SERCOM_SPI_CTRLA_DOPO_Pos) |
- (0x2 << SERCOM_SPI_CTRLA_DIPO_Pos),
- /** SPI MUX setting D. */
- SPI_SIGNAL_MUX_SETTING_D =
- (0x0 << SERCOM_SPI_CTRLA_DOPO_Pos) |
- (0x3 << SERCOM_SPI_CTRLA_DIPO_Pos),
- /** SPI MUX setting E. */
- SPI_SIGNAL_MUX_SETTING_E =
- (0x1 << SERCOM_SPI_CTRLA_DOPO_Pos) |
- (0x0 << SERCOM_SPI_CTRLA_DIPO_Pos),
- /** SPI MUX setting F. */
- SPI_SIGNAL_MUX_SETTING_F =
- (0x1 << SERCOM_SPI_CTRLA_DOPO_Pos) |
- (0x1 << SERCOM_SPI_CTRLA_DIPO_Pos),
- /** SPI MUX setting G. */
- SPI_SIGNAL_MUX_SETTING_G =
- (0x1 << SERCOM_SPI_CTRLA_DOPO_Pos) |
- (0x2 << SERCOM_SPI_CTRLA_DIPO_Pos),
- /** SPI MUX setting H. */
- SPI_SIGNAL_MUX_SETTING_H =
- (0x1 << SERCOM_SPI_CTRLA_DOPO_Pos) |
- (0x3 << SERCOM_SPI_CTRLA_DIPO_Pos),
- /** SPI MUX setting I. */
- SPI_SIGNAL_MUX_SETTING_I =
- (0x2 << SERCOM_SPI_CTRLA_DOPO_Pos) |
- (0x0 << SERCOM_SPI_CTRLA_DIPO_Pos),
- /** SPI MUX setting J. */
- SPI_SIGNAL_MUX_SETTING_J =
- (0x2 << SERCOM_SPI_CTRLA_DOPO_Pos) |
- (0x1 << SERCOM_SPI_CTRLA_DIPO_Pos),
- /** SPI MUX setting K. */
- SPI_SIGNAL_MUX_SETTING_K =
- (0x2 << SERCOM_SPI_CTRLA_DOPO_Pos) |
- (0x2 << SERCOM_SPI_CTRLA_DIPO_Pos),
- /** SPI MUX setting L. */
- SPI_SIGNAL_MUX_SETTING_L =
- (0x2 << SERCOM_SPI_CTRLA_DOPO_Pos) |
- (0x3 << SERCOM_SPI_CTRLA_DIPO_Pos),
- /** SPI MUX setting M. */
- SPI_SIGNAL_MUX_SETTING_M =
- (0x3 << SERCOM_SPI_CTRLA_DOPO_Pos) |
- (0x0 << SERCOM_SPI_CTRLA_DIPO_Pos),
- /** SPI MUX setting N. */
- SPI_SIGNAL_MUX_SETTING_N =
- (0x3 << SERCOM_SPI_CTRLA_DOPO_Pos) |
- (0x1 << SERCOM_SPI_CTRLA_DIPO_Pos),
- /** SPI MUX setting O. */
- SPI_SIGNAL_MUX_SETTING_O =
- (0x3 << SERCOM_SPI_CTRLA_DOPO_Pos) |
- (0x2 << SERCOM_SPI_CTRLA_DIPO_Pos),
- /** SPI MUX setting P. */
- SPI_SIGNAL_MUX_SETTING_P =
- (0x3 << SERCOM_SPI_CTRLA_DOPO_Pos) |
- (0x3 << SERCOM_SPI_CTRLA_DIPO_Pos),
-};
-
-/**
- * \brief SPI address modes enum
- *
- * For slave mode when using the SPI frame with address format.
- *
- */
-enum spi_addr_mode {
- /**
- * \c address_mask in the \ref spi_config struct is used as a mask to the register.
- */
- SPI_ADDR_MODE_MASK = SERCOM_SPI_CTRLB_AMODE(0),
- /**
- * The slave responds to the two unique addresses in \c address and
- * \c address_mask in the \ref spi_config struct.
- */
- SPI_ADDR_MODE_UNIQUE = SERCOM_SPI_CTRLB_AMODE(1),
- /**
- * The slave responds to the range of addresses between and including \c address
- * and \c address_mask in in the \ref spi_config struct.
- */
- SPI_ADDR_MODE_RANGE = SERCOM_SPI_CTRLB_AMODE(2),
-};
-
-/**
- * \brief SPI modes enum
- *
- * SPI mode selection.
- */
-enum spi_mode {
- /** Master mode. */
- SPI_MODE_MASTER = 1,
- /** Slave mode. */
- SPI_MODE_SLAVE = 0,
-};
-
-/**
- * \brief SPI data order enum
- *
- * SPI data order.
- *
- */
-enum spi_data_order {
- /** The LSB of the data is transmitted first. */
- SPI_DATA_ORDER_LSB = SERCOM_SPI_CTRLA_DORD,
- /** The MSB of the data is transmitted first. */
- SPI_DATA_ORDER_MSB = 0,
-};
-
-/**
- * \brief SPI character size enum
- *
- * SPI character size.
- *
- */
-enum spi_character_size {
- /** 8-bit character. */
- SPI_CHARACTER_SIZE_8BIT = SERCOM_SPI_CTRLB_CHSIZE(0),
- /** 9-bit character. */
- SPI_CHARACTER_SIZE_9BIT = SERCOM_SPI_CTRLB_CHSIZE(1),
-};
-
-# if SPI_CALLBACK_MODE == true
-/** Prototype for the device instance. */
-struct spi_module;
-
-/** Type of the callback functions. */
-typedef void (*spi_callback_t)(const struct spi_module *const module);
-
-# if !defined(__DOXYGEN__)
-/** Prototype for the interrupt handler. */
-extern void _spi_interrupt_handler(uint8_t instance);
-# endif
-# endif
-
-/**
- * \brief SERCOM SPI driver software device instance structure.
- *
- * SERCOM SPI driver software instance structure, used to retain software state
- * information of an associated hardware module instance.
- *
- * \note The fields of this structure should not be altered by the user
- * application; they are reserved for module-internal use only.
- */
-struct spi_module {
-# if !defined(__DOXYGEN__)
- /** SERCOM hardware module. */
- Sercom *hw;
- /** Module lock. */
- volatile bool locked;
- /** SPI mode. */
- enum spi_mode mode;
- /** SPI character size. */
- enum spi_character_size character_size;
- /** Receiver enabled. */
- bool receiver_enabled;
-# ifdef FEATURE_SPI_HARDWARE_SLAVE_SELECT
- /** Enable Hardware Slave Select. */
- bool master_slave_select_enable;
-# endif
-# if SPI_CALLBACK_MODE == true
- /** Direction of transaction. */
- volatile enum _spi_direction dir;
- /** Array to store callback function pointers in. */
- spi_callback_t callback[SPI_CALLBACK_N];
- /** Buffer pointer to where the next received character will be put. */
- volatile uint8_t *rx_buffer_ptr;
- /** Buffer pointer to where the next character will be transmitted from.
- **/
- volatile uint8_t *tx_buffer_ptr;
- /** Remaining characters to receive. */
- volatile uint16_t remaining_rx_buffer_length;
- /** Remaining dummy characters to send when reading. */
- volatile uint16_t remaining_dummy_buffer_length;
- /** Remaining characters to transmit. */
- volatile uint16_t remaining_tx_buffer_length;
- /** Bit mask for callbacks registered. */
- uint8_t registered_callback;
- /** Bit mask for callbacks enabled. */
- uint8_t enabled_callback;
- /** Holds the status of the ongoing or last operation. */
- volatile enum status_code status;
-# endif
-# endif
-};
-
-/**
- * \brief SPI peripheral slave instance structure
- *
- * SPI peripheral slave software instance structure, used to configure the
- * correct SPI transfer mode settings for an attached slave. See
- * \ref spi_select_slave.
- */
-struct spi_slave_inst {
- /** Pin to use as Slave Select. */
- uint8_t ss_pin;
- /** Address recognition enabled in slave device. */
- bool address_enabled;
- /** Address of slave device. */
- uint8_t address;
-};
-
-/**
- * \brief SPI peripheral slave configuration structure
- *
- * SPI Peripheral slave configuration structure.
- */
-struct spi_slave_inst_config {
- /** Pin to use as Slave Select. */
- uint8_t ss_pin;
- /** Enable address. */
- bool address_enabled;
- /** Address of slave. */
- uint8_t address;
-};
-
-/**
- * \brief SPI Master configuration structure
- *
- * SPI Master configuration structure.
- */
-struct spi_master_config {
- /** Baud rate. */
- uint32_t baudrate;
-};
-
-/**
- * \brief SPI slave configuration structure
- *
- * SPI slave configuration structure.
- */
-struct spi_slave_config {
- /** Frame format. */
- enum spi_frame_format frame_format;
- /** Address mode. */
- enum spi_addr_mode address_mode;
- /** Address. */
- uint8_t address;
- /** Address mask. */
- uint8_t address_mask;
- /** Preload data to the shift register while SS is high. */
- bool preload_enable;
-};
-
-/**
- * \brief SPI configuration structure
- *
- * Configuration structure for an SPI instance. This structure should be
- * initialized by the \ref spi_get_config_defaults function before being
- * modified by the user application.
- */
-struct spi_config {
- /** SPI mode. */
- enum spi_mode mode;
- /** Data order. */
- enum spi_data_order data_order;
- /** Transfer mode. */
- enum spi_transfer_mode transfer_mode;
- /** MUX setting. */
- enum spi_signal_mux_setting mux_setting;
- /** SPI character size. */
- enum spi_character_size character_size;
- /** Enabled in sleep modes. */
- bool run_in_standby;
- /** Enable receiver. */
- bool receiver_enable;
-# ifdef FEATURE_SPI_SLAVE_SELECT_LOW_DETECT
- /** Enable Slave Select Low Detect. */
- bool select_slave_low_detect_enable;
-# endif
-# ifdef FEATURE_SPI_HARDWARE_SLAVE_SELECT
- /** Enable Master Slave Select. */
- bool master_slave_select_enable;
-# endif
- /** Union for slave or master specific configuration. */
- union {
- /** Slave specific configuration. */
- struct spi_slave_config slave;
- /** Master specific configuration. */
- struct spi_master_config master;
- } mode_specific;
- /** GCLK generator to use as clock source. */
- enum gclk_generator generator_source;
- /** PAD0 pinmux. */
- uint32_t pinmux_pad0;
- /** PAD1 pinmux. */
- uint32_t pinmux_pad1;
- /** PAD2 pinmux. */
- uint32_t pinmux_pad2;
- /** PAD3 pinmux. */
- uint32_t pinmux_pad3;
-};
-
-/**
- * \brief Determines if the SPI module is currently synchronizing to the bus.
- *
- * This function will check if the underlying hardware peripheral module is
- * currently synchronizing across multiple clock domains to the hardware bus.
- * This function can be used to delay further operations on the module until it
- * is ready.
- *
- * \param[in] module SPI hardware module
- *
- * \return Synchronization status of the underlying hardware module.
- * \retval true Module synchronization is ongoing
- * \retval false Module synchronization is not ongoing
- *
- */
-static inline bool spi_is_syncing(
- struct spi_module *const module)
-{
- /* Sanity check arguments */
- Assert(module);
- Assert(module->hw);
-
- SercomSpi *const spi_module = &(module->hw->SPI);
-
-# ifdef FEATURE_SPI_SYNC_SCHEME_VERSION_2
- /* Return synchronization status */
- return (spi_module->SYNCBUSY.reg);
-# else
- /* Return synchronization status */
- return (spi_module->STATUS.reg & SERCOM_SPI_STATUS_SYNCBUSY);
-# endif
-}
-
-/**
- * \name Driver Initialization and Configuration
- * @{
- */
-
-/**
- * \brief Initializes an SPI configuration structure to default values
- *
- * This function will initialize a given SPI configuration structure to a set
- * of known default values. This function should be called on any new
- * instance of the configuration structures before being modified by the
- * user application.
- *
- * The default configuration is as follows:
- * \li Master mode enabled
- * \li MSB of the data is transmitted first
- * \li Transfer mode 0
- * \li MUX Setting D
- * \li Character size eight bits
- * \li Not enabled in sleep mode
- * \li Receiver enabled
- * \li Baudrate 100000
- * \li Default pinmux settings for all pads
- * \li GCLK generator 0
- *
- * \param[out] config Configuration structure to initialize to default values
- */
-static inline void spi_get_config_defaults(
- struct spi_config *const config)
-{
- /* Sanity check arguments */
- Assert(config);
-
- /* Default configuration values */
- config->mode = SPI_MODE_MASTER;
- config->data_order = SPI_DATA_ORDER_MSB;
- config->transfer_mode = SPI_TRANSFER_MODE_0;
- config->mux_setting = SPI_SIGNAL_MUX_SETTING_D;
- config->character_size = SPI_CHARACTER_SIZE_8BIT;
- config->run_in_standby = false;
- config->receiver_enable = true;
-# ifdef FEATURE_SPI_SLAVE_SELECT_LOW_DETECT
- config->select_slave_low_detect_enable= true;
-# endif
-# ifdef FEATURE_SPI_HARDWARE_SLAVE_SELECT
- config->master_slave_select_enable= false;
-# endif
- config->generator_source = GCLK_GENERATOR_0;
-
- /* Clear mode specific config */
- memset(&(config->mode_specific), 0, sizeof(config->mode_specific));
-
- /* Master config defaults */
- config->mode_specific.master.baudrate = 100000;
-
- /* pinmux config defaults */
- config->pinmux_pad0 = PINMUX_DEFAULT;
- config->pinmux_pad1 = PINMUX_DEFAULT;
- config->pinmux_pad2 = PINMUX_DEFAULT;
- config->pinmux_pad3 = PINMUX_DEFAULT;
-
-};
-
-/**
- * \brief Initializes an SPI peripheral slave device configuration structure to default values
- *
- * This function will initialize a given SPI slave device configuration
- * structure to a set of known default values. This function should be called
- * on any new instance of the configuration structures before being modified by
- * the user application.
- *
- * The default configuration is as follows:
- * \li Slave Select on GPIO pin 10
- * \li Addressing not enabled
- *
- * \param[out] config Configuration structure to initialize to default values
- */
-static inline void spi_slave_inst_get_config_defaults(
- struct spi_slave_inst_config *const config)
-{
- Assert(config);
-
- config->ss_pin = 10;
- config->address_enabled = false;
- config->address = 0;
-}
-
-/**
- * \brief Attaches an SPI peripheral slave
- *
- * This function will initialize the software SPI peripheral slave, based on
- * the values of the config struct. The slave can then be selected and
- * optionally addressed by the \ref spi_select_slave function.
- *
- * \param[out] slave Pointer to the software slave instance struct
- * \param[in] config Pointer to the config struct
- *
- */
-static inline void spi_attach_slave(
- struct spi_slave_inst *const slave,
- struct spi_slave_inst_config *const config)
-{
- Assert(slave);
- Assert(config);
-
- slave->ss_pin = config->ss_pin;
- slave->address_enabled = config->address_enabled;
- slave->address = config->address;
-
- /* Get default config for pin */
- struct port_config pin_conf;
- port_get_config_defaults(&pin_conf);
-
- /* Edit config to set the pin as output */
- pin_conf.direction = PORT_PIN_DIR_OUTPUT;
-
- /* Set config on Slave Select pin */
- port_pin_set_config(slave->ss_pin, &pin_conf);
- port_pin_set_output_level(slave->ss_pin, true);
-}
-
-enum status_code spi_init(
- struct spi_module *const module,
- Sercom *const hw,
- const struct spi_config *const config);
-
-/** @} */
-
-/**
- * \name Enable/Disable
- * @{
- */
-
-/**
- * \brief Enables the SERCOM SPI module
- *
- * This function will enable the SERCOM SPI module.
- *
- * \param[in,out] module Pointer to the software instance struct
- */
-static inline void spi_enable(
- struct spi_module *const module)
-{
- /* Sanity check arguments */
- Assert(module);
- Assert(module->hw);
-
- SercomSpi *const spi_module = &(module->hw->SPI);
-
-# if SPI_CALLBACK_MODE == true
- system_interrupt_enable(_sercom_get_interrupt_vector(module->hw));
-# endif
-
- while (spi_is_syncing(module)) {
- /* Wait until the synchronization is complete */
- }
-
- /* Enable SPI */
- spi_module->CTRLA.reg |= SERCOM_SPI_CTRLA_ENABLE;
-}
-
-/**
- * \brief Disables the SERCOM SPI module
- *
- * This function will disable the SERCOM SPI module.
- *
- * \param[in,out] module Pointer to the software instance struct
- */
-static inline void spi_disable(
- struct spi_module *const module)
-{
- /* Sanity check arguments */
- Assert(module);
- Assert(module->hw);
-
- SercomSpi *const spi_module = &(module->hw->SPI);
-
-# if SPI_CALLBACK_MODE == true
- system_interrupt_disable(_sercom_get_interrupt_vector(module->hw));
-# endif
-
- while (spi_is_syncing(module)) {
- /* Wait until the synchronization is complete */
- }
-
- /* Disable SPI */
- spi_module->CTRLA.reg &= ~SERCOM_SPI_CTRLA_ENABLE;
-}
-
-void spi_reset(
- struct spi_module *const module);
-
-/** @} */
-
-enum status_code spi_set_baudrate(
- struct spi_module *const module,
- uint32_t baudrate);
-
-/**
- * \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_lock(struct spi_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
- *
- * \retval STATUS_OK if the module was locked
- * \retval STATUS_BUSY if the module was already locked
- */
-static inline void spi_unlock(struct spi_module *const module)
-{
- module->locked = false;
-}
-
-/** @} */
-
-/**
- * \name Ready to Write/Read
- * @{
- */
-
- /**
- * \brief Checks if the SPI in master mode has shifted out last data, or if the master has ended the transfer in slave mode.
- *
- * This function will check if the SPI master module has shifted out last data,
- * or if the slave select pin has been drawn high by the master for the SPI
- * slave module.
- *
- * \param[in] module Pointer to the software instance struct
- *
- * \return Indication of whether any writes are ongoing.
- * \retval true If the SPI master module has shifted out data, or slave select
- * has been drawn high for SPI slave
- * \retval false If the SPI master module has not shifted out data
- */
-static inline bool spi_is_write_complete(
- struct spi_module *const module)
-{
- /* Sanity check arguments */
- Assert(module);
- Assert(module->hw);
-
- SercomSpi *const spi_module = &(module->hw->SPI);
-
- /* Check interrupt flag */
- return (spi_module->INTFLAG.reg & SERCOM_SPI_INTFLAG_TXC);
-}
-
- /**
- * \brief Checks if the SPI module is ready to write data
- *
- * This function will check if the SPI module is ready to write data.
- *
- * \param[in] module Pointer to the software instance struct
- *
- * \return Indication of whether the module is ready to read data or not.
- * \retval true If the SPI module is ready to write data
- * \retval false If the SPI module is not ready to write data
- */
-static inline bool spi_is_ready_to_write(
- struct spi_module *const module)
-{
- /* Sanity check arguments */
- Assert(module);
- Assert(module->hw);
-
- SercomSpi *const spi_module = &(module->hw->SPI);
-
- /* Check interrupt flag */
- return (spi_module->INTFLAG.reg & SERCOM_SPI_INTFLAG_DRE);
-}
-
-/**
- * \brief Checks if the SPI module is ready to read data
- *
- * This function will check if the SPI module is ready to read data.
- *
- * \param[in] module Pointer to the software instance struct
- *
- * \return Indication of whether the module is ready to read data or not.
- * \retval true If the SPI module is ready to read data
- * \retval false If the SPI module is not ready to read data
- */
-static inline bool spi_is_ready_to_read(
- struct spi_module *const module)
-{
- /* Sanity check arguments */
- Assert(module);
- Assert(module->hw);
-
- SercomSpi *const spi_module = &(module->hw->SPI);
-
- /* Check interrupt flag */
- return (spi_module->INTFLAG.reg & SERCOM_SPI_INTFLAG_RXC);
-}
-/** @} */
-
-/**
- * \name Read/Write
- * @{
- */
-
- /**
- * \brief Transfers a single SPI character
- *
- * This function will send a single SPI character via SPI and ignore any data
- * shifted in by the connected device. To both send and receive data, use the
- * \ref spi_transceive_wait function or use the \ref spi_read function after
- * writing a character. The \ref spi_is_ready_to_write function
- * should be called before calling this function.
- *
- * Note that this function does not handle the SS (Slave Select)
- * pin(s) in master mode; this must be handled from the user application.
- *
- * \note In slave mode, the data will not be transferred before a master
- * initiates a transaction.
- *
- * \param[in] module Pointer to the software instance struct
- * \param[in] tx_data Data to transmit
- *
- * \return Status of the procedure.
- * \retval STATUS_OK If the data was written
- * \retval STATUS_BUSY If the last write was not completed
- */
-static inline enum status_code spi_write(
- struct spi_module *module,
- uint16_t tx_data)
-{
- /* Sanity check arguments */
- Assert(module);
- Assert(module->hw);
-
- SercomSpi *const spi_module = &(module->hw->SPI);
-
- /* Check if the data register has been copied to the shift register */
- if (!spi_is_ready_to_write(module)) {
- /* Data register has not been copied to the shift register, return */
- return STATUS_BUSY;
- }
-
- /* Write the character to the DATA register */
- spi_module->DATA.reg = tx_data & SERCOM_SPI_DATA_MASK;
-
- return STATUS_OK;
-}
-
-enum status_code spi_write_buffer_wait(
- struct spi_module *const module,
- const uint8_t *tx_data,
- uint16_t length);
-
-/**
- * \brief Reads last received SPI character
- *
- * This function will return the last SPI character shifted into the receive
- * register by the \ref spi_write function.
- *
- * \note The \ref spi_is_ready_to_read function should be called before calling
- * this function.
- *
- * \note Receiver must be enabled in the configuration.
- *
- * \param[in] module Pointer to the software instance struct
- * \param[out] rx_data Pointer to store the received data
- *
- * \returns Status of the read operation.
- * \retval STATUS_OK If data was read
- * \retval STATUS_ERR_IO If no data is available
- * \retval STATUS_ERR_OVERFLOW If the data is overflown
- */
-static inline enum status_code spi_read(
- struct spi_module *const module,
- uint16_t *rx_data)
-{
- /* Sanity check arguments */
- Assert(module);
- Assert(module->hw);
-
- SercomSpi *const spi_module = &(module->hw->SPI);
-
- /* Check if data is ready to be read */
- if (!spi_is_ready_to_read(module)) {
- /* No data has been received, return */
- return STATUS_ERR_IO;
- }
-
- /* Return value */
- enum status_code retval = STATUS_OK;
-
- /* Check if data is overflown */
- if (spi_module->STATUS.reg & SERCOM_SPI_STATUS_BUFOVF) {
- retval = STATUS_ERR_OVERFLOW;
- /* Clear overflow flag */
- spi_module->STATUS.reg |= SERCOM_SPI_STATUS_BUFOVF;
- }
-
- /* Read the character from the DATA register */
- if (module->character_size == SPI_CHARACTER_SIZE_9BIT) {
- *rx_data = (spi_module->DATA.reg & SERCOM_SPI_DATA_MASK);
- } else {
- *rx_data = (uint8_t)spi_module->DATA.reg;
- }
-
- return retval;
-}
-
-enum status_code spi_read_buffer_wait(
- struct spi_module *const module,
- uint8_t *rx_data,
- uint16_t length,
- uint16_t dummy);
-
-enum status_code spi_transceive_wait(
- struct spi_module *const module,
- uint16_t tx_data,
- uint16_t *rx_data);
-
-enum status_code spi_transceive_buffer_wait(
- struct spi_module *const module,
- uint8_t *tx_data,
- uint8_t *rx_data,
- uint16_t length);
-
-enum status_code spi_select_slave(
- struct spi_module *const module,
- struct spi_slave_inst *const slave,
- bool select);
-
-/** @} */
-
-#ifdef __cplusplus
-}
-#endif
-
-/** @} */
-
-
-/**
- * \page asfdoc_sam0_sercom_spi_extra Extra Information for SERCOM SPI Driver
- *
- * \section asfdoc_sam0_sercom_spi_extra_acronyms Acronyms
- * Below is a table listing the acronyms used in this module, along with their
- * intended meanings.
- *
- *
- *
- * Acronym |
- * Description |
- *
- *
- * SERCOM |
- * Serial Communication Interface |
- *
- *
- * SPI |
- * Serial Peripheral Interface |
- *
- *
- * SCK |
- * Serial Clock |
- *
- *
- * MOSI |
- * Master Output Slave Input |
- *
- *
- * MISO |
- * Master Input Slave Output |
- *
- *
- * SS |
- * Slave Select |
- *
- *
- * DIO |
- * Data Input Output |
- *
- *
- * DO |
- * Data Output |
- *
- *
- * DI |
- * Data Input |
- *
- *
- * DMA |
- * Direct Memory Access |
- *
- *
- *
- * \section asfdoc_sam0_sercom_spi_extra_dependencies Dependencies
- * The SPI driver has the following dependencies:
- * \li \ref asfdoc_sam0_system_pinmux_group "System Pin Multiplexer Driver"
- *
- *
- * \section asfdoc_sam0_sercom_spi_extra_workarounds Workarounds Implemented by Driver
- * No workarounds in driver.
- *
- * \section asfdoc_sam0_sercom_spi_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.
- *
- *
- *
- * Changelog |
- *
- *
- * Add SAML21 support |
- *
- *
- * Add SAMD21 support and added new features as below:
- * \li Slave select low detect
- * \li Hardware slave select
- * \li DMA support |
- *
- *
- * Edited slave part of write and transceive buffer functions to ensure
- * that second character is sent at the right time |
- *
- *
- * Renamed the anonymous union in \c struct spi_config to
- * \c mode_specific |
- *
- *
- * Initial Release |
- *
- *
- */
-
-/**
- * \page asfdoc_sam0_sercom_spi_exqsg Examples for SERCOM SPI Driver
- *
- * This is a list of the available Quick Start guides (QSGs) and example
- * applications for \ref asfdoc_sam0_sercom_spi_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_basic_use
- * - \subpage asfdoc_sam0_sercom_spi_slave_basic_use
- * \if SPI_CALLBACK_MODE
- * - \subpage asfdoc_sam0_sercom_spi_master_callback_use
- * - \subpage asfdoc_sam0_sercom_spi_slave_callback_use
- * \endif
- * - \subpage asfdoc_sam0_sercom_spi_dma_use_case
- */
-
- /**
- * \page asfdoc_sam0_sercom_spi_mux_settings MUX Settings
- *
- * The following lists the possible internal SERCOM module pad function
- * assignments, for the four SERCOM pads in both SPI Master, and SPI Slave
- * modes. Note that this is in addition to the physical GPIO pin MUX of the
- * device, and can be used in conjunction to optimize the serial data pin-out.
- *
- * \section asfdoc_sam0_sercom_spi_mux_settings_master Master Mode Settings
- * The following table describes the SERCOM pin functionalities for the various
- * MUX settings, whilst in SPI Master mode.
- *
- * \note If MISO is unlisted, the SPI receiver must not be enabled for the
- * given MUX setting.
- *
- *
- *
- * MUX/Pad |
- * PAD 0 |
- * PAD 1 |
- * PAD 2 |
- * PAD 3 |
- *
- *
- * A |
- * MOSI |
- * SCK |
- * - |
- * - |
- *
- *
- * B |
- * MOSI |
- * SCK |
- * - |
- * - |
- *
- *
- * C |
- * MOSI |
- * SCK |
- * MISO |
- * - |
- *
- *
- * D |
- * MOSI |
- * SCK |
- * - |
- * MISO |
- *
- *
- * E |
- * MISO |
- * - |
- * MOSI |
- * SCK |
- *
- *
- * F |
- * - |
- * MISO |
- * MOSI |
- * SCK |
- *
- *
- * G |
- * - |
- * - |
- * MOSI |
- * SCK |
- *
- *
- * H |
- * - |
- * - |
- * MOSI |
- * SCK |
- *
- *
- * I (1) |
- * MISO |
- * SCK |
- * - |
- * MOSI |
- *
- *
- * J (1) |
- * - |
- * SCK |
- * - |
- * MOSI |
- *
- *
- * K (1) |
- * - |
- * SCK |
- * MISO |
- * MOSI |
- *
- *
- * L (1) |
- * - |
- * SCK |
- * - |
- * MOSI |
- *
- *
- * M (1) |
- * MOSI |
- * - |
- * - |
- * SCK |
- *
- *
- * N (1) |
- * MOSI |
- * MISO |
- * - |
- * SCK |
- *
- *
- * O (1) |
- * MOSI |
- * - |
- * MISO |
- * SCK |
- *
- *
- * P (1) |
- * MOSI |
- * - |
- * - |
- * SCK |
- *
- *
- *
- * (1) Not available in all silicon revisions.
- *
- * \section asfdoc_sam0_sercom_spi_mux_settings_slave Slave Mode Settings
- * The following table describes the SERCOM pin functionalities for the various
- * MUX settings, whilst in SPI Slave mode.
- *
- * \note If MISO is unlisted, the SPI receiver must not be enabled for the
- * given MUX setting.
- *
- *
- *
- * MUX/Pad |
- * PAD 0 |
- * PAD 1 |
- * PAD 2 |
- * PAD 3 |
- *
- *
- * A |
- * MISO |
- * SCK |
- * /SS |
- * - |
- *
- *
- * B |
- * MISO |
- * SCK |
- * /SS |
- * - |
- *
- *
- * C |
- * MISO |
- * SCK |
- * /SS |
- * - |
- *
- *
- * D |
- * MISO |
- * SCK |
- * /SS |
- * MOSI |
- *
- *
- * E |
- * MOSI |
- * /SS |
- * MISO |
- * SCK |
- *
- *
- * F |
- * - |
- * /SS |
- * MISO |
- * SCK |
- *
- *
- * G |
- * - |
- * /SS |
- * MISO |
- * SCK |
- *
- *
- * H |
- * - |
- * /SS |
- * MISO |
- * SCK |
- *
- *
- * I (1) |
- * MOSI |
- * SCK |
- * /SS |
- * MISO |
- *
- *
- * J (1) |
- * - |
- * SCK |
- * /SS |
- * MISO |
- *
- *
- * K (1) |
- * - |
- * SCK |
- * /SS |
- * MISO |
- *
- *
- * L (1) |
- * - |
- * SCK |
- * /SS |
- * MISO |
- *
- *
- * M (1) |
- * MISO |
- * /SS |
- * - |
- * SCK |
- *
- *
- * N (1) |
- * MISO |
- * /SS |
- * - |
- * SCK |
- *
- *
- * O (1) |
- * MISO |
- * /SS |
- * MOSI |
- * SCK |
- *
- *
- * P (1) |
- * MISO |
- * /SS |
- * - |
- * SCK |
- *
- *
- *
- * (1) Not available in all silicon revisions.
- *
- *
- * \page asfdoc_sam0_sercom_spi_document_revision_history Document Revision History
- *
- *
- *
- * Doc. Rev.
- * | Date
- * | Comments
- * |
- *
- * E |
- * 11/2014 |
- * Add SAM L21 support. |
- *
- *
- * D |
- * 12/2014 |
- * Add SAM R21/D10/D11 support. |
- *
- *
- * C |
- * 01/2014 |
- * Add SAM D21 support. |
- *
- *
- * B |
- * 11/2013 |
- * Replaced the pad multiplexing documentation with a condensed table. |
- *
- *
- * A |
- * 06/2013 |
- * Initial release |
- *
- *
- */
-
-#endif /* SPI_H_INCLUDED */
diff --git a/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/objects.h b/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/objects.h
index 758d89b2c7..2ce40bb12e 100644
--- a/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/objects.h
+++ b/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/objects.h
@@ -71,11 +71,20 @@ struct can_s {
struct i2c_s {
LPC_I2C_TypeDef *i2c;
};
+*/
struct spi_s {
- LPC_SSP_TypeDef *spi;
+ Sercom *spi;
+ uint8_t mode;
+#if DEVICE_SPI_ASYNCH
+ uint8_t status;
+ uint32_t mask;
+ uint32_t event;
+ void *tx_buffer;
+ void *rx_buffer;
+#endif
};
-*/
+
#ifdef __cplusplus
}
#endif
diff --git a/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/spi_api.c b/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/spi_api.c
new file mode 100644
index 0000000000..fbdbb8903b
--- /dev/null
+++ b/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/spi_api.c
@@ -0,0 +1,772 @@
+/* mbed Microcontroller Library
+ * Copyright (c) 2006-2013 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "mbed_assert.h"
+#include "spi_api.h"
+
+#include
+
+#include "cmsis.h"
+#include "pinmap.h"
+#include "sercom.h"
+
+////////////////////////////////////////
+#define EXT1_SPI_MODULE SERCOM5
+#define EXT1_SPI_SERCOM_MUX_SETTING ((0x1 << SERCOM_SPI_CTRLA_DOPO_Pos) | (0x0 << SERCOM_SPI_CTRLA_DIPO_Pos))
+#define EXT1_SPI_SERCOM_PINMUX_PAD0 PINMUX_PB02D_SERCOM5_PAD0
+#define EXT1_SPI_SERCOM_PINMUX_PAD1 PINMUX_PB03D_SERCOM5_PAD1
+#define EXT1_SPI_SERCOM_PINMUX_PAD2 PINMUX_PB22D_SERCOM5_PAD2
+#define EXT1_SPI_SERCOM_PINMUX_PAD3 PINMUX_PB23D_SERCOM5_PAD3
+#define EXT1_SPI_SERCOM_DMAC_ID_TX SERCOM5_DMAC_ID_TX
+#define EXT1_SPI_SERCOM_DMAC_ID_RX SERCOM5_DMAC_ID_RX
+
+/** Default pinmux. */
+# define PINMUX_DEFAULT 0
+
+/** Unused pinmux. */
+# define PINMUX_UNUSED 0xFFFFFFFF
+////////////////////////////////////////
+
+#if DEVICE_SPI_ASYNCH
+#define pSPI_S(obj) obj->spi.spi
+#else
+#define pSPI_S(obj) obj->spi
+#endif
+#define _SPI(obj) pSPI_S(obj)->SPI
+
+/** SPI default baud rate. */
+#define SPI_DEFAULT_BAUD 50000//100000
+
+
+/** SPI timeout value. */
+# define SPI_TIMEOUT 10000
+
+#if DEVICE_SPI_ASYNCH
+/* Global variables */
+void *_sercom_instances[SERCOM_INST_NUM] = {0};
+
+static void _spi_transceive_buffer(spi_t *obj);
+
+/** \internal
+ * Generates a SERCOM interrupt handler function for a given SERCOM index.
+ */
+#define _SERCOM_SPI_INTERRUPT_HANDLER(n, unused) \
+void SERCOM##n##_SPIHandler(void) \
+{ \
+ _spi_transceive_buffer((spi_t *)_sercom_instances[n]); \
+}
+#define _SERCOM_SPI_INTERRUPT_HANDLER_DECLR(n, unused) \
+ (uint32_t)SERCOM##n##_SPIHandler,
+
+/** Auto-generate a set of interrupt handlers for each SERCOM SPI in the device */
+MREPEAT(SERCOM_INST_NUM, _SERCOM_SPI_INTERRUPT_HANDLER, ~)
+
+uint32_t _sercom_handlers[SERCOM_INST_NUM] = {
+ MREPEAT(SERCOM_INST_NUM, _SERCOM_SPI_INTERRUPT_HANDLER_DECLR, ~)
+ };
+#endif
+
+static inline bool spi_is_syncing(spi_t *obj)
+{
+ /* Sanity check arguments */
+ MBED_ASSERT(obj);
+
+ /* Return synchronization status */
+ return (_SPI(obj).SYNCBUSY.reg);
+}
+
+static inline void spi_enable(spi_t *obj)
+{
+ /* Sanity check arguments */
+ MBED_ASSERT(obj);
+
+#if DEVICE_SPI_ASYNCH
+ /* Enable interrupt */
+ NVIC_EnableIRQ(SERCOM0_IRQn + _sercom_get_sercom_inst_index(pSPI_S(obj)));
+#endif
+
+ /* Wait until the synchronization is complete */
+ while (spi_is_syncing(obj));
+
+ /* Enable SPI */
+ _SPI(obj).CTRLA.reg |= SERCOM_SPI_CTRLA_ENABLE;
+}
+
+static inline void spi_disable(spi_t *obj)
+{
+ /* Sanity check arguments */
+ MBED_ASSERT(obj);
+
+#if DEVICE_SPI_ASYNCH
+ /* Disable interrupt */
+ NVIC_DisableIRQ(SERCOM0_IRQn + _sercom_get_sercom_inst_index(pSPI_S(obj)));
+#endif
+ /* Wait until the synchronization is complete */
+ while (spi_is_syncing(obj));
+
+ /* Disable SPI */
+ _SPI(obj).CTRLA.reg &= ~SERCOM_SPI_CTRLA_ENABLE;
+}
+
+static inline bool spi_is_write_complete(spi_t *obj)
+{
+ /* Sanity check arguments */
+ MBED_ASSERT(obj);
+
+ /* Check interrupt flag */
+ return (_SPI(obj).INTFLAG.reg & SERCOM_SPI_INTFLAG_TXC);
+}
+
+static inline bool spi_is_ready_to_write(spi_t *obj)
+{
+ /* Sanity check arguments */
+ MBED_ASSERT(obj);
+
+ /* Check interrupt flag */
+ return (_SPI(obj).INTFLAG.reg & SERCOM_SPI_INTFLAG_DRE);
+}
+
+static inline bool spi_is_ready_to_read(spi_t *obj)
+{
+ /* Sanity check arguments */
+ MBED_ASSERT(obj);
+
+ /* Check interrupt flag */
+ return (_SPI(obj).INTFLAG.reg & SERCOM_SPI_INTFLAG_RXC);
+}
+
+static inline bool spi_write(spi_t *obj, uint16_t tx_data)
+{
+ /* Sanity check arguments */
+ MBED_ASSERT(obj);
+
+ /* Check if the data register has been copied to the shift register */
+ if (!spi_is_ready_to_write(obj)) {
+ /* Data register has not been copied to the shift register, return */
+ return 0;
+ }
+
+ /* Write the character to the DATA register */
+ _SPI(obj).DATA.reg = tx_data & SERCOM_SPI_DATA_MASK;
+
+ return 1;
+}
+
+static inline bool spi_read(spi_t *obj, uint16_t *rx_data)
+{
+ /* Sanity check arguments */
+ MBED_ASSERT(obj);
+
+ /* Check if data is ready to be read */
+ if (!spi_is_ready_to_read(obj)) {
+ /* No data has been received, return */
+ return 0;
+ }
+
+ /* Check if data is overflown */
+ if (_SPI(obj).STATUS.reg & SERCOM_SPI_STATUS_BUFOVF) {
+ /* Clear overflow flag */
+ _SPI(obj).STATUS.reg |= SERCOM_SPI_STATUS_BUFOVF;
+ }
+
+ /* Read the character from the DATA register */
+ if (_SPI(obj).CTRLB.bit.CHSIZE == 1) {
+ *rx_data = (_SPI(obj).DATA.reg & SERCOM_SPI_DATA_MASK);
+ } else {
+ *rx_data = (uint8_t)_SPI(obj).DATA.reg;
+ }
+
+ return 1;
+}
+
+/**
+ * \defgroup GeneralSPI SPI Configuration Functions
+ * @{
+ */
+
+/** Initialize the SPI peripheral
+ *
+ * Configures the pins used by SPI, sets a default format and frequency, and enables the peripheral
+ * @param[out] obj The SPI object to initialize
+ * @param[in] mosi The pin to use for MOSI
+ * @param[in] miso The pin to use for MISO
+ * @param[in] sclk The pin to use for SCLK
+ * @param[in] ssel The pin to use for SSEL
+ */
+void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel) {
+ uint16_t baud = 0;
+ uint32_t ctrla = 0;
+ uint32_t ctrlb = 0;
+ enum status_code error_code;
+
+ // TODO: Calculate SERCOM instance from pins
+ // TEMP: Giving our own value for testing
+ pSPI_S(obj) = EXT1_SPI_MODULE;
+
+ /* Disable SPI */
+ spi_disable(obj);
+
+ /* Check if reset is in progress. */
+ if (_SPI(obj).CTRLA.reg & SERCOM_SPI_CTRLA_SWRST){
+ return;
+ }
+ uint32_t sercom_index = _sercom_get_sercom_inst_index(pSPI_S(obj));
+ uint32_t pm_index, gclk_index;
+#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 + PM_APBCMASK_SERCOM0_Pos;
+ gclk_index = sercom_index + SERCOM0_GCLK_ID_CORE;
+#endif
+
+ /* 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 = GCLK_GENERATOR_0;
+ system_gclk_chan_set_config(gclk_index, &gclk_chan_conf);
+ system_gclk_chan_enable(gclk_index);
+ sercom_set_gclk_generator(GCLK_GENERATOR_0, false);
+
+#if DEVICE_SPI_ASYNCH
+ /* Save the object */
+ _sercom_instances[sercom_index] = obj;
+
+ /* Configure interrupt handler */
+ NVIC_SetVector((SERCOM0_IRQn + sercom_index), (uint32_t)_sercom_handlers[sercom_index]);
+#endif
+
+ /* Set the SERCOM in SPI master mode */
+ _SPI(obj).CTRLA.reg |= SERCOM_SPI_CTRLA_MODE(0x3);
+
+ // TODO: Do pin muxing here
+ struct system_pinmux_config pin_conf;
+ system_pinmux_get_config_defaults(&pin_conf);
+ pin_conf.direction = SYSTEM_PINMUX_PIN_DIR_INPUT;
+ //if(config->mode == SPI_MODE_SLAVE) {
+ //pin_conf.input_pull = SYSTEM_PINMUX_PIN_PULL_NONE;
+ //}
+
+ uint32_t pad_pinmuxes[] = {
+ EXT1_SPI_SERCOM_PINMUX_PAD0, EXT1_SPI_SERCOM_PINMUX_PAD1,
+ EXT1_SPI_SERCOM_PINMUX_PAD2, EXT1_SPI_SERCOM_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(pSPI_S(obj), pad);
+ }
+
+ if (current_pinmux != PINMUX_UNUSED) {
+ pin_conf.mux_position = current_pinmux & 0xFFFF;
+ system_pinmux_pin_set_config(current_pinmux >> 16, &pin_conf);
+ }
+ }
+
+ /* Get baud value, based on baudrate and the internal clock frequency */
+ uint32_t internal_clock = system_gclk_chan_get_hz(gclk_index);
+ //internal_clock = 8000000;
+ error_code = _sercom_get_sync_baud_val(SPI_DEFAULT_BAUD, internal_clock, &baud);
+ if (error_code != STATUS_OK) {
+ /* Baud rate calculation error */
+ return;
+ }
+ _SPI(obj).BAUD.reg = (uint8_t)baud;
+
+ /* Set MUX setting */
+ ctrla |= EXT1_SPI_SERCOM_MUX_SETTING; // TODO: Change this to appropriate Settings
+
+ /* Set SPI character size */
+ ctrlb |= SERCOM_SPI_CTRLB_CHSIZE(0);
+
+ /* Enable receiver */
+ ctrlb |= SERCOM_SPI_CTRLB_RXEN;
+
+ /* Write CTRLA register */
+ _SPI(obj).CTRLA.reg |= ctrla;
+
+ /* Write CTRLB register */
+ _SPI(obj).CTRLB.reg |= ctrlb;
+
+ /* Enable SPI */
+ spi_enable(obj);
+}
+
+/** Release a SPI object
+ *
+ * TODO: spi_free is currently unimplemented
+ * This will require reference counting at the C++ level to be safe
+ *
+ * Return the pins owned by the SPI object to their reset state
+ * Disable the SPI peripheral
+ * Disable the SPI clock
+ * @param[in] obj The SPI object to deinitialize
+ */
+void spi_free(spi_t *obj) {
+ // [TODO]
+}
+
+/** Configure the SPI format
+ *
+ * Set the number of bits per frame, configure clock polarity and phase, shift order and master/slave mode
+ * @param[in,out] obj The SPI object to configure
+ * @param[in] bits The number of bits per frame
+ * @param[in] mode The SPI mode (clock polarity, phase, and shift direction)
+ * @param[in] slave Zero for master mode or non-zero for slave mode
+ */
+void spi_format(spi_t *obj, int bits, int mode, int slave) {
+
+ /* Disable SPI */
+ spi_disable(obj);
+
+ /* Set the SERCOM in SPI mode */
+ _SPI(obj).CTRLA.bit.MODE = slave? 0x2 : 0x3;
+
+ /* Set SPI Frame size - only 8-bit and 9-bit supported now */
+ _SPI(obj).CTRLB.bit.CHSIZE = (bits > 8)? 1 : 0;
+
+ /* Set SPI Clock Phase */
+ _SPI(obj).CTRLA.bit.CPHA = (mode & 0x01)? 1 : 0;
+
+ /* Set SPI Clock Polarity */
+ _SPI(obj).CTRLA.bit.CPOL = (mode & 0x02)? 1 : 0;
+
+ /* Enable SPI */
+ spi_enable(obj);
+}
+
+/** Set the SPI baud rate
+ *
+ * Actual frequency may differ from the desired frequency due to available dividers and bus clock
+ * Configures the SPI peripheral's baud rate
+ * @param[in,out] obj The SPI object to configure
+ * @param[in] hz The baud rate in Hz
+ */
+void spi_frequency(spi_t *obj, int hz) {
+ uint16_t baud = 0;
+
+ /* Disable SPI */
+ spi_disable(obj);
+
+ /* Find frequency of the internal SERCOMi_GCLK_ID_CORE */
+ uint32_t sercom_index = _sercom_get_sercom_inst_index(pSPI_S(obj));
+ uint32_t gclk_index = sercom_index + SERCOM0_GCLK_ID_CORE;
+ uint32_t internal_clock = system_gclk_chan_get_hz(gclk_index);
+
+ /* Get baud value, based on baudrate and the internal clock frequency */
+ enum status_code error_code = _sercom_get_sync_baud_val(hz, internal_clock, &baud);
+
+ if (error_code != STATUS_OK) {
+ /* Baud rate calculation error, return status code */
+ /* Enable SPI */
+ spi_enable(obj);
+ return;
+ }
+
+ _SPI(obj).BAUD.reg = (uint8_t)baud;
+
+ /* Enable SPI */
+ spi_enable(obj);
+}
+
+/**@}*/
+/**
+ * \defgroup SynchSPI Synchronous SPI Hardware Abstraction Layer
+ * @{
+ */
+
+/** Write a byte out in master mode and receive a value
+ *
+ * @param[in] obj The SPI peripheral to use for sending
+ * @param[in] value The value to send
+ * @return Returns the value received during send
+ */
+int spi_master_write(spi_t *obj, int value) {
+ uint16_t rx_data = 0;
+
+ /* Sanity check arguments */
+ MBED_ASSERT(obj);
+
+#if DEVICE_SPI_ASYNCH
+ if (obj->spi.status == STATUS_BUSY) {
+ /* Check if the SPI module is busy with a job */
+ return 0;
+ }
+#endif
+
+ /* Wait until the module is ready to write the character */
+ while (!spi_is_ready_to_write(obj));
+
+ /* Write data */
+ spi_write(obj, value);
+
+ if (!(_SPI(obj).CTRLB.bit.RXEN)) {
+ return 0;
+ }
+
+ /* Wait until the module is ready to read the character */
+ while (!spi_is_ready_to_read(obj));
+
+ /* Read data */
+ spi_read(obj, &rx_data);
+
+ return rx_data;
+}
+
+/** Check if a value is available to read
+ *
+ * @param[in] obj The SPI peripheral to check
+ * @return non-zero if a value is available
+ */
+int spi_slave_receive(spi_t *obj) {
+ /* Sanity check arguments */
+ MBED_ASSERT(obj);
+
+ return spi_is_ready_to_read(obj);
+}
+
+/** Get a received value out of the SPI receive buffer in slave mode
+ *
+ * Blocks until a value is available
+ * @param[in] obj The SPI peripheral to read
+ * @return The value received
+ */
+int spi_slave_read(spi_t *obj) {
+ int i;
+ uint16_t rx_data = 0;
+
+ /* Sanity check arguments */
+ MBED_ASSERT(obj);
+
+ /* Check for timeout period */
+ for (i = 0; i < SPI_TIMEOUT; i++) {
+ if (spi_is_ready_to_read(obj)) {
+ break;
+ }
+ }
+ if (i == SPI_TIMEOUT) {
+ /* Not ready to read data within timeout period */
+ return 0;
+ }
+
+ /* Read data */
+ spi_read(obj, &rx_data);
+
+ return rx_data;
+}
+
+/** Write a value to the SPI peripheral in slave mode
+ *
+ * Blocks until the SPI peripheral can be written to
+ * @param[in] obj The SPI peripheral to write
+ * @param[in] value The value to write
+ */
+void spi_slave_write(spi_t *obj, int value) {
+ int i;
+
+ /* Sanity check arguments */
+ MBED_ASSERT(obj);
+
+ /* Check for timeout period */
+ for (i = 0; i < SPI_TIMEOUT; i++) {
+ if (spi_is_ready_to_write(obj)) {
+ break;
+ }
+ }
+ if (i == SPI_TIMEOUT) {
+ /* Not ready to write data within timeout period */
+ return;
+ }
+
+ /* Write data */
+ spi_write(obj, value);
+}
+
+/** Checks if the specified SPI peripheral is in use
+ *
+ * @param[in] obj The SPI peripheral to check
+ * @return non-zero if the peripheral is currently transmitting
+ */
+int spi_busy(spi_t *obj)
+{
+ /* Sanity check arguments */
+ MBED_ASSERT(obj);
+
+ return spi_is_write_complete(obj);
+}
+
+/** Get the module number
+ *
+ * @param[in] obj The SPI peripheral to check
+ * @return The module number
+ */
+uint8_t spi_get_module(spi_t *obj)
+{
+ /* Sanity check arguments */
+ MBED_ASSERT(obj);
+ return _sercom_get_sercom_inst_index(pSPI_S(obj));
+}
+
+
+#if DEVICE_SPI_ASYNCH
+/**
+ * \defgroup AsynchSPI Asynchronous SPI Hardware Abstraction Layer
+ * @{
+ */
+
+
+/**
+ * \internal
+ * Writes a character from the TX buffer to the Data register.
+ *
+ * \param[in,out] module Pointer to SPI software instance struct
+ */
+static void _spi_write_async(spi_t *obj)
+{
+ /* Sanity check arguments */
+ MBED_ASSERT(obj);
+
+ uint16_t data_to_send;
+ uint8_t *tx_buffer = obj->tx_buff.buffer;
+
+ /* Do nothing if we are at the end of buffer */
+ if (obj->tx_buff.pos < obj->tx_buff.length) {
+ /* Write value will be at least 8-bits long */
+ data_to_send = tx_buffer[obj->tx_buff.pos];
+ /* Increment 8-bit index */
+ obj->tx_buff.pos++;
+
+ if (_SPI(obj).CTRLB.bit.CHSIZE == 1) {
+ data_to_send |= (tx_buffer[obj->tx_buff.pos] << 8);
+ /* Increment 8-bit index */
+ obj->tx_buff.pos++;
+ }
+ } else {
+ /* Write a dummy packet */
+ data_to_send = ~0;
+ }
+
+ /* Write the data to send*/
+ _SPI(obj).DATA.reg = data_to_send & SERCOM_SPI_DATA_MASK;
+
+ /* Check for error */
+ if ((_SPI(obj).INTFLAG.reg & SERCOM_SPI_INTFLAG_ERROR) && (obj->spi.mask & SPI_EVENT_ERROR)) {
+ obj->spi.event != SPI_EVENT_ERROR;
+ }
+}
+
+/**
+ * \internal
+ * Reads a character from the Data register to the RX buffer.
+ *
+ * \param[in,out] module Pointer to SPI software instance struct
+ */
+static void _spi_read_async(spi_t *obj)
+{
+ /* Sanity check arguments */
+ MBED_ASSERT(obj);
+
+ uint8_t *rx_buffer = obj->rx_buff.buffer;
+
+ /* Check if data is overflown */
+ if (_SPI(obj).STATUS.reg & SERCOM_SPI_STATUS_BUFOVF) {
+ /* Clear overflow flag */
+ _SPI(obj).STATUS.reg |= SERCOM_SPI_STATUS_BUFOVF;
+ if (obj->spi.mask & SPI_EVENT_RX_OVERFLOW) {
+ /* Set overflow error */
+ obj->spi.event != SPI_EVENT_RX_OVERFLOW;
+ return;
+ }
+ }
+
+ /* Read data, either valid, or dummy */
+ uint16_t received_data = (_SPI(obj).DATA.reg & SERCOM_SPI_DATA_MASK);
+
+ /* Do nothing if we are at the end of buffer */
+ if (obj->rx_buff.pos >= obj->rx_buff.length) {
+ return;
+ }
+
+ /* Read value will be at least 8-bits long */
+ rx_buffer[obj->rx_buff.pos] = received_data;
+ /* Increment 8-bit index */
+ obj->rx_buff.pos++;
+
+ if (_SPI(obj).CTRLB.bit.CHSIZE == 1) {
+ /* 9-bit data, write next received byte to the buffer */
+ rx_buffer[obj->rx_buff.pos] = (received_data >> 8);
+ /* Increment 8-bit index */
+ obj->rx_buff.pos++;
+ }
+
+ /* Check for error */
+ if ((_SPI(obj).INTFLAG.reg & SERCOM_SPI_INTFLAG_ERROR) && (obj->spi.mask & SPI_EVENT_ERROR)) {
+ obj->spi.event != SPI_EVENT_ERROR;
+ }
+}
+
+/**
+ * \internal
+ * Starts transceive of buffers with a given length
+ *
+ * \param[in] obj Pointer to SPI software instance struct
+ *
+ */
+static void _spi_transceive_buffer(spi_t *obj)
+{
+ /* Sanity check arguments */
+ MBED_ASSERT(obj);
+
+ uint16_t interrupt_status = _SPI(obj).INTFLAG.reg;
+
+ uint8_t sercom_index = _sercom_get_sercom_inst_index(obj->spi.spi);
+
+ /* Disable all interrupt handlers for now
+ _SPI(obj).INTENCLR.reg = interrupt_status;*/
+
+ interrupt_status &= _SPI(obj).INTENSET.reg;
+
+ if (interrupt_status & SERCOM_SPI_INTFLAG_DRE) {
+ _spi_write_async(obj);
+ }
+
+ if (interrupt_status & SERCOM_SPI_INTFLAG_RXC) {
+ _spi_read_async(obj);
+ }
+
+ if ((obj->spi.event & SPI_EVENT_ERROR) || (obj->spi.event & SPI_EVENT_RX_OVERFLOW)) {
+ /* Disable all interrupts */
+ _SPI(obj).INTENCLR.reg =
+ SERCOM_SPI_INTFLAG_DRE |
+ SERCOM_SPI_INTFLAG_TXC |
+ SERCOM_SPI_INTFLAG_RXC |
+ SERCOM_SPI_INTFLAG_ERROR;
+ NVIC_DisableIRQ(SERCOM0_IRQn + sercom_index);
+
+ /* Transfer complete, invoke the callback function */
+ if (obj->spi.event & SPI_EVENT_RX_OVERFLOW) {
+ obj->spi.status = STATUS_ERR_OVERFLOW;
+ } else {
+ obj->spi.status = STATUS_ERR_BAD_DATA;
+ }
+ // TODO: Invoke callback
+ return;
+ }
+
+ if (interrupt_status & (SERCOM_SPI_INTFLAG_TXC | SERCOM_SPI_INTFLAG_RXC)) {
+ if ((obj->tx_buff.pos >= obj->tx_buff.length) && (obj->rx_buff.pos >= obj->rx_buff.length)) {
+ /* Clear all interrupts */
+ _SPI(obj).INTENCLR.reg =
+ SERCOM_SPI_INTFLAG_DRE |
+ SERCOM_SPI_INTFLAG_TXC |
+ SERCOM_SPI_INTFLAG_RXC |
+ SERCOM_SPI_INTFLAG_ERROR;
+ NVIC_DisableIRQ(SERCOM0_IRQn + sercom_index);
+ NVIC_SetVector((SERCOM0_IRQn + sercom_index), (uint32_t)NULL);
+
+ /* Transfer complete, invoke the callback function */
+ obj->spi.event |= SPI_EVENT_COMPLETE;
+ // TODO: Invoke callback
+ return;
+ }
+ }
+
+ /* Enable back interrupts
+ _SPI(obj).INTENSET.reg = interrupt_status;*/
+}
+
+/** Begin the SPI transfer. Buffer pointers and lengths are specified in tx_buff and rx_buff
+ *
+ * @param[in] obj The SPI object which holds the transfer information
+ * @param[in] tx The buffer to send
+ * @param[in] tx_length The number of words to transmit
+ * @param[in] rx The buffer to receive
+ * @param[in] rx_length The number of words to receive
+ * @param[in] bit_width The bit width of buffer words
+ * @param[in] event The logical OR of events to be registered
+ * @param[in] handler SPI interrupt handler
+ * @param[in] hint A suggestion for how to use DMA with this transfer **< DMA currently not implemented >**
+ */
+void spi_master_transfer(spi_t *obj, void *tx, size_t tx_length, void *rx, size_t rx_length, uint8_t bit_width, uint32_t handler, uint32_t event, DMAUsage hint)
+{
+ // TODO:
+}
+
+/** The asynchronous IRQ handler
+ *
+ * Reads the received values out of the RX FIFO, writes values into the TX FIFO and checks for transfer termination
+ * conditions, such as buffer overflows or transfer complete.
+ * @param[in] obj The SPI object which holds the transfer information
+ * @return event flags if a transfer termination condition was met or 0 otherwise.
+ */
+uint32_t spi_irq_handler_asynch(spi_t *obj)
+{
+ return 0;
+}
+
+/** Attempts to determine if the SPI peripheral is already in use.
+ * @param[in] obj The SPI object to check for activity
+ * @return non-zero if the SPI port is active or zero if it is not.
+ */
+uint8_t spi_active(spi_t *obj)
+{
+ return 0;
+}
+
+/** Abort an SPI transfer
+ *
+ * @param obj The SPI peripheral to stop
+ */
+void spi_abort_asynch(spi_t *obj)
+{
+ /* Sanity check arguments */
+ MBED_ASSERT(obj);
+
+ uint8_t sercom_index = _sercom_get_sercom_inst_index(obj->spi.spi);
+
+ /* Clear all interrupts */
+ _SPI(obj).INTENCLR.reg =
+ SERCOM_SPI_INTFLAG_DRE |
+ SERCOM_SPI_INTFLAG_TXC |
+ SERCOM_SPI_INTFLAG_RXC |
+ SERCOM_SPI_INTFLAG_ERROR;
+
+ // TODO: Disable and remove irq handler
+ NVIC_DisableIRQ(SERCOM0_IRQn + sercom_index);
+ NVIC_SetVector((SERCOM0_IRQn + sercom_index), NULL);
+
+ obj->spi.status = STATUS_ABORTED;
+}
+
+#endif
diff --git a/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/us_ticker.c b/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/us_ticker.c
index 56356d102f..5458bdd135 100644
--- a/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/us_ticker.c
+++ b/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/us_ticker.c
@@ -22,6 +22,10 @@
#include "tc.h"
#include "tc_interrupt.h"
+#define TICKER_COUNTER_uS TC4
+#define TICKER_COUNTER_IRQn TC4_IRQn
+#define TICKER_COUNTER_Handlr TC4_Handler
+
static int us_ticker_inited = 0;
struct tc_module us_ticker_module;
@@ -30,8 +34,8 @@ void us_ticker_irq_handler_internal(struct tc_module* us_tc_module)
{
us_ticker_irq_handler();
- /* Disable the callback */
- tc_disable_callback(us_tc_module, TC_CALLBACK_CC_CHANNEL0);
+ /* Disable the interrupt */
+ us_ticker_disable_interrupt();
}
void us_ticker_init(void)
@@ -55,13 +59,14 @@ void us_ticker_init(void)
}
config_tc.clock_prescaler = TC_CTRLA_PRESCALER(prescaler);
config_tc.counter_size = TC_COUNTER_SIZE_32BIT;
+ config_tc.run_in_standby = true;
config_tc.counter_32_bit.value = 0;
config_tc.counter_32_bit.compare_capture_channel[0] = 0xFFFFFFFF;
//config_tc.oneshot = true;
/* Initialize the timer */
- ret_status = tc_init(&us_ticker_module, TC4, &config_tc);
+ ret_status = tc_init(&us_ticker_module, TICKER_COUNTER_uS, &config_tc);
MBED_ASSERT(ret_status == STATUS_OK);
/* Register callback function */
@@ -92,9 +97,12 @@ void us_ticker_set_interrupt(timestamp_t timestamp)
us_ticker_irq_handler();
return;
}
-
+
tc_set_compare_value(&us_ticker_module, TC_CALLBACK_CC_CHANNEL0, timestamp);
+ NVIC_SetVector(TICKER_COUNTER_IRQn, (uint32_t)TICKER_COUNTER_Handlr);
+ NVIC_EnableIRQ(TICKER_COUNTER_IRQn);
+
/* Enable the callback */
tc_enable_callback(&us_ticker_module, TC_CALLBACK_CC_CHANNEL0);
@@ -105,9 +113,13 @@ void us_ticker_set_interrupt(timestamp_t timestamp)
void us_ticker_disable_interrupt(void) {
/* Disable the callback */
tc_disable_callback(&us_ticker_module, TC_CALLBACK_CC_CHANNEL0);
+ NVIC_DisableIRQ(TICKER_COUNTER_IRQn);
}
void us_ticker_clear_interrupt(void) {
- /* Disable the callback */
- tc_disable_callback(&us_ticker_module, TC_CALLBACK_CC_CHANNEL0);
+ /* Disable the interrupt, this is clear the interrupt also */
+ us_ticker_disable_interrupt();
+
+ NVIC_DisableIRQ(TICKER_COUNTER_IRQn);
+ NVIC_SetVector(TICKER_COUNTER_IRQn, (uint32_t)NULL);
}
\ No newline at end of file