summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorScott Shawcroft <scott@chickadee.tech>2016-10-11 15:48:43 -0700
committerScott Shawcroft <scott@chickadee.tech>2016-10-11 15:48:43 -0700
commit011056af15f6107b9ef35fdf19a3f715b55f55d5 (patch)
tree75712ad385a21f3d777c2fd00b8a832cc35f2518
parent6986aa9aa2bd626371a6d49be287516e4943b798 (diff)
atmel-samd: Add support for SPI.
Also separate out the ASF config headers that are shared across all boards.
-rw-r--r--atmel-samd/Makefile2
-rw-r--r--atmel-samd/asf_conf/conf_clocks.h (renamed from atmel-samd/boards/arduino_zero/conf_clocks.h)0
-rw-r--r--atmel-samd/asf_conf/conf_sleepmgr.h (renamed from atmel-samd/boards/arduino_zero/conf_sleepmgr.h)0
-rw-r--r--atmel-samd/asf_conf/conf_spi.h (renamed from atmel-samd/boards/metro_m0_flash/conf_sleepmgr.h)14
-rw-r--r--atmel-samd/asf_conf/user_board.h (renamed from atmel-samd/boards/arduino_zero/user_board.h)0
-rw-r--r--atmel-samd/boards/feather_m0_bluefruit_le/conf_clocks.h197
-rw-r--r--atmel-samd/boards/feather_m0_bluefruit_le/conf_sleepmgr.h52
-rw-r--r--atmel-samd/boards/feather_m0_bluefruit_le/user_board.h40
-rw-r--r--atmel-samd/boards/metro_m0_flash/conf_clocks.h197
-rw-r--r--atmel-samd/boards/metro_m0_flash/pins.c2
-rw-r--r--atmel-samd/boards/metro_m0_flash/user_board.h40
-rw-r--r--atmel-samd/common-hal/modules/machine.c60
-rw-r--r--atmel-samd/common-hal/modules/machine_types.h6
-rw-r--r--atmel-samd/modmachine.c1
-rw-r--r--shared-bindings/modules/machine.c203
-rw-r--r--shared-bindings/modules/machine.h12
16 files changed, 275 insertions, 551 deletions
diff --git a/atmel-samd/Makefile b/atmel-samd/Makefile
index b8bdd2b1b..b6396d2ed 100644
--- a/atmel-samd/Makefile
+++ b/atmel-samd/Makefile
@@ -32,6 +32,7 @@ INC += -I..
INC += -I../lib/mp-readline
INC += -I../lib/timeutils
INC += -Icommon-hal/modules/
+INC += -Iasf_conf/
INC += -Iasf/common/boards/
INC += -Iasf/common/services/sleepmgr/
INC += -Iasf/common/services/storage/ctrl_access/
@@ -117,6 +118,7 @@ SRC_ASF = $(addprefix asf/sam0/,\
drivers/sercom/i2c/i2c_sam0/i2c_master.c \
drivers/sercom/sercom.c \
drivers/sercom/sercom_interrupt.c \
+ drivers/sercom/spi/spi.c \
drivers/sercom/usart/usart.c \
drivers/sercom/usart/usart_interrupt.c \
drivers/system/clock/clock_samd21_r21_da/clock.c \
diff --git a/atmel-samd/boards/arduino_zero/conf_clocks.h b/atmel-samd/asf_conf/conf_clocks.h
index 20ee967e2..20ee967e2 100644
--- a/atmel-samd/boards/arduino_zero/conf_clocks.h
+++ b/atmel-samd/asf_conf/conf_clocks.h
diff --git a/atmel-samd/boards/arduino_zero/conf_sleepmgr.h b/atmel-samd/asf_conf/conf_sleepmgr.h
index 281a36078..281a36078 100644
--- a/atmel-samd/boards/arduino_zero/conf_sleepmgr.h
+++ b/atmel-samd/asf_conf/conf_sleepmgr.h
diff --git a/atmel-samd/boards/metro_m0_flash/conf_sleepmgr.h b/atmel-samd/asf_conf/conf_spi.h
index 281a36078..d093a58c5 100644
--- a/atmel-samd/boards/metro_m0_flash/conf_sleepmgr.h
+++ b/atmel-samd/asf_conf/conf_spi.h
@@ -1,9 +1,9 @@
/**
* \file
*
- * \brief Sleep manager configuration
+ * \brief SAM D21 SPI configuration
*
- * Copyright (c) 2014-2015 Atmel Corporation. All rights reserved.
+ * Copyright (C) 2013-2016 Atmel Corporation. All rights reserved.
*
* \asf_license_start
*
@@ -44,9 +44,11 @@
* Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
*/
-#ifndef CONF_SLEEPMGR_H_INCLUDED
-#define CONF_SLEEPMGR_H_INCLUDED
-#define CONFIG_SLEEPMGR_ENABLE
+#ifndef CONF_SPI_H_INCLUDED
+#define CONF_SPI_H_INCLUDED
-#endif /* CONF_SLEEPMGR_H_INCLUDED */
+#define CONF_SPI_MASTER_ENABLE true
+#define CONF_SPI_SLAVE_ENABLE false
+
+#endif /* CONF_SPI_H_INCLUDED */
diff --git a/atmel-samd/boards/arduino_zero/user_board.h b/atmel-samd/asf_conf/user_board.h
index 39980a7d2..39980a7d2 100644
--- a/atmel-samd/boards/arduino_zero/user_board.h
+++ b/atmel-samd/asf_conf/user_board.h
diff --git a/atmel-samd/boards/feather_m0_bluefruit_le/conf_clocks.h b/atmel-samd/boards/feather_m0_bluefruit_le/conf_clocks.h
deleted file mode 100644
index 20ee967e2..000000000
--- a/atmel-samd/boards/feather_m0_bluefruit_le/conf_clocks.h
+++ /dev/null
@@ -1,197 +0,0 @@
-/**
- * \file
- *
- * \brief SAM D21 Clock configuration
- *
- * Copyright (C) 2014-2015 Atmel Corporation. All rights reserved.
- *
- * \asf_license_start
- *
- * \page License
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * 3. The name of Atmel may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * 4. This software may only be redistributed and used in connection with an
- * Atmel microcontroller product.
- *
- * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
- * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- * \asf_license_stop
- *
- */
-/*
- * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
- */
-#include <clock.h>
-
-#ifndef CONF_CLOCKS_H_INCLUDED
-# define CONF_CLOCKS_H_INCLUDED
-
-/* System clock bus configuration */
-# define CONF_CLOCK_CPU_CLOCK_FAILURE_DETECT false
-# define CONF_CLOCK_FLASH_WAIT_STATES 2
-# define CONF_CLOCK_CPU_DIVIDER SYSTEM_MAIN_CLOCK_DIV_1
-# define CONF_CLOCK_APBA_DIVIDER SYSTEM_MAIN_CLOCK_DIV_1
-# define CONF_CLOCK_APBB_DIVIDER SYSTEM_MAIN_CLOCK_DIV_1
-# define CONF_CLOCK_APBC_DIVIDER SYSTEM_MAIN_CLOCK_DIV_1
-
-/* SYSTEM_CLOCK_SOURCE_OSC8M configuration - Internal 8MHz oscillator */
-# define CONF_CLOCK_OSC8M_PRESCALER SYSTEM_OSC8M_DIV_1
-# define CONF_CLOCK_OSC8M_ON_DEMAND true
-# define CONF_CLOCK_OSC8M_RUN_IN_STANDBY false
-
-/* SYSTEM_CLOCK_SOURCE_XOSC configuration - External clock/oscillator */
-# define CONF_CLOCK_XOSC_ENABLE false
-# define CONF_CLOCK_XOSC_EXTERNAL_CRYSTAL SYSTEM_CLOCK_EXTERNAL_CRYSTAL
-# define CONF_CLOCK_XOSC_EXTERNAL_FREQUENCY 12000000UL
-# define CONF_CLOCK_XOSC_STARTUP_TIME SYSTEM_XOSC_STARTUP_32768
-# define CONF_CLOCK_XOSC_AUTO_GAIN_CONTROL true
-# define CONF_CLOCK_XOSC_ON_DEMAND true
-# define CONF_CLOCK_XOSC_RUN_IN_STANDBY false
-
-/* SYSTEM_CLOCK_SOURCE_XOSC32K configuration - External 32KHz crystal/clock oscillator */
-# define CONF_CLOCK_XOSC32K_ENABLE true
-# define CONF_CLOCK_XOSC32K_EXTERNAL_CRYSTAL SYSTEM_CLOCK_EXTERNAL_CRYSTAL
-# define CONF_CLOCK_XOSC32K_STARTUP_TIME SYSTEM_XOSC32K_STARTUP_65536
-# define CONF_CLOCK_XOSC32K_AUTO_AMPLITUDE_CONTROL false
-# define CONF_CLOCK_XOSC32K_ENABLE_1KHZ_OUPUT false
-# define CONF_CLOCK_XOSC32K_ENABLE_32KHZ_OUTPUT true
-# define CONF_CLOCK_XOSC32K_ON_DEMAND false
-# define CONF_CLOCK_XOSC32K_RUN_IN_STANDBY true
-
-/* SYSTEM_CLOCK_SOURCE_OSC32K configuration - Internal 32KHz oscillator */
-# define CONF_CLOCK_OSC32K_ENABLE false
-# define CONF_CLOCK_OSC32K_STARTUP_TIME SYSTEM_OSC32K_STARTUP_130
-# define CONF_CLOCK_OSC32K_ENABLE_1KHZ_OUTPUT true
-# define CONF_CLOCK_OSC32K_ENABLE_32KHZ_OUTPUT true
-# define CONF_CLOCK_OSC32K_ON_DEMAND true
-# define CONF_CLOCK_OSC32K_RUN_IN_STANDBY false
-
-/* SYSTEM_CLOCK_SOURCE_DFLL configuration - Digital Frequency Locked Loop */
-# define CONF_CLOCK_DFLL_ENABLE true
-# define CONF_CLOCK_DFLL_LOOP_MODE SYSTEM_CLOCK_DFLL_LOOP_MODE_CLOSED
-# define CONF_CLOCK_DFLL_ON_DEMAND true
-
-/* DFLL open loop mode configuration */
-# define CONF_CLOCK_DFLL_FINE_VALUE (512)
-
-/* DFLL closed loop mode configuration */
-# define CONF_CLOCK_DFLL_SOURCE_GCLK_GENERATOR GCLK_GENERATOR_1
-# define CONF_CLOCK_DFLL_MULTIPLY_FACTOR (48000000 / 32768)
-# define CONF_CLOCK_DFLL_QUICK_LOCK true
-# define CONF_CLOCK_DFLL_TRACK_AFTER_FINE_LOCK true
-# define CONF_CLOCK_DFLL_KEEP_LOCK_ON_WAKEUP true
-# define CONF_CLOCK_DFLL_ENABLE_CHILL_CYCLE true
-# define CONF_CLOCK_DFLL_MAX_COARSE_STEP_SIZE (0x1f / 4)
-# define CONF_CLOCK_DFLL_MAX_FINE_STEP_SIZE (0xff / 4)
-
-/* SYSTEM_CLOCK_SOURCE_DPLL configuration - Digital Phase-Locked Loop */
-# define CONF_CLOCK_DPLL_ENABLE false
-# define CONF_CLOCK_DPLL_ON_DEMAND true
-# define CONF_CLOCK_DPLL_RUN_IN_STANDBY false
-# define CONF_CLOCK_DPLL_LOCK_BYPASS false
-# define CONF_CLOCK_DPLL_WAKE_UP_FAST false
-# define CONF_CLOCK_DPLL_LOW_POWER_ENABLE false
-
-# define CONF_CLOCK_DPLL_LOCK_TIME SYSTEM_CLOCK_SOURCE_DPLL_LOCK_TIME_DEFAULT
-# define CONF_CLOCK_DPLL_REFERENCE_CLOCK SYSTEM_CLOCK_SOURCE_DPLL_REFERENCE_CLOCK_XOSC32K
-# define CONF_CLOCK_DPLL_FILTER SYSTEM_CLOCK_SOURCE_DPLL_FILTER_DEFAULT
-
-# define CONF_CLOCK_DPLL_REFERENCE_FREQUENCY 32768
-# define CONF_CLOCK_DPLL_REFERENCE_DIVIDER 1
-# define CONF_CLOCK_DPLL_OUTPUT_FREQUENCY 48000000
-
-/* DPLL GCLK reference configuration */
-# define CONF_CLOCK_DPLL_REFERENCE_GCLK_GENERATOR GCLK_GENERATOR_1
-/* DPLL GCLK lock timer configuration */
-# define CONF_CLOCK_DPLL_LOCK_GCLK_GENERATOR GCLK_GENERATOR_1
-
-/* Set this to true to configure the GCLK when running clocks_init. If set to
- * false, none of the GCLK generators will be configured in clocks_init(). */
-# define CONF_CLOCK_CONFIGURE_GCLK true
-
-/* Configure GCLK generator 0 (Main Clock) */
-# define CONF_CLOCK_GCLK_0_ENABLE true
-# define CONF_CLOCK_GCLK_0_RUN_IN_STANDBY true
-# define CONF_CLOCK_GCLK_0_CLOCK_SOURCE SYSTEM_CLOCK_SOURCE_DFLL
-# define CONF_CLOCK_GCLK_0_PRESCALER 1
-# define CONF_CLOCK_GCLK_0_OUTPUT_ENABLE false
-
-/* Configure GCLK generator 1 */
-# define CONF_CLOCK_GCLK_1_ENABLE true
-# define CONF_CLOCK_GCLK_1_RUN_IN_STANDBY false
-# define CONF_CLOCK_GCLK_1_CLOCK_SOURCE SYSTEM_CLOCK_SOURCE_XOSC32K
-# define CONF_CLOCK_GCLK_1_PRESCALER 1
-# define CONF_CLOCK_GCLK_1_OUTPUT_ENABLE true
-
-/* Configure GCLK generator 2 (RTC) */
-# define CONF_CLOCK_GCLK_2_ENABLE false
-# define CONF_CLOCK_GCLK_2_RUN_IN_STANDBY false
-# define CONF_CLOCK_GCLK_2_CLOCK_SOURCE SYSTEM_CLOCK_SOURCE_OSC32K
-# define CONF_CLOCK_GCLK_2_PRESCALER 32
-# define CONF_CLOCK_GCLK_2_OUTPUT_ENABLE false
-
-/* Configure GCLK generator 3 */
-# define CONF_CLOCK_GCLK_3_ENABLE true
-# define CONF_CLOCK_GCLK_3_RUN_IN_STANDBY false
-# define CONF_CLOCK_GCLK_3_CLOCK_SOURCE SYSTEM_CLOCK_SOURCE_OSC8M
-# define CONF_CLOCK_GCLK_3_PRESCALER 1
-# define CONF_CLOCK_GCLK_3_OUTPUT_ENABLE false
-
-/* Configure GCLK generator 4 */
-# define CONF_CLOCK_GCLK_4_ENABLE false
-# define CONF_CLOCK_GCLK_4_RUN_IN_STANDBY false
-# define CONF_CLOCK_GCLK_4_CLOCK_SOURCE SYSTEM_CLOCK_SOURCE_OSC8M
-# define CONF_CLOCK_GCLK_4_PRESCALER 1
-# define CONF_CLOCK_GCLK_4_OUTPUT_ENABLE false
-
-/* Configure GCLK generator 5 */
-# define CONF_CLOCK_GCLK_5_ENABLE false
-# define CONF_CLOCK_GCLK_5_RUN_IN_STANDBY false
-# define CONF_CLOCK_GCLK_5_CLOCK_SOURCE SYSTEM_CLOCK_SOURCE_OSC8M
-# define CONF_CLOCK_GCLK_5_PRESCALER 1
-# define CONF_CLOCK_GCLK_5_OUTPUT_ENABLE false
-
-/* Configure GCLK generator 6 */
-# define CONF_CLOCK_GCLK_6_ENABLE false
-# define CONF_CLOCK_GCLK_6_RUN_IN_STANDBY false
-# define CONF_CLOCK_GCLK_6_CLOCK_SOURCE SYSTEM_CLOCK_SOURCE_OSC8M
-# define CONF_CLOCK_GCLK_6_PRESCALER 1
-# define CONF_CLOCK_GCLK_6_OUTPUT_ENABLE false
-
-/* Configure GCLK generator 7 */
-# define CONF_CLOCK_GCLK_7_ENABLE false
-# define CONF_CLOCK_GCLK_7_RUN_IN_STANDBY false
-# define CONF_CLOCK_GCLK_7_CLOCK_SOURCE SYSTEM_CLOCK_SOURCE_OSC8M
-# define CONF_CLOCK_GCLK_7_PRESCALER 1
-# define CONF_CLOCK_GCLK_7_OUTPUT_ENABLE false
-
-/* Configure GCLK generator 8 */
-# define CONF_CLOCK_GCLK_8_ENABLE false
-# define CONF_CLOCK_GCLK_8_RUN_IN_STANDBY false
-# define CONF_CLOCK_GCLK_8_CLOCK_SOURCE SYSTEM_CLOCK_SOURCE_OSC8M
-# define CONF_CLOCK_GCLK_8_PRESCALER 1
-# define CONF_CLOCK_GCLK_8_OUTPUT_ENABLE false
-
-#endif /* CONF_CLOCKS_H_INCLUDED */
diff --git a/atmel-samd/boards/feather_m0_bluefruit_le/conf_sleepmgr.h b/atmel-samd/boards/feather_m0_bluefruit_le/conf_sleepmgr.h
deleted file mode 100644
index 281a36078..000000000
--- a/atmel-samd/boards/feather_m0_bluefruit_le/conf_sleepmgr.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/**
- * \file
- *
- * \brief Sleep manager configuration
- *
- * Copyright (c) 2014-2015 Atmel Corporation. All rights reserved.
- *
- * \asf_license_start
- *
- * \page License
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * 3. The name of Atmel may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * 4. This software may only be redistributed and used in connection with an
- * Atmel microcontroller product.
- *
- * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
- * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- * \asf_license_stop
- *
- */
-/*
- * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
- */
-
-#ifndef CONF_SLEEPMGR_H_INCLUDED
-#define CONF_SLEEPMGR_H_INCLUDED
-
-#define CONFIG_SLEEPMGR_ENABLE
-
-#endif /* CONF_SLEEPMGR_H_INCLUDED */
diff --git a/atmel-samd/boards/feather_m0_bluefruit_le/user_board.h b/atmel-samd/boards/feather_m0_bluefruit_le/user_board.h
deleted file mode 100644
index 39980a7d2..000000000
--- a/atmel-samd/boards/feather_m0_bluefruit_le/user_board.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/**
- * \file
- *
- * \brief User board definition template
- *
- */
-
- /* This file is intended to contain definitions and configuration details for
- * features and devices that are available on the board, e.g., frequency and
- * startup time for an external crystal, external memory devices, LED and USART
- * pins.
- */
-/*
- * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
- */
-
-#ifndef USER_BOARD_H
-#define USER_BOARD_H
-
-#include <conf_board.h>
-
-// External oscillator settings.
-// Uncomment and set correct values if external oscillator is used.
-
-// External oscillator frequency
-//#define BOARD_XOSC_HZ 8000000
-
-// External oscillator type.
-//!< External clock signal
-//#define BOARD_XOSC_TYPE XOSC_TYPE_EXTERNAL
-//!< 32.768 kHz resonator on TOSC
-//#define BOARD_XOSC_TYPE XOSC_TYPE_32KHZ
-//!< 0.4 to 16 MHz resonator on XTALS
-//#define BOARD_XOSC_TYPE XOSC_TYPE_XTAL
-
-// External oscillator startup time
-//#define BOARD_XOSC_STARTUP_US 500000
-
-
-#endif // USER_BOARD_H
diff --git a/atmel-samd/boards/metro_m0_flash/conf_clocks.h b/atmel-samd/boards/metro_m0_flash/conf_clocks.h
deleted file mode 100644
index 20ee967e2..000000000
--- a/atmel-samd/boards/metro_m0_flash/conf_clocks.h
+++ /dev/null
@@ -1,197 +0,0 @@
-/**
- * \file
- *
- * \brief SAM D21 Clock configuration
- *
- * Copyright (C) 2014-2015 Atmel Corporation. All rights reserved.
- *
- * \asf_license_start
- *
- * \page License
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * 3. The name of Atmel may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * 4. This software may only be redistributed and used in connection with an
- * Atmel microcontroller product.
- *
- * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
- * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- * \asf_license_stop
- *
- */
-/*
- * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
- */
-#include <clock.h>
-
-#ifndef CONF_CLOCKS_H_INCLUDED
-# define CONF_CLOCKS_H_INCLUDED
-
-/* System clock bus configuration */
-# define CONF_CLOCK_CPU_CLOCK_FAILURE_DETECT false
-# define CONF_CLOCK_FLASH_WAIT_STATES 2
-# define CONF_CLOCK_CPU_DIVIDER SYSTEM_MAIN_CLOCK_DIV_1
-# define CONF_CLOCK_APBA_DIVIDER SYSTEM_MAIN_CLOCK_DIV_1
-# define CONF_CLOCK_APBB_DIVIDER SYSTEM_MAIN_CLOCK_DIV_1
-# define CONF_CLOCK_APBC_DIVIDER SYSTEM_MAIN_CLOCK_DIV_1
-
-/* SYSTEM_CLOCK_SOURCE_OSC8M configuration - Internal 8MHz oscillator */
-# define CONF_CLOCK_OSC8M_PRESCALER SYSTEM_OSC8M_DIV_1
-# define CONF_CLOCK_OSC8M_ON_DEMAND true
-# define CONF_CLOCK_OSC8M_RUN_IN_STANDBY false
-
-/* SYSTEM_CLOCK_SOURCE_XOSC configuration - External clock/oscillator */
-# define CONF_CLOCK_XOSC_ENABLE false
-# define CONF_CLOCK_XOSC_EXTERNAL_CRYSTAL SYSTEM_CLOCK_EXTERNAL_CRYSTAL
-# define CONF_CLOCK_XOSC_EXTERNAL_FREQUENCY 12000000UL
-# define CONF_CLOCK_XOSC_STARTUP_TIME SYSTEM_XOSC_STARTUP_32768
-# define CONF_CLOCK_XOSC_AUTO_GAIN_CONTROL true
-# define CONF_CLOCK_XOSC_ON_DEMAND true
-# define CONF_CLOCK_XOSC_RUN_IN_STANDBY false
-
-/* SYSTEM_CLOCK_SOURCE_XOSC32K configuration - External 32KHz crystal/clock oscillator */
-# define CONF_CLOCK_XOSC32K_ENABLE true
-# define CONF_CLOCK_XOSC32K_EXTERNAL_CRYSTAL SYSTEM_CLOCK_EXTERNAL_CRYSTAL
-# define CONF_CLOCK_XOSC32K_STARTUP_TIME SYSTEM_XOSC32K_STARTUP_65536
-# define CONF_CLOCK_XOSC32K_AUTO_AMPLITUDE_CONTROL false
-# define CONF_CLOCK_XOSC32K_ENABLE_1KHZ_OUPUT false
-# define CONF_CLOCK_XOSC32K_ENABLE_32KHZ_OUTPUT true
-# define CONF_CLOCK_XOSC32K_ON_DEMAND false
-# define CONF_CLOCK_XOSC32K_RUN_IN_STANDBY true
-
-/* SYSTEM_CLOCK_SOURCE_OSC32K configuration - Internal 32KHz oscillator */
-# define CONF_CLOCK_OSC32K_ENABLE false
-# define CONF_CLOCK_OSC32K_STARTUP_TIME SYSTEM_OSC32K_STARTUP_130
-# define CONF_CLOCK_OSC32K_ENABLE_1KHZ_OUTPUT true
-# define CONF_CLOCK_OSC32K_ENABLE_32KHZ_OUTPUT true
-# define CONF_CLOCK_OSC32K_ON_DEMAND true
-# define CONF_CLOCK_OSC32K_RUN_IN_STANDBY false
-
-/* SYSTEM_CLOCK_SOURCE_DFLL configuration - Digital Frequency Locked Loop */
-# define CONF_CLOCK_DFLL_ENABLE true
-# define CONF_CLOCK_DFLL_LOOP_MODE SYSTEM_CLOCK_DFLL_LOOP_MODE_CLOSED
-# define CONF_CLOCK_DFLL_ON_DEMAND true
-
-/* DFLL open loop mode configuration */
-# define CONF_CLOCK_DFLL_FINE_VALUE (512)
-
-/* DFLL closed loop mode configuration */
-# define CONF_CLOCK_DFLL_SOURCE_GCLK_GENERATOR GCLK_GENERATOR_1
-# define CONF_CLOCK_DFLL_MULTIPLY_FACTOR (48000000 / 32768)
-# define CONF_CLOCK_DFLL_QUICK_LOCK true
-# define CONF_CLOCK_DFLL_TRACK_AFTER_FINE_LOCK true
-# define CONF_CLOCK_DFLL_KEEP_LOCK_ON_WAKEUP true
-# define CONF_CLOCK_DFLL_ENABLE_CHILL_CYCLE true
-# define CONF_CLOCK_DFLL_MAX_COARSE_STEP_SIZE (0x1f / 4)
-# define CONF_CLOCK_DFLL_MAX_FINE_STEP_SIZE (0xff / 4)
-
-/* SYSTEM_CLOCK_SOURCE_DPLL configuration - Digital Phase-Locked Loop */
-# define CONF_CLOCK_DPLL_ENABLE false
-# define CONF_CLOCK_DPLL_ON_DEMAND true
-# define CONF_CLOCK_DPLL_RUN_IN_STANDBY false
-# define CONF_CLOCK_DPLL_LOCK_BYPASS false
-# define CONF_CLOCK_DPLL_WAKE_UP_FAST false
-# define CONF_CLOCK_DPLL_LOW_POWER_ENABLE false
-
-# define CONF_CLOCK_DPLL_LOCK_TIME SYSTEM_CLOCK_SOURCE_DPLL_LOCK_TIME_DEFAULT
-# define CONF_CLOCK_DPLL_REFERENCE_CLOCK SYSTEM_CLOCK_SOURCE_DPLL_REFERENCE_CLOCK_XOSC32K
-# define CONF_CLOCK_DPLL_FILTER SYSTEM_CLOCK_SOURCE_DPLL_FILTER_DEFAULT
-
-# define CONF_CLOCK_DPLL_REFERENCE_FREQUENCY 32768
-# define CONF_CLOCK_DPLL_REFERENCE_DIVIDER 1
-# define CONF_CLOCK_DPLL_OUTPUT_FREQUENCY 48000000
-
-/* DPLL GCLK reference configuration */
-# define CONF_CLOCK_DPLL_REFERENCE_GCLK_GENERATOR GCLK_GENERATOR_1
-/* DPLL GCLK lock timer configuration */
-# define CONF_CLOCK_DPLL_LOCK_GCLK_GENERATOR GCLK_GENERATOR_1
-
-/* Set this to true to configure the GCLK when running clocks_init. If set to
- * false, none of the GCLK generators will be configured in clocks_init(). */
-# define CONF_CLOCK_CONFIGURE_GCLK true
-
-/* Configure GCLK generator 0 (Main Clock) */
-# define CONF_CLOCK_GCLK_0_ENABLE true
-# define CONF_CLOCK_GCLK_0_RUN_IN_STANDBY true
-# define CONF_CLOCK_GCLK_0_CLOCK_SOURCE SYSTEM_CLOCK_SOURCE_DFLL
-# define CONF_CLOCK_GCLK_0_PRESCALER 1
-# define CONF_CLOCK_GCLK_0_OUTPUT_ENABLE false
-
-/* Configure GCLK generator 1 */
-# define CONF_CLOCK_GCLK_1_ENABLE true
-# define CONF_CLOCK_GCLK_1_RUN_IN_STANDBY false
-# define CONF_CLOCK_GCLK_1_CLOCK_SOURCE SYSTEM_CLOCK_SOURCE_XOSC32K
-# define CONF_CLOCK_GCLK_1_PRESCALER 1
-# define CONF_CLOCK_GCLK_1_OUTPUT_ENABLE true
-
-/* Configure GCLK generator 2 (RTC) */
-# define CONF_CLOCK_GCLK_2_ENABLE false
-# define CONF_CLOCK_GCLK_2_RUN_IN_STANDBY false
-# define CONF_CLOCK_GCLK_2_CLOCK_SOURCE SYSTEM_CLOCK_SOURCE_OSC32K
-# define CONF_CLOCK_GCLK_2_PRESCALER 32
-# define CONF_CLOCK_GCLK_2_OUTPUT_ENABLE false
-
-/* Configure GCLK generator 3 */
-# define CONF_CLOCK_GCLK_3_ENABLE true
-# define CONF_CLOCK_GCLK_3_RUN_IN_STANDBY false
-# define CONF_CLOCK_GCLK_3_CLOCK_SOURCE SYSTEM_CLOCK_SOURCE_OSC8M
-# define CONF_CLOCK_GCLK_3_PRESCALER 1
-# define CONF_CLOCK_GCLK_3_OUTPUT_ENABLE false
-
-/* Configure GCLK generator 4 */
-# define CONF_CLOCK_GCLK_4_ENABLE false
-# define CONF_CLOCK_GCLK_4_RUN_IN_STANDBY false
-# define CONF_CLOCK_GCLK_4_CLOCK_SOURCE SYSTEM_CLOCK_SOURCE_OSC8M
-# define CONF_CLOCK_GCLK_4_PRESCALER 1
-# define CONF_CLOCK_GCLK_4_OUTPUT_ENABLE false
-
-/* Configure GCLK generator 5 */
-# define CONF_CLOCK_GCLK_5_ENABLE false
-# define CONF_CLOCK_GCLK_5_RUN_IN_STANDBY false
-# define CONF_CLOCK_GCLK_5_CLOCK_SOURCE SYSTEM_CLOCK_SOURCE_OSC8M
-# define CONF_CLOCK_GCLK_5_PRESCALER 1
-# define CONF_CLOCK_GCLK_5_OUTPUT_ENABLE false
-
-/* Configure GCLK generator 6 */
-# define CONF_CLOCK_GCLK_6_ENABLE false
-# define CONF_CLOCK_GCLK_6_RUN_IN_STANDBY false
-# define CONF_CLOCK_GCLK_6_CLOCK_SOURCE SYSTEM_CLOCK_SOURCE_OSC8M
-# define CONF_CLOCK_GCLK_6_PRESCALER 1
-# define CONF_CLOCK_GCLK_6_OUTPUT_ENABLE false
-
-/* Configure GCLK generator 7 */
-# define CONF_CLOCK_GCLK_7_ENABLE false
-# define CONF_CLOCK_GCLK_7_RUN_IN_STANDBY false
-# define CONF_CLOCK_GCLK_7_CLOCK_SOURCE SYSTEM_CLOCK_SOURCE_OSC8M
-# define CONF_CLOCK_GCLK_7_PRESCALER 1
-# define CONF_CLOCK_GCLK_7_OUTPUT_ENABLE false
-
-/* Configure GCLK generator 8 */
-# define CONF_CLOCK_GCLK_8_ENABLE false
-# define CONF_CLOCK_GCLK_8_RUN_IN_STANDBY false
-# define CONF_CLOCK_GCLK_8_CLOCK_SOURCE SYSTEM_CLOCK_SOURCE_OSC8M
-# define CONF_CLOCK_GCLK_8_PRESCALER 1
-# define CONF_CLOCK_GCLK_8_OUTPUT_ENABLE false
-
-#endif /* CONF_CLOCKS_H_INCLUDED */
diff --git a/atmel-samd/boards/metro_m0_flash/pins.c b/atmel-samd/boards/metro_m0_flash/pins.c
index db0c6ee4c..26754b4f4 100644
--- a/atmel-samd/boards/metro_m0_flash/pins.c
+++ b/atmel-samd/boards/metro_m0_flash/pins.c
@@ -121,7 +121,7 @@ PIN(PB10, false, NO_ADC_INPUT,
PIN(PA12, false, NO_ADC_INPUT,
TIMER(0, TCC2, 0, 0, PIN_PA12E_TCC2_WO0, MUX_PA12E_TCC2_WO0),
TIMER(0, TCC0, 2, 6, PIN_PA12F_TCC0_WO6, MUX_PA12F_TCC0_WO6),
- SERCOM(SERCOM4, 0, PINMUX_PA12D_SERCOM4_PAD0),
+ SERCOM(SERCOM4, 0, PINMUX_PA12D_SERCOM4_PAD0),
SERCOM(SERCOM2, 0, PINMUX_PA12C_SERCOM2_PAD0));
PIN(PA13, false, NO_ADC_INPUT,
TIMER(0, TCC2, 1, 1, PIN_PA13E_TCC2_WO1, MUX_PA13E_TCC2_WO1),
diff --git a/atmel-samd/boards/metro_m0_flash/user_board.h b/atmel-samd/boards/metro_m0_flash/user_board.h
deleted file mode 100644
index 39980a7d2..000000000
--- a/atmel-samd/boards/metro_m0_flash/user_board.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/**
- * \file
- *
- * \brief User board definition template
- *
- */
-
- /* This file is intended to contain definitions and configuration details for
- * features and devices that are available on the board, e.g., frequency and
- * startup time for an external crystal, external memory devices, LED and USART
- * pins.
- */
-/*
- * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
- */
-
-#ifndef USER_BOARD_H
-#define USER_BOARD_H
-
-#include <conf_board.h>
-
-// External oscillator settings.
-// Uncomment and set correct values if external oscillator is used.
-
-// External oscillator frequency
-//#define BOARD_XOSC_HZ 8000000
-
-// External oscillator type.
-//!< External clock signal
-//#define BOARD_XOSC_TYPE XOSC_TYPE_EXTERNAL
-//!< 32.768 kHz resonator on TOSC
-//#define BOARD_XOSC_TYPE XOSC_TYPE_32KHZ
-//!< 0.4 to 16 MHz resonator on XTALS
-//#define BOARD_XOSC_TYPE XOSC_TYPE_XTAL
-
-// External oscillator startup time
-//#define BOARD_XOSC_STARTUP_US 500000
-
-
-#endif // USER_BOARD_H
diff --git a/atmel-samd/common-hal/modules/machine.c b/atmel-samd/common-hal/modules/machine.c
index a43762e0f..b0558cd5c 100644
--- a/atmel-samd/common-hal/modules/machine.c
+++ b/atmel-samd/common-hal/modules/machine.c
@@ -205,3 +205,63 @@ void mp_hal_i2c_read_mem(machine_i2c_obj_t *self, uint8_t addr, uint16_t memaddr
mp_hal_i2c_read(self, addr, dest, len);
return;
}
+
+void mp_hal_spi_construct(machine_spi_obj_t *self, const pin_obj_t * clock,
+ const pin_obj_t * mosi, const pin_obj_t * miso,
+ uint32_t baudrate) {
+ struct spi_config config_spi_master;
+ spi_get_config_defaults(&config_spi_master);
+
+ // Depends on where MOSI and CLK are.
+ uint8_t dopo = 8;
+ if (clock->primary_sercom.pad == 1) {
+ if (mosi->primary_sercom.pad == 0) {
+ dopo = 0;
+ } else if (mosi->primary_sercom.pad == 3) {
+ dopo = 2;
+ }
+ } else if (clock->primary_sercom.pad == 3) {
+ if (mosi->primary_sercom.pad == 0) {
+ dopo = 3;
+ } else if (mosi->primary_sercom.pad == 2) {
+ dopo = 1;
+ }
+ }
+ if (dopo == 8) {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "SPI MOSI and clock pins incompatible."));
+ }
+
+ config_spi_master.mux_setting = (dopo << SERCOM_SPI_CTRLA_DOPO_Pos) |
+ (miso->primary_sercom.pad << SERCOM_SPI_CTRLA_DIPO_Pos);
+
+ // Map pad to pinmux through a short array.
+ uint32_t *pinmuxes[4] = {&config_spi_master.pinmux_pad0,
+ &config_spi_master.pinmux_pad1,
+ &config_spi_master.pinmux_pad2,
+ &config_spi_master.pinmux_pad3};
+ *pinmuxes[clock->primary_sercom.pad] = clock->primary_sercom.pinmux;
+ *pinmuxes[mosi->primary_sercom.pad] = mosi->primary_sercom.pinmux;
+ *pinmuxes[miso->primary_sercom.pad] = miso->primary_sercom.pinmux;
+
+ config_spi_master.mode_specific.master.baudrate = baudrate;
+
+ spi_init(&self->spi_master_instance, mosi->primary_sercom.sercom, &config_spi_master);
+}
+
+void mp_hal_spi_init(machine_spi_obj_t *self) {
+ spi_enable(&self->spi_master_instance);
+}
+
+void mp_hal_spi_deinit(machine_spi_obj_t *self) {
+ spi_disable(&self->spi_master_instance);
+}
+
+void mp_hal_spi_transfer(machine_spi_obj_t *self, size_t len, const uint8_t *src,
+ uint8_t *dest) {
+ // TODO(tannewt): Don't cast away the const. Change ASF to respect it instead.
+ enum status_code status = spi_transceive_buffer_wait(
+ &self->spi_master_instance, (uint8_t *) src, dest, len);
+ if (status != STATUS_OK) {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "SPI bus error"));
+ }
+}
diff --git a/atmel-samd/common-hal/modules/machine_types.h b/atmel-samd/common-hal/modules/machine_types.h
index 00fe99825..2267115d3 100644
--- a/atmel-samd/common-hal/modules/machine_types.h
+++ b/atmel-samd/common-hal/modules/machine_types.h
@@ -42,6 +42,7 @@
#include "asf/sam0/drivers/adc/adc_sam_d_r/adc_feature.h"
#include "asf/sam0/drivers/sercom/i2c/i2c_master.h"
+#include "asf/sam0/drivers/sercom/spi/spi.h"
#include "py/obj.h"
@@ -77,4 +78,9 @@ typedef struct _machine_i2c_obj_t {
struct i2c_master_module i2c_master_instance;
} machine_i2c_obj_t;
+typedef struct _machine_spi_obj_t {
+ mp_obj_base_t base;
+ struct spi_module spi_master_instance;
+} machine_spi_obj_t;
+
#endif // __MICROPY_INCLUDED_ATMEL_SAMD_API_MACHINE_TYPES_H__
diff --git a/atmel-samd/modmachine.c b/atmel-samd/modmachine.c
index b09abac30..67bccc5fd 100644
--- a/atmel-samd/modmachine.c
+++ b/atmel-samd/modmachine.c
@@ -50,6 +50,7 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&pin_type) },
{ MP_ROM_QSTR(MP_QSTR_PWM), MP_ROM_PTR(&pwm_type) },
{ MP_ROM_QSTR(MP_QSTR_Flash), MP_ROM_PTR(&flash_type) },
+ { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&machine_spi_type) },
};
STATIC MP_DEFINE_CONST_DICT(machine_module_globals, machine_module_globals_table);
diff --git a/shared-bindings/modules/machine.c b/shared-bindings/modules/machine.c
index 46ef7d92e..b16ab8aae 100644
--- a/shared-bindings/modules/machine.c
+++ b/shared-bindings/modules/machine.c
@@ -45,8 +45,19 @@
//|
//| I2C objects are created attached to a specific bus. They can be initialised
//| when created, or initialised later on.
-
-STATIC void machine_i2c_obj_init_helper(machine_i2c_obj_t *self, mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+//|
+//| Constructors
+//| ------------
+//| .. class:: I2C(scl, sda, \*, freq=400000)
+//|
+//| Construct and return a new I2C object.
+//| See the init method below for a description of the arguments.
+STATIC mp_obj_t machine_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *pos_args) {
+ mp_arg_check_num(n_args, n_kw, 0, MP_OBJ_FUN_ARGS_MAX, true);
+ machine_i2c_obj_t *self = m_new_obj(machine_i2c_obj_t);
+ self->base.type = &machine_i2c_type;
+ mp_map_t kw_args;
+ mp_map_init_fixed_table(&kw_args, n_kw, pos_args + n_args);
enum { ARG_scl, ARG_sda, ARG_freq };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_scl, MP_ARG_REQUIRED | MP_ARG_OBJ },
@@ -54,26 +65,11 @@ STATIC void machine_i2c_obj_init_helper(machine_i2c_obj_t *self, mp_uint_t n_arg
{ MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 400000} },
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
- mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+ mp_arg_parse_all(n_args, pos_args, &kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
// TODO(tannewt): Replace pin_find with a unified version.
const pin_obj_t* scl = pin_find(args[ARG_scl].u_obj);
const pin_obj_t* sda = pin_find(args[ARG_sda].u_obj);
mp_hal_i2c_construct(self, scl, sda, args[ARG_freq].u_int);
-}
-
-//| Constructors
-//| ------------
-//| .. class:: I2C(scl, sda, \*, freq=400000)
-//|
-//| Construct and return a new I2C object.
-//| See the init method below for a description of the arguments.
-STATIC mp_obj_t machine_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
- mp_arg_check_num(n_args, n_kw, 0, MP_OBJ_FUN_ARGS_MAX, true);
- machine_i2c_obj_t *self = m_new_obj(machine_i2c_obj_t);
- self->base.type = &machine_i2c_type;
- mp_map_t kw_args;
- mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
- machine_i2c_obj_init_helper(self, n_args, args, &kw_args);
return (mp_obj_t)self;
}
@@ -281,6 +277,7 @@ STATIC const mp_rom_map_elem_t machine_i2c_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_writeto), MP_ROM_PTR(&machine_i2c_writeto_obj) },
// memory operations
+ // TODO(tannewt): Move these into a separate loadable Python module.
{ MP_ROM_QSTR(MP_QSTR_readfrom_mem), MP_ROM_PTR(&machine_i2c_readfrom_mem_obj) },
{ MP_ROM_QSTR(MP_QSTR_readfrom_mem_into), MP_ROM_PTR(&machine_i2c_readfrom_mem_into_obj) },
{ MP_ROM_QSTR(MP_QSTR_writeto_mem), MP_ROM_PTR(&machine_i2c_writeto_mem_obj) },
@@ -294,3 +291,173 @@ const mp_obj_type_t machine_i2c_type = {
.make_new = machine_i2c_make_new,
.locals_dict = (mp_obj_dict_t*)&machine_i2c_locals_dict,
};
+
+//| class SPI -- a master-driven serial protocol
+//| ============================================
+//|
+//| SPI is a serial protocol that is driven by a master. This class only
+//| manages three of the four SPI lines: SCK, MOSI, MISO. Its up to the client
+//| to manage the appropriate slave select line.
+//|
+//| Constructors
+//| ------------
+//|
+//| .. class:: SPI(clock, MOSI, MISO, baudrate=1000000)
+//|
+//| Construct an SPI object on the given bus. ``id`` can be only 0.
+//| With no additional parameters, the SPI object is created but not
+//| initialised (it has the settings from the last initialisation of
+//| the bus, if any). If extra arguments are given, the bus is initialised.
+//| See ``init`` for parameters of initialisation.
+//|
+//| - ``clock`` is the pin to use for the clock.
+//| - ``MOSI`` is the Master Out Slave In pin.
+//| - ``MISO`` is the Master In Slave Out pin.
+//| - ``baudrate`` is the SCK clock rate.
+//|
+//| Methods
+//| -------
+//|
+
+// TODO(tannewt): Support LSB SPI.
+// TODO(tannewt): Support phase, polarity and bit order.
+STATIC mp_obj_t machine_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *pos_args) {
+ mp_arg_check_num(n_args, n_kw, 0, MP_OBJ_FUN_ARGS_MAX, true);
+ machine_spi_obj_t *self = m_new_obj(machine_spi_obj_t);
+ self->base.type = &machine_spi_type;
+ mp_map_t kw_args;
+ mp_map_init_fixed_table(&kw_args, n_kw, pos_args + n_args);
+ enum { ARG_clock, ARG_MOSI, ARG_MISO, ARG_baudrate, ARG_polarity, ARG_phase, ARG_bits, ARG_firstbit };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_clock, MP_ARG_REQUIRED | MP_ARG_OBJ },
+ { MP_QSTR_MOSI, MP_ARG_REQUIRED | MP_ARG_OBJ },
+ { MP_QSTR_MISO, MP_ARG_REQUIRED | MP_ARG_OBJ },
+ { MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 100000} },
+ { MP_QSTR_polarity, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 400000} },
+ { MP_QSTR_phase, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 400000} },
+ { MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} },
+ };
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all(n_args, pos_args, &kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+ // TODO(tannewt): Replace pin_find with a unified version.
+ const pin_obj_t* clock = pin_find(args[ARG_clock].u_obj);
+ const pin_obj_t* mosi = pin_find(args[ARG_MOSI].u_obj);
+ const pin_obj_t* miso = pin_find(args[ARG_MISO].u_obj);
+ mp_hal_spi_construct(self, clock, mosi, miso, args[ARG_baudrate].u_int);
+ return (mp_obj_t)self;
+}
+
+//| .. method:: SPI.init()
+//|
+//| Initialises the bus.
+STATIC mp_obj_t machine_spi_obj_init(mp_obj_t self_in) {
+ machine_spi_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ mp_hal_spi_init(self);
+ return self_in;
+}
+MP_DEFINE_CONST_FUN_OBJ_1(machine_spi_init_obj, machine_spi_obj_init);
+
+//| .. method:: SPI.deinit()
+//|
+//| Turn off the SPI bus.
+STATIC mp_obj_t machine_spi_obj_deinit(mp_obj_t self_in) {
+ machine_spi_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ mp_hal_spi_deinit(self);
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_1(machine_spi_deinit_obj, machine_spi_obj_deinit);
+
+STATIC mp_obj_t machine_spi_obj___exit__(size_t n_args, const mp_obj_t *args) {
+ (void)n_args;
+ mp_hal_spi_deinit(args[0]);
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_spi_obj___exit___obj, 4, 4, machine_spi_obj___exit__);
+
+//| .. method:: SPI.write_readinto(write_buf, read_buf)
+//|
+//| Write from ``write_buf`` and read into ``read_buf``. Both buffers must have the
+//| same length. This is the same as a SPI transfer function on other platforms.
+//| Returns the number of bytes written
+STATIC mp_obj_t mp_machine_spi_write_readinto(mp_obj_t self_in, mp_obj_t wr_buf, mp_obj_t rd_buf) {
+ mp_buffer_info_t src;
+ mp_get_buffer_raise(wr_buf, &src, MP_BUFFER_READ);
+ mp_buffer_info_t dest;
+ mp_get_buffer_raise(rd_buf, &dest, MP_BUFFER_WRITE);
+ if (src.len != dest.len) {
+ mp_raise_ValueError("buffers must be the same length");
+ }
+ machine_spi_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ mp_hal_spi_transfer(self, src.len, (uint8_t *) src.buf, (uint8_t *) dest.buf);
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_3(mp_machine_spi_write_readinto_obj, mp_machine_spi_write_readinto);
+
+//| Helper operations
+//| -----------------
+//| The below operations are finer grained operations based upon ``SPI.write_readinto``.
+//| They may be moved out of the core module later.
+//|
+//| .. method:: SPI.write(buf)
+//|
+//| Write the data contained in ``buf``.
+//| Returns the number of bytes written.
+STATIC mp_obj_t mp_machine_spi_write(mp_obj_t self_in, mp_obj_t wr_buf) {
+ mp_buffer_info_t src;
+ mp_get_buffer_raise(wr_buf, &src, MP_BUFFER_READ);
+ machine_spi_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ mp_hal_spi_transfer(self, src.len, (uint8_t *) src.buf, NULL);
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_2(mp_machine_spi_write_obj, mp_machine_spi_write);
+
+//| .. method:: SPI.read(nbytes, *, write=0x00)
+//|
+//| Read the ``nbytes`` while writing the data specified by ``write``.
+//| Return the number of bytes read.
+STATIC mp_obj_t mp_machine_spi_read(size_t n_args, const mp_obj_t *args) {
+ vstr_t vstr;
+ vstr_init_len(&vstr, mp_obj_get_int(args[1]));
+ memset(vstr.buf, n_args == 3 ? mp_obj_get_int(args[2]) : 0, vstr.len);
+ mp_hal_spi_transfer(args[0], vstr.len, (uint8_t *) vstr.buf, (uint8_t *) vstr.buf);
+ return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
+}
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_machine_spi_read_obj, 2, 3, mp_machine_spi_read);
+
+//| .. method:: SPI.readinto(buf, *, write=0x00)
+//|
+//| Read into the buffer specified by ``buf`` while writing the data specified by
+//| ``write``.
+//| Return the number of bytes read.
+STATIC mp_obj_t mp_machine_spi_readinto(size_t n_args, const mp_obj_t *args) {
+ mp_buffer_info_t bufinfo;
+ mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_WRITE);
+ memset(bufinfo.buf, n_args == 3 ? mp_obj_get_int(args[2]) : 0, bufinfo.len);
+ mp_hal_spi_transfer(args[0], bufinfo.len, (uint8_t *) bufinfo.buf, (uint8_t *) bufinfo.buf);
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_machine_spi_readinto_obj, 2, 3, mp_machine_spi_readinto);
+
+STATIC const mp_rom_map_elem_t machine_spi_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_spi_init_obj) },
+ { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_spi_deinit_obj) },
+ { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&machine_spi_init_obj) },
+ { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&machine_spi_obj___exit___obj) },
+
+ // Standard simultaneous read/write transfer.
+ { MP_ROM_QSTR(MP_QSTR_write_readinto), MP_ROM_PTR(&mp_machine_spi_write_readinto_obj) },
+
+ // Helper methods.
+ // TODO(tannewt): Move these into a helper Python class.
+ { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_machine_spi_read_obj) },
+ { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_machine_spi_readinto_obj) },
+ { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_machine_spi_write_obj) },
+};
+STATIC MP_DEFINE_CONST_DICT(machine_spi_locals_dict, machine_spi_locals_dict_table);
+
+const mp_obj_type_t machine_spi_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_SPI,
+ .make_new = machine_spi_make_new,
+ .locals_dict = (mp_obj_dict_t*)&machine_spi_locals_dict,
+};
diff --git a/shared-bindings/modules/machine.h b/shared-bindings/modules/machine.h
index 66b0ae465..a3f8a4a0c 100644
--- a/shared-bindings/modules/machine.h
+++ b/shared-bindings/modules/machine.h
@@ -49,6 +49,7 @@
// Type object used in Python. Should be shared between ports.
extern const mp_obj_type_t machine_i2c_type;
+extern const mp_obj_type_t machine_spi_type;
// Initializes the hardware peripheral.
extern void mp_hal_i2c_construct(machine_i2c_obj_t *self, const pin_obj_t * scl,
@@ -76,5 +77,16 @@ extern void mp_hal_i2c_write_mem(machine_i2c_obj_t *self, uint8_t addr,
uint16_t memaddr, const uint8_t *src,
size_t len);
+// Construct an underlying SPI object.
+extern void mp_hal_spi_construct(machine_spi_obj_t *self, const pin_obj_t * clock,
+ const pin_obj_t * mosi, const pin_obj_t * miso,
+ uint32_t baudrate);
+
+extern void mp_hal_spi_init(machine_spi_obj_t *self);
+extern void mp_hal_spi_deinit(machine_spi_obj_t *self);
+
+// Concurrently write and read len bytes from the SPI port. Chip select is
+// handled externally.
+extern void mp_hal_spi_transfer(machine_spi_obj_t *self, size_t len, const uint8_t *src, uint8_t *dest);
#endif // __MICROPY_INCLUDED_API_MACHINE_H__