diff options
| author | Jeff Epler <jepler@gmail.com> | 2020-06-26 10:58:54 -0500 |
|---|---|---|
| committer | Jeff Epler <jepler@gmail.com> | 2020-06-26 11:50:42 -0500 |
| commit | f496c0b58d63f594ce42bd5b34cf8421674b4108 (patch) | |
| tree | f9db3d3e9db51a6a08ef9cabdff1c5e55c550eec | |
| parent | d4b945851285c0b5d3a38094223d97184449e7e1 (diff) | |
atmel-samd: Add SDIO SD card interface
| -rw-r--r-- | locale/circuitpython.pot | 10 | ||||
| -rw-r--r-- | ports/atmel-samd/Makefile | 15 | ||||
| m--------- | ports/atmel-samd/asf4 | 0 | ||||
| -rw-r--r-- | ports/atmel-samd/asf4_conf/samd51/hpl_sdhc_config.h | 24 | ||||
| -rw-r--r-- | ports/atmel-samd/asf4_conf/samd51/peripheral_clk_config.h | 164 | ||||
| -rw-r--r-- | ports/atmel-samd/asf4_conf/same54/hpl_sdhc_config.h | 24 | ||||
| -rw-r--r-- | ports/atmel-samd/asf4_conf/same54/peripheral_clk_config.h | 164 | ||||
| -rw-r--r-- | ports/atmel-samd/boards/grandcentral_m4_express/mpconfigboard.mk | 2 | ||||
| -rw-r--r-- | ports/atmel-samd/boards/grandcentral_m4_express/pins.c | 17 | ||||
| -rw-r--r-- | ports/atmel-samd/boards/same54_xplained/mpconfigboard.mk | 3 | ||||
| -rw-r--r-- | ports/atmel-samd/boards/same54_xplained/pins.c | 17 | ||||
| -rw-r--r-- | ports/atmel-samd/common-hal/sdioio/SDCard.c | 272 | ||||
| -rw-r--r-- | ports/atmel-samd/common-hal/sdioio/SDCard.h | 40 | ||||
| -rw-r--r-- | ports/atmel-samd/common-hal/sdioio/__init__.c | 0 | ||||
| -rw-r--r-- | ports/atmel-samd/common-hal/sdioio/__init__.h | 0 | ||||
| -rwxr-xr-x | tools/mksdiodata.py | 40 |
16 files changed, 790 insertions, 2 deletions
diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot index 481d29f24..3a3b159a0 100644 --- a/locale/circuitpython.pot +++ b/locale/circuitpython.pot @@ -58,6 +58,10 @@ msgstr "" msgid "%d address pins and %d rgb pins indicate a height of %d, not %d" msgstr "" +#: ports/atmel-samd/common-hal/sdioio/SDCard.c +msgid "%q failure: %d" +msgstr "" + #: shared-bindings/microcontroller/Pin.c msgid "%q in use" msgstr "" @@ -85,6 +89,10 @@ msgstr "" msgid "%q must be a tuple of length 2" msgstr "" +#: ports/atmel-samd/common-hal/sdioio/SDCard.c +msgid "%q pin invalid" +msgstr "" + #: shared-bindings/fontio/BuiltinFont.c msgid "%q should be an int" msgstr "" @@ -417,7 +425,7 @@ msgstr "" msgid "Buffer length %d too big. It must be less than %d" msgstr "" -#: shared-module/sdcardio/SDCard.c +#: ports/atmel-samd/common-hal/sdioio/SDCard.c shared-module/sdcardio/SDCard.c msgid "Buffer length must be a multiple of 512" msgstr "" diff --git a/ports/atmel-samd/Makefile b/ports/atmel-samd/Makefile index 5f901a199..c308105a3 100644 --- a/ports/atmel-samd/Makefile +++ b/ports/atmel-samd/Makefile @@ -246,6 +246,14 @@ SRC_ASF += \ endif +ifeq ($(CIRCUITPY_SDIOIO),1) +SRC_ASF += \ + hal/src/hal_mci_sync.c \ + hpl/sdhc/hpl_sdhc.c \ + +$(BUILD)/asf4/$(CHIP_FAMILY)/hpl/sdhc/hpl_sdhc.o: CFLAGS += -Wno-cast-align +endif + SRC_ASF := $(addprefix asf4/$(CHIP_FAMILY)/, $(SRC_ASF)) SRC_C = \ @@ -290,6 +298,9 @@ SRC_C = \ supervisor/shared/memory.c \ timer_handler.c \ +ifeq ($(CIRCUITPY_SDIOIO),1) +SRC_C += ports/atmel-samd/sd_mmc/sd_mmc.c +endif ifeq ($(CIRCUITPY_NETWORK),1) CFLAGS += -DMICROPY_PY_NETWORK=1 @@ -346,6 +357,10 @@ endif OBJ += $(addprefix $(BUILD)/, $(SRC_S:.s=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_MOD:.c=.o)) +SRC_QSTR += $(HEADER_BUILD)/sdiodata.h +$(HEADER_BUILD)/sdiodata.h: $(TOP)/tools/mksdiodata.py | $(HEADER_BUILD) + $(Q)$(PYTHON3) $< > $@ + SRC_QSTR += $(SRC_C) $(SRC_SUPERVISOR) $(SRC_COMMON_HAL_EXPANDED) $(SRC_SHARED_MODULE_EXPANDED) # Sources that only hold QSTRs after pre-processing. SRC_QSTR_PREPROCESSOR += peripherals/samd/$(PERIPHERALS_CHIP_FAMILY)/clocks.c diff --git a/ports/atmel-samd/asf4 b/ports/atmel-samd/asf4 -Subproject c0eef7b75124fc946af5f75e12d82d6d01315ab +Subproject 35a1525796c7ef8a3893d90befdad2f267fca20 diff --git a/ports/atmel-samd/asf4_conf/samd51/hpl_sdhc_config.h b/ports/atmel-samd/asf4_conf/samd51/hpl_sdhc_config.h new file mode 100644 index 000000000..daa662051 --- /dev/null +++ b/ports/atmel-samd/asf4_conf/samd51/hpl_sdhc_config.h @@ -0,0 +1,24 @@ +/* Auto-generated config file hpl_sdhc_config.h */ +#ifndef HPL_SDHC_CONFIG_H +#define HPL_SDHC_CONFIG_H + +// <<< Use Configuration Wizard in Context Menu >>> + +#include "peripheral_clk_config.h" + +#ifndef CONF_BASE_FREQUENCY +#define CONF_BASE_FREQUENCY CONF_SDHC0_FREQUENCY +#endif + +// <o> Clock Generator Select +// <0=> Divided Clock mode +// <1=> Programmable Clock mode +// <i> This defines the clock generator mode in the SDCLK Frequency Select field +// <id> sdhc_clk_gsel +#ifndef CONF_SDHC0_CLK_GEN_SEL +#define CONF_SDHC0_CLK_GEN_SEL 0 +#endif + +// <<< end of configuration section >>> + +#endif // HPL_SDHC_CONFIG_H diff --git a/ports/atmel-samd/asf4_conf/samd51/peripheral_clk_config.h b/ports/atmel-samd/asf4_conf/samd51/peripheral_clk_config.h index 030a90a7a..59fe8730e 100644 --- a/ports/atmel-samd/asf4_conf/samd51/peripheral_clk_config.h +++ b/ports/atmel-samd/asf4_conf/samd51/peripheral_clk_config.h @@ -1001,6 +1001,170 @@ #define CONF_GCLK_USB_FREQUENCY 48000000 #endif +// <h> SDHC Clock Settings +// <y> SDHC Clock source + +// <GCLK_PCHCTRL_GEN_GCLK0_Val"> Generic clock generator 0 + +// <GCLK_PCHCTRL_GEN_GCLK1_Val"> Generic clock generator 1 + +// <GCLK_PCHCTRL_GEN_GCLK2_Val"> Generic clock generator 2 + +// <GCLK_PCHCTRL_GEN_GCLK3_Val"> Generic clock generator 3 + +// <GCLK_PCHCTRL_GEN_GCLK4_Val"> Generic clock generator 4 + +// <GCLK_PCHCTRL_GEN_GCLK5_Val"> Generic clock generator 5 + +// <GCLK_PCHCTRL_GEN_GCLK6_Val"> Generic clock generator 6 + +// <GCLK_PCHCTRL_GEN_GCLK7_Val"> Generic clock generator 7 + +// <GCLK_PCHCTRL_GEN_GCLK8_Val"> Generic clock generator 8 + +// <GCLK_PCHCTRL_GEN_GCLK9_Val"> Generic clock generator 9 + +// <GCLK_PCHCTRL_GEN_GCLK10_Val"> Generic clock generator 10 + +// <GCLK_PCHCTRL_GEN_GCLK11_Val"> Generic clock generator 11 + +// <i> Select the clock source for SDHC. +// <id> sdhc_gclk_selection +#ifndef CONF_GCLK_SDHC0_SRC +#define CONF_GCLK_SDHC0_SRC GCLK_GENCTRL_SRC_DFLL_Val +#endif + +// <y> SDHC clock slow source + +// <GCLK_PCHCTRL_GEN_GCLK0_Val"> Generic clock generator 0 + +// <GCLK_PCHCTRL_GEN_GCLK1_Val"> Generic clock generator 1 + +// <GCLK_PCHCTRL_GEN_GCLK2_Val"> Generic clock generator 2 + +// <GCLK_PCHCTRL_GEN_GCLK3_Val"> Generic clock generator 3 + +// <GCLK_PCHCTRL_GEN_GCLK4_Val"> Generic clock generator 4 + +// <GCLK_PCHCTRL_GEN_GCLK5_Val"> Generic clock generator 5 + +// <GCLK_PCHCTRL_GEN_GCLK6_Val"> Generic clock generator 6 + +// <GCLK_PCHCTRL_GEN_GCLK7_Val"> Generic clock generator 7 + +// <GCLK_PCHCTRL_GEN_GCLK8_Val"> Generic clock generator 8 + +// <GCLK_PCHCTRL_GEN_GCLK9_Val"> Generic clock generator 9 + +// <GCLK_PCHCTRL_GEN_GCLK10_Val"> Generic clock generator 10 + +// <GCLK_PCHCTRL_GEN_GCLK11_Val"> Generic clock generator 11 + +// <i> Select the clock source for SDHC. +// <id> sdhc_slow_gclk_selection +#ifndef CONF_GCLK_SDHC0_SLOW_SRC +#define CONF_GCLK_SDHC0_SLOW_SRC GCLK_GENCTRL_SRC_DFLL_Val +#endif +// </h> + +/** + * \def SDHC FREQUENCY + * \brief SDHC's Clock frequency + */ +#ifndef CONF_SDHC0_FREQUENCY +#define CONF_SDHC0_FREQUENCY 12000000 +#endif + +/** + * \def SDHC FREQUENCY + * \brief SDHC's Clock slow frequency + */ +#ifndef CONF_SDHC0_SLOW_FREQUENCY +#define CONF_SDHC0_SLOW_FREQUENCY 12000000 +#endif + +// <h> SDHC Clock Settings +// <y> SDHC Clock source + +// <GCLK_PCHCTRL_GEN_GCLK0_Val"> Generic clock generator 0 + +// <GCLK_PCHCTRL_GEN_GCLK1_Val"> Generic clock generator 1 + +// <GCLK_PCHCTRL_GEN_GCLK2_Val"> Generic clock generator 2 + +// <GCLK_PCHCTRL_GEN_GCLK3_Val"> Generic clock generator 3 + +// <GCLK_PCHCTRL_GEN_GCLK4_Val"> Generic clock generator 4 + +// <GCLK_PCHCTRL_GEN_GCLK5_Val"> Generic clock generator 5 + +// <GCLK_PCHCTRL_GEN_GCLK6_Val"> Generic clock generator 6 + +// <GCLK_PCHCTRL_GEN_GCLK7_Val"> Generic clock generator 7 + +// <GCLK_PCHCTRL_GEN_GCLK8_Val"> Generic clock generator 8 + +// <GCLK_PCHCTRL_GEN_GCLK9_Val"> Generic clock generator 9 + +// <GCLK_PCHCTRL_GEN_GCLK10_Val"> Generic clock generator 10 + +// <GCLK_PCHCTRL_GEN_GCLK11_Val"> Generic clock generator 11 + +// <i> Select the clock source for SDHC. +// <id> sdhc_gclk_selection +#ifndef CONF_GCLK_SDHC1_SRC +#define CONF_GCLK_SDHC1_SRC GCLK_GENCTRL_SRC_DFLL_Val +#endif + +// <y> SDHC clock slow source + +// <GCLK_PCHCTRL_GEN_GCLK0_Val"> Generic clock generator 0 + +// <GCLK_PCHCTRL_GEN_GCLK1_Val"> Generic clock generator 1 + +// <GCLK_PCHCTRL_GEN_GCLK2_Val"> Generic clock generator 2 + +// <GCLK_PCHCTRL_GEN_GCLK3_Val"> Generic clock generator 3 + +// <GCLK_PCHCTRL_GEN_GCLK4_Val"> Generic clock generator 4 + +// <GCLK_PCHCTRL_GEN_GCLK5_Val"> Generic clock generator 5 + +// <GCLK_PCHCTRL_GEN_GCLK6_Val"> Generic clock generator 6 + +// <GCLK_PCHCTRL_GEN_GCLK7_Val"> Generic clock generator 7 + +// <GCLK_PCHCTRL_GEN_GCLK8_Val"> Generic clock generator 8 + +// <GCLK_PCHCTRL_GEN_GCLK9_Val"> Generic clock generator 9 + +// <GCLK_PCHCTRL_GEN_GCLK10_Val"> Generic clock generator 10 + +// <GCLK_PCHCTRL_GEN_GCLK11_Val"> Generic clock generator 11 + +// <i> Select the clock source for SDHC. +// <id> sdhc_slow_gclk_selection +#ifndef CONF_GCLK_SDHC1_SLOW_SRC +#define CONF_GCLK_SDHC1_SLOW_SRC GCLK_GENCTRL_SRC_DFLL_Val +#endif +// </h> + +/** + * \def SDHC FREQUENCY + * \brief SDHC's Clock frequency + */ +#ifndef CONF_SDHC1_FREQUENCY +#define CONF_SDHC1_FREQUENCY 12000000 +#endif + +/** + * \def SDHC FREQUENCY + * \brief SDHC's Clock slow frequency + */ +#ifndef CONF_SDHC1_SLOW_FREQUENCY +#define CONF_SDHC1_SLOW_FREQUENCY 12000000 +#endif + // <<< end of configuration section >>> #endif // PERIPHERAL_CLK_CONFIG_H diff --git a/ports/atmel-samd/asf4_conf/same54/hpl_sdhc_config.h b/ports/atmel-samd/asf4_conf/same54/hpl_sdhc_config.h new file mode 100644 index 000000000..daa662051 --- /dev/null +++ b/ports/atmel-samd/asf4_conf/same54/hpl_sdhc_config.h @@ -0,0 +1,24 @@ +/* Auto-generated config file hpl_sdhc_config.h */ +#ifndef HPL_SDHC_CONFIG_H +#define HPL_SDHC_CONFIG_H + +// <<< Use Configuration Wizard in Context Menu >>> + +#include "peripheral_clk_config.h" + +#ifndef CONF_BASE_FREQUENCY +#define CONF_BASE_FREQUENCY CONF_SDHC0_FREQUENCY +#endif + +// <o> Clock Generator Select +// <0=> Divided Clock mode +// <1=> Programmable Clock mode +// <i> This defines the clock generator mode in the SDCLK Frequency Select field +// <id> sdhc_clk_gsel +#ifndef CONF_SDHC0_CLK_GEN_SEL +#define CONF_SDHC0_CLK_GEN_SEL 0 +#endif + +// <<< end of configuration section >>> + +#endif // HPL_SDHC_CONFIG_H diff --git a/ports/atmel-samd/asf4_conf/same54/peripheral_clk_config.h b/ports/atmel-samd/asf4_conf/same54/peripheral_clk_config.h index 030a90a7a..59fe8730e 100644 --- a/ports/atmel-samd/asf4_conf/same54/peripheral_clk_config.h +++ b/ports/atmel-samd/asf4_conf/same54/peripheral_clk_config.h @@ -1001,6 +1001,170 @@ #define CONF_GCLK_USB_FREQUENCY 48000000 #endif +// <h> SDHC Clock Settings +// <y> SDHC Clock source + +// <GCLK_PCHCTRL_GEN_GCLK0_Val"> Generic clock generator 0 + +// <GCLK_PCHCTRL_GEN_GCLK1_Val"> Generic clock generator 1 + +// <GCLK_PCHCTRL_GEN_GCLK2_Val"> Generic clock generator 2 + +// <GCLK_PCHCTRL_GEN_GCLK3_Val"> Generic clock generator 3 + +// <GCLK_PCHCTRL_GEN_GCLK4_Val"> Generic clock generator 4 + +// <GCLK_PCHCTRL_GEN_GCLK5_Val"> Generic clock generator 5 + +// <GCLK_PCHCTRL_GEN_GCLK6_Val"> Generic clock generator 6 + +// <GCLK_PCHCTRL_GEN_GCLK7_Val"> Generic clock generator 7 + +// <GCLK_PCHCTRL_GEN_GCLK8_Val"> Generic clock generator 8 + +// <GCLK_PCHCTRL_GEN_GCLK9_Val"> Generic clock generator 9 + +// <GCLK_PCHCTRL_GEN_GCLK10_Val"> Generic clock generator 10 + +// <GCLK_PCHCTRL_GEN_GCLK11_Val"> Generic clock generator 11 + +// <i> Select the clock source for SDHC. +// <id> sdhc_gclk_selection +#ifndef CONF_GCLK_SDHC0_SRC +#define CONF_GCLK_SDHC0_SRC GCLK_GENCTRL_SRC_DFLL_Val +#endif + +// <y> SDHC clock slow source + +// <GCLK_PCHCTRL_GEN_GCLK0_Val"> Generic clock generator 0 + +// <GCLK_PCHCTRL_GEN_GCLK1_Val"> Generic clock generator 1 + +// <GCLK_PCHCTRL_GEN_GCLK2_Val"> Generic clock generator 2 + +// <GCLK_PCHCTRL_GEN_GCLK3_Val"> Generic clock generator 3 + +// <GCLK_PCHCTRL_GEN_GCLK4_Val"> Generic clock generator 4 + +// <GCLK_PCHCTRL_GEN_GCLK5_Val"> Generic clock generator 5 + +// <GCLK_PCHCTRL_GEN_GCLK6_Val"> Generic clock generator 6 + +// <GCLK_PCHCTRL_GEN_GCLK7_Val"> Generic clock generator 7 + +// <GCLK_PCHCTRL_GEN_GCLK8_Val"> Generic clock generator 8 + +// <GCLK_PCHCTRL_GEN_GCLK9_Val"> Generic clock generator 9 + +// <GCLK_PCHCTRL_GEN_GCLK10_Val"> Generic clock generator 10 + +// <GCLK_PCHCTRL_GEN_GCLK11_Val"> Generic clock generator 11 + +// <i> Select the clock source for SDHC. +// <id> sdhc_slow_gclk_selection +#ifndef CONF_GCLK_SDHC0_SLOW_SRC +#define CONF_GCLK_SDHC0_SLOW_SRC GCLK_GENCTRL_SRC_DFLL_Val +#endif +// </h> + +/** + * \def SDHC FREQUENCY + * \brief SDHC's Clock frequency + */ +#ifndef CONF_SDHC0_FREQUENCY +#define CONF_SDHC0_FREQUENCY 12000000 +#endif + +/** + * \def SDHC FREQUENCY + * \brief SDHC's Clock slow frequency + */ +#ifndef CONF_SDHC0_SLOW_FREQUENCY +#define CONF_SDHC0_SLOW_FREQUENCY 12000000 +#endif + +// <h> SDHC Clock Settings +// <y> SDHC Clock source + +// <GCLK_PCHCTRL_GEN_GCLK0_Val"> Generic clock generator 0 + +// <GCLK_PCHCTRL_GEN_GCLK1_Val"> Generic clock generator 1 + +// <GCLK_PCHCTRL_GEN_GCLK2_Val"> Generic clock generator 2 + +// <GCLK_PCHCTRL_GEN_GCLK3_Val"> Generic clock generator 3 + +// <GCLK_PCHCTRL_GEN_GCLK4_Val"> Generic clock generator 4 + +// <GCLK_PCHCTRL_GEN_GCLK5_Val"> Generic clock generator 5 + +// <GCLK_PCHCTRL_GEN_GCLK6_Val"> Generic clock generator 6 + +// <GCLK_PCHCTRL_GEN_GCLK7_Val"> Generic clock generator 7 + +// <GCLK_PCHCTRL_GEN_GCLK8_Val"> Generic clock generator 8 + +// <GCLK_PCHCTRL_GEN_GCLK9_Val"> Generic clock generator 9 + +// <GCLK_PCHCTRL_GEN_GCLK10_Val"> Generic clock generator 10 + +// <GCLK_PCHCTRL_GEN_GCLK11_Val"> Generic clock generator 11 + +// <i> Select the clock source for SDHC. +// <id> sdhc_gclk_selection +#ifndef CONF_GCLK_SDHC1_SRC +#define CONF_GCLK_SDHC1_SRC GCLK_GENCTRL_SRC_DFLL_Val +#endif + +// <y> SDHC clock slow source + +// <GCLK_PCHCTRL_GEN_GCLK0_Val"> Generic clock generator 0 + +// <GCLK_PCHCTRL_GEN_GCLK1_Val"> Generic clock generator 1 + +// <GCLK_PCHCTRL_GEN_GCLK2_Val"> Generic clock generator 2 + +// <GCLK_PCHCTRL_GEN_GCLK3_Val"> Generic clock generator 3 + +// <GCLK_PCHCTRL_GEN_GCLK4_Val"> Generic clock generator 4 + +// <GCLK_PCHCTRL_GEN_GCLK5_Val"> Generic clock generator 5 + +// <GCLK_PCHCTRL_GEN_GCLK6_Val"> Generic clock generator 6 + +// <GCLK_PCHCTRL_GEN_GCLK7_Val"> Generic clock generator 7 + +// <GCLK_PCHCTRL_GEN_GCLK8_Val"> Generic clock generator 8 + +// <GCLK_PCHCTRL_GEN_GCLK9_Val"> Generic clock generator 9 + +// <GCLK_PCHCTRL_GEN_GCLK10_Val"> Generic clock generator 10 + +// <GCLK_PCHCTRL_GEN_GCLK11_Val"> Generic clock generator 11 + +// <i> Select the clock source for SDHC. +// <id> sdhc_slow_gclk_selection +#ifndef CONF_GCLK_SDHC1_SLOW_SRC +#define CONF_GCLK_SDHC1_SLOW_SRC GCLK_GENCTRL_SRC_DFLL_Val +#endif +// </h> + +/** + * \def SDHC FREQUENCY + * \brief SDHC's Clock frequency + */ +#ifndef CONF_SDHC1_FREQUENCY +#define CONF_SDHC1_FREQUENCY 12000000 +#endif + +/** + * \def SDHC FREQUENCY + * \brief SDHC's Clock slow frequency + */ +#ifndef CONF_SDHC1_SLOW_FREQUENCY +#define CONF_SDHC1_SLOW_FREQUENCY 12000000 +#endif + // <<< end of configuration section >>> #endif // PERIPHERAL_CLK_CONFIG_H diff --git a/ports/atmel-samd/boards/grandcentral_m4_express/mpconfigboard.mk b/ports/atmel-samd/boards/grandcentral_m4_express/mpconfigboard.mk index ab81ec5a2..08eb5c98b 100644 --- a/ports/atmel-samd/boards/grandcentral_m4_express/mpconfigboard.mk +++ b/ports/atmel-samd/boards/grandcentral_m4_express/mpconfigboard.mk @@ -10,3 +10,5 @@ QSPI_FLASH_FILESYSTEM = 1 EXTERNAL_FLASH_DEVICE_COUNT = 2 EXTERNAL_FLASH_DEVICES = "W25Q64JV_IQ, GD25Q64C" LONGINT_IMPL = MPZ + +CIRCUITPY_SDIOIO = 1 diff --git a/ports/atmel-samd/boards/grandcentral_m4_express/pins.c b/ports/atmel-samd/boards/grandcentral_m4_express/pins.c index 6b09c62bf..b125aca08 100644 --- a/ports/atmel-samd/boards/grandcentral_m4_express/pins.c +++ b/ports/atmel-samd/boards/grandcentral_m4_express/pins.c @@ -1,5 +1,18 @@ +#include "py/objtuple.h" #include "shared-bindings/board/__init__.h" +STATIC const mp_rom_obj_tuple_t sdio_data_tuple = { + {&mp_type_tuple}, + 4, + { + MP_ROM_PTR(&pin_PB18), + MP_ROM_PTR(&pin_PB19), + MP_ROM_PTR(&pin_PB20), + MP_ROM_PTR(&pin_PB21), + } +}; + + // This mapping only includes functional names because pins broken // out on connectors are labeled with their MCU name available from // microcontroller.pin. @@ -129,5 +142,9 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, + + { MP_ROM_QSTR(MP_QSTR_SDIO_CLOCK), MP_ROM_PTR(&pin_PA21) }, + { MP_ROM_QSTR(MP_QSTR_SDIO_COMMAND), MP_ROM_PTR(&pin_PA20) }, + { MP_ROM_QSTR(MP_QSTR_SDIO_DATA), MP_ROM_PTR(&sdio_data_tuple) }, }; MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table); diff --git a/ports/atmel-samd/boards/same54_xplained/mpconfigboard.mk b/ports/atmel-samd/boards/same54_xplained/mpconfigboard.mk index ffc4f567f..7ac126514 100644 --- a/ports/atmel-samd/boards/same54_xplained/mpconfigboard.mk +++ b/ports/atmel-samd/boards/same54_xplained/mpconfigboard.mk @@ -10,4 +10,5 @@ QSPI_FLASH_FILESYSTEM = 1 EXTERNAL_FLASH_DEVICE_COUNT = 2 EXTERNAL_FLASH_DEVICES = "N25Q256A" LONGINT_IMPL = MPZ -LONGINT_IMPL = MPZ + +CIRCUITPY_SDIOIO = 1 diff --git a/ports/atmel-samd/boards/same54_xplained/pins.c b/ports/atmel-samd/boards/same54_xplained/pins.c index 5b9373724..8a864ab97 100644 --- a/ports/atmel-samd/boards/same54_xplained/pins.c +++ b/ports/atmel-samd/boards/same54_xplained/pins.c @@ -1,5 +1,18 @@ +#include "py/objtuple.h" #include "shared-bindings/board/__init__.h" +STATIC const mp_rom_obj_tuple_t sdio_data_tuple = { + {&mp_type_tuple}, + 4, + { + MP_ROM_PTR(&pin_PB18), + MP_ROM_PTR(&pin_PB19), + MP_ROM_PTR(&pin_PB20), + MP_ROM_PTR(&pin_PB21), + } +}; + + // This mapping only includes functional names because pins broken // out on connectors are labeled with their MCU name available from // microcontroller.pin. @@ -95,5 +108,9 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, + + { MP_ROM_QSTR(MP_QSTR_SDIO_CLOCK), MP_ROM_PTR(&pin_PA21) }, + { MP_ROM_QSTR(MP_QSTR_SDIO_COMMAND), MP_ROM_PTR(&pin_PA20) }, + { MP_ROM_QSTR(MP_QSTR_SDIO_DATA), MP_ROM_PTR(&sdio_data_tuple) }, }; MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table); diff --git a/ports/atmel-samd/common-hal/sdioio/SDCard.c b/ports/atmel-samd/common-hal/sdioio/SDCard.c new file mode 100644 index 000000000..6014bd8ab --- /dev/null +++ b/ports/atmel-samd/common-hal/sdioio/SDCard.c @@ -0,0 +1,272 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 Jeff Epler for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include <stdbool.h> + +#include "py/mperrno.h" +#include "py/runtime.h" + +#include "boards/board.h" +#include "common-hal/microcontroller/Pin.h" +#include "shared-bindings/sdioio/SDCard.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-bindings/microcontroller/__init__.h" +#include "supervisor/shared/translate.h" + +#include "genhdr/sdiodata.h" + +#include "sd_mmc/sd_mmc.h" +#include "sd_mmc/conf_sd_mmc.h" +#include "peripheral_clk_config.h" + +#ifndef DEBUG_SDIO +#define DEBUG_SDIO (1) +#endif + +#if DEBUG_SDIO +#define DEBUG_PRINT(...) ((void)mp_printf(&mp_plat_print, __VA_ARGS__)) +#define DEBUG_PRINT_OBJ(o) ((void)mp_obj_print_helper(&mp_plat_print, (mp_obj_t)o, PRINT_REPR)) +#else +#define DEBUG_PRINT(...) ((void)0) +#define DEBUG_PRINT_OBJ(...) ((void)0) +#endif +#define DEBUG_PRINT_OBJ_NL(o) (DEBUG_PRINT_OBJ(o), DEBUG_PRINT("\n")) + +#define GPIO_PIN_FUNCTION_SDIO (GPIO_PIN_FUNCTION_I) + +static Sdhc *sdhc_insts[] = SDHC_INSTS; + +STATIC pin_function_t *find_pin_function(pin_function_t *table, const mcu_pin_obj_t *pin, int instance, uint16_t name) { + DEBUG_PRINT("\n\n[inst=% 2d] %q: ", instance, name); + DEBUG_PRINT_OBJ_NL(pin); + + for(; table->obj; table++) { + DEBUG_PRINT("[inst=% 2d] considering table @%p: "); + DEBUG_PRINT_OBJ(table->obj); + DEBUG_PRINT(" %d %d\n", table->instance, table->pin); + if (instance != -1 && instance != table->instance) { + continue; + } + if (pin == table->obj) { + return table; + } + } + mp_raise_ValueError_varg(translate("%q pin invalid"), name); +} + +void common_hal_sdioio_sdcard_construct(sdioio_sdcard_obj_t *self, + const mcu_pin_obj_t * clock, const mcu_pin_obj_t * command, + uint8_t num_data, mcu_pin_obj_t ** data, uint32_t frequency) { + /* +SD breakout as assembled ("*" = minimum viable set) + +PURPLE 9 DAT2 SDA +BLUE 1 DAT3 SCL +GREEN 2 CMD * D32 +YELLOW 3 VSS1 +RED 4 VDD * 3.3V +BROWN 5 CLK * BROWN +BLACK 6 VSS2 * GND +WHITE 7 DAT0 * D8 +GREY 8 DAT1 D29 + +DAT0..3 PB18..21 (D8 D29 D20 D21) WHITE GREY PURPLE BLUE +CMD PA20 PCC_D? (D33) GREEN +CLK PA21 PCC_D? (D32) BROWN + +*/ + + pin_function_t *functions[6] = {}; + functions[0] = find_pin_function(sdio_cmd, command, -1, MP_QSTR_command); + int instance = functions[0]->instance; + functions[1] = find_pin_function(sdio_ck, clock, instance, MP_QSTR_clock); + functions[2] = find_pin_function(sdio_dat0, data[0], instance, MP_QSTR_data0); + if(num_data == 4) { + functions[3] = find_pin_function(sdio_dat1, data[1], instance, MP_QSTR_data1); + functions[4] = find_pin_function(sdio_dat2, data[2], instance, MP_QSTR_data2); + functions[5] = find_pin_function(sdio_dat3, data[3], instance, MP_QSTR_data3); + } + + // We've verified all pins, now set their special functions + self->command_pin = common_hal_mcu_pin_number(functions[0]->obj); + self->clock_pin = common_hal_mcu_pin_number(functions[1]->obj); + + for(int i=0; i<num_data; i++) { + pin_function_t *function = functions[2+i]; + if (function) { + self->data_pins[i] = common_hal_mcu_pin_number(function->obj); + } else { + self->data_pins[i] = COMMON_HAL_MCU_NO_PIN; + } + } + + for(size_t i=0; i<MP_ARRAY_SIZE(functions); i++) { + if (!functions[i]->obj) { + break; + } + + gpio_set_pin_direction(functions[i]->pin, GPIO_DIRECTION_OUT); + gpio_set_pin_level(functions[i]->pin, false); + // Enable pullups on all pins except CLK and DAT3 + gpio_set_pin_pull_mode(functions[i]->pin, + (i == 1 || i == 5) ? GPIO_PULL_OFF : GPIO_PULL_UP); + gpio_set_pin_function(functions[i]->pin, GPIO_PIN_FUNCTION_SDIO); + + common_hal_never_reset_pin(functions[i]->obj); + } + + self->num_data = num_data; + self->frequency = frequency; + + if(instance == 0) { + hri_mclk_set_AHBMASK_SDHC0_bit(MCLK); + hri_gclk_write_PCHCTRL_reg(GCLK, SDHC0_GCLK_ID, CONF_GCLK_SDHC0_SRC | (1 << GCLK_PCHCTRL_CHEN_Pos)); + hri_gclk_write_PCHCTRL_reg(GCLK, SDHC0_GCLK_ID_SLOW, CONF_GCLK_SDHC0_SLOW_SRC | (1 << GCLK_PCHCTRL_CHEN_Pos)); + } else { +#ifdef SDHC1_GCLK_ID + hri_mclk_set_AHBMASK_SDHC1_bit(MCLK); + hri_gclk_write_PCHCTRL_reg(GCLK, SDHC1_GCLK_ID, CONF_GCLK_SDHC1_SRC | (1 << GCLK_PCHCTRL_CHEN_Pos)); + hri_gclk_write_PCHCTRL_reg(GCLK, SDHC1_GCLK_ID_SLOW, CONF_GCLK_SDHC1_SLOW_SRC | (1 << GCLK_PCHCTRL_CHEN_Pos)); +#endif + } + + DEBUG_PRINT("instance %d @%p\n", instance, sdhc_insts[instance]); + mci_sync_init(&self->IO_BUS, sdhc_insts[instance]); + sd_mmc_init(&self->IO_BUS, NULL, NULL); + + sd_mmc_err_t result = SD_MMC_INIT_ONGOING; + + for (int i=0; result == SD_MMC_INIT_ONGOING && i<100; i++) { + result = sd_mmc_check(0); + DEBUG_PRINT("sd_mmc_check(0) -> %d\n", result); + } + + if (result != SD_MMC_OK) { + mp_raise_OSError_msg_varg(translate("%q failure: %d"), MP_QSTR_sd_mmc_check, (int)result); + } + // sd_mmc_get_capacity() is in KiB, but our "capacity" is in 512-byte blocks + self->capacity = sd_mmc_get_capacity(0) * 2; + + DEBUG_PRINT("capacity=%u\n", self->capacity); +} + +uint32_t common_hal_sdioio_sdcard_get_count(sdioio_sdcard_obj_t *self) { + return self->capacity; +} + +uint32_t common_hal_sdioio_sdcard_get_frequency(sdioio_sdcard_obj_t *self) { + return self->frequency; // self->frequency; +} + +uint8_t common_hal_sdioio_sdcard_get_width(sdioio_sdcard_obj_t *self) { + return self->num_data; // self->width; +} + +STATIC void check_for_deinit(sdioio_sdcard_obj_t *self) { +} + +STATIC void check_whole_block(mp_buffer_info_t *bufinfo) { + if (bufinfo->len % 512) { + mp_raise_ValueError(translate("Buffer length must be a multiple of 512")); + } +} + +STATIC void wait_write_complete(sdioio_sdcard_obj_t *self) { + if (self->state_programming) { + sd_mmc_wait_end_of_write_blocks(0); + self->state_programming = 0; + } +} + +STATIC void debug_print_state(sdioio_sdcard_obj_t *self, const char *what, sd_mmc_err_t r) { +#if DEBUG_SDIO + DEBUG_PRINT("%s: %d\n", what, r); +#endif +} + +int common_hal_sdioio_sdcard_writeblocks(sdioio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *bufinfo) { + check_for_deinit(self); + check_whole_block(bufinfo); + wait_write_complete(self); + self->state_programming = true; + sd_mmc_err_t r = sd_mmc_init_write_blocks(0, start_block, bufinfo->len / 512); + if (r != SD_MMC_OK) { + debug_print_state(self, "sd_mmc_init_write_blocks", r); + return -EIO; + } + r = sd_mmc_start_write_blocks(bufinfo->buf, bufinfo->len / 512); + if (r != SD_MMC_OK) { + debug_print_state(self, "sd_mmc_start_write_blocks", r); + return -EIO; + } + // debug_print_state(self, "after writeblocks OK"); + return 0; +} + +int common_hal_sdioio_sdcard_readblocks(sdioio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *bufinfo) { + check_for_deinit(self); + check_whole_block(bufinfo); + wait_write_complete(self); + sd_mmc_err_t r = sd_mmc_init_read_blocks(0, start_block, bufinfo->len / 512); + if (r != SD_MMC_OK) { + debug_print_state(self, "sd_mmc_init_read_blocks", r); + return -EIO; + } + r = sd_mmc_start_read_blocks(bufinfo->buf, bufinfo->len / 512); + if (r != SD_MMC_OK) { + debug_print_state(self, "sd_mmc_start_read_blocks", r); + return -EIO; + } + sd_mmc_wait_end_of_write_blocks(0); + return 0; +} + +bool common_hal_sdioio_sdcard_configure(sdioio_sdcard_obj_t *self, uint32_t frequency, uint8_t bits) { + check_for_deinit(self); + return true; +} + +bool common_hal_sdioio_sdcard_deinited(sdioio_sdcard_obj_t *self) { + return self->command_pin == COMMON_HAL_MCU_NO_PIN; +} + +void common_hal_sdioio_sdcard_deinit(sdioio_sdcard_obj_t *self) { + reset_pin_number(self->command_pin); + reset_pin_number(self->clock_pin); + reset_pin_number(self->data_pins[0]); + reset_pin_number(self->data_pins[1]); + reset_pin_number(self->data_pins[2]); + reset_pin_number(self->data_pins[3]); + + self->command_pin = COMMON_HAL_MCU_NO_PIN; + self->clock_pin = COMMON_HAL_MCU_NO_PIN; + self->data_pins[0] = COMMON_HAL_MCU_NO_PIN; + self->data_pins[1] = COMMON_HAL_MCU_NO_PIN; + self->data_pins[2] = COMMON_HAL_MCU_NO_PIN; + self->data_pins[3] = COMMON_HAL_MCU_NO_PIN; +} + +void common_hal_sdioio_sdcard_never_reset(sdioio_sdcard_obj_t *self) { +} diff --git a/ports/atmel-samd/common-hal/sdioio/SDCard.h b/ports/atmel-samd/common-hal/sdioio/SDCard.h new file mode 100644 index 000000000..2baba38f0 --- /dev/null +++ b/ports/atmel-samd/common-hal/sdioio/SDCard.h @@ -0,0 +1,40 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Scott Shawcroft + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#pragma once + +#include "hal_mci_sync.h" + +typedef struct { + mp_obj_base_t base; + struct mci_sync_desc IO_BUS; + uint32_t frequency; + uint32_t capacity; + uint8_t num_data:3, state_programming:1, has_lock:1; + uint8_t command_pin; + uint8_t clock_pin; + uint8_t data_pins[4]; +} sdioio_sdcard_obj_t; diff --git a/ports/atmel-samd/common-hal/sdioio/__init__.c b/ports/atmel-samd/common-hal/sdioio/__init__.c new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/ports/atmel-samd/common-hal/sdioio/__init__.c diff --git a/ports/atmel-samd/common-hal/sdioio/__init__.h b/ports/atmel-samd/common-hal/sdioio/__init__.h new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/ports/atmel-samd/common-hal/sdioio/__init__.h diff --git a/tools/mksdiodata.py b/tools/mksdiodata.py new file mode 100755 index 000000000..0cce3819f --- /dev/null +++ b/tools/mksdiodata.py @@ -0,0 +1,40 @@ +#!/usr/bin/python3 + +def defines(name, function): + print(f'pin_function_t {name} [] = {{') + for instance in (0, 1): + for port in 'ABCD': + for idx in range(32): + pin = f'P{port}{idx:02d}' + pinmux = f'PINMUX_{pin}I_SDHC{instance}_{function}' + print(f'''\ +#if defined({pinmux}) && ! defined(IGNORE_PIN_{pin}) + {{&pin_{pin}, {instance}, PIN_{pin}, {pinmux} & 0xffff}}, +#endif''') + print(f'{{NULL, 0, 0}}') + print(f'}};') + print() + +print('''\ +#include <stdint.h> +#include "py/obj.h" +#include "sam.h" +#include "samd/pins.h" +#include "mpconfigport.h" +#include "atmel_start_pins.h" +#include "hal/include/hal_gpio.h" + +typedef struct { + const mcu_pin_obj_t *obj; + uint8_t instance; + uint8_t pin; + uint16_t function; +} pin_function_t; +''') + +defines('sdio_ck', 'SDCK') +defines('sdio_cmd', 'SDCMD') +defines('sdio_dat0', 'SDDAT0') +defines('sdio_dat1', 'SDDAT1') +defines('sdio_dat2', 'SDDAT2') +defines('sdio_dat3', 'SDDAT3') |
