commit
111f7ddf69
|
@ -8,7 +8,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-06-25 11:44-0500\n"
|
||||
"POT-Creation-Date: 2020-06-26 11:50-0500\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
|
@ -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 ""
|
||||
|
@ -338,7 +346,7 @@ msgstr ""
|
|||
msgid "Array values should be single bytes."
|
||||
msgstr ""
|
||||
|
||||
#: shared-bindings/rgbmatrix/RGBMatrix.c
|
||||
#: shared-bindings/microcontroller/Pin.c
|
||||
msgid "At most %d %q may be specified (not %d)"
|
||||
msgstr ""
|
||||
|
||||
|
@ -417,6 +425,10 @@ msgstr ""
|
|||
msgid "Buffer length %d too big. It must be less than %d"
|
||||
msgstr ""
|
||||
|
||||
#: ports/atmel-samd/common-hal/sdioio/SDCard.c shared-module/sdcardio/SDCard.c
|
||||
msgid "Buffer length must be a multiple of 512"
|
||||
msgstr ""
|
||||
|
||||
#: shared-bindings/bitbangio/I2C.c shared-bindings/busio/I2C.c
|
||||
msgid "Buffer must be at least length 1"
|
||||
msgstr ""
|
||||
|
@ -698,7 +710,8 @@ msgstr ""
|
|||
msgid "Error in regex"
|
||||
msgstr ""
|
||||
|
||||
#: shared-bindings/aesio/aes.c shared-bindings/microcontroller/Pin.c
|
||||
#: shared-bindings/aesio/aes.c shared-bindings/busio/SPI.c
|
||||
#: shared-bindings/microcontroller/Pin.c
|
||||
#: shared-bindings/neopixel_write/__init__.c shared-bindings/pulseio/PulseOut.c
|
||||
#: shared-bindings/terminalio/Terminal.c
|
||||
msgid "Expected a %q"
|
||||
|
@ -858,6 +871,10 @@ msgstr ""
|
|||
msgid "Internal error #%d"
|
||||
msgstr ""
|
||||
|
||||
#: shared-bindings/sdioio/SDCard.c
|
||||
msgid "Invalid %q"
|
||||
msgstr ""
|
||||
|
||||
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
|
||||
#: ports/atmel-samd/common-hal/audiobusio/PDMIn.c
|
||||
msgid "Invalid %q pin"
|
||||
|
@ -1358,6 +1375,10 @@ msgstr ""
|
|||
msgid "Running in safe mode! Not running saved code.\n"
|
||||
msgstr ""
|
||||
|
||||
#: shared-module/sdcardio/SDCard.c
|
||||
msgid "SD card CSD format not supported"
|
||||
msgstr ""
|
||||
|
||||
#: ports/atmel-samd/common-hal/busio/I2C.c
|
||||
#: ports/mimxrt10xx/common-hal/busio/I2C.c ports/nrf/common-hal/busio/I2C.c
|
||||
msgid "SDA or SCL needs a pull up"
|
||||
|
@ -1979,6 +2000,10 @@ msgstr ""
|
|||
msgid "can't send non-None value to a just-started generator"
|
||||
msgstr ""
|
||||
|
||||
#: shared-module/sdcardio/SDCard.c
|
||||
msgid "can't set 512 block size"
|
||||
msgstr ""
|
||||
|
||||
#: py/objnamedtuple.c
|
||||
msgid "can't set attribute"
|
||||
msgstr ""
|
||||
|
@ -2105,6 +2130,10 @@ msgstr ""
|
|||
msgid "could not invert Vandermonde matrix"
|
||||
msgstr ""
|
||||
|
||||
#: shared-module/sdcardio/SDCard.c
|
||||
msgid "couldn't determine SD card version"
|
||||
msgstr ""
|
||||
|
||||
#: extmod/ulab/code/approx.c
|
||||
msgid "data must be iterable"
|
||||
msgstr ""
|
||||
|
@ -2662,6 +2691,10 @@ msgstr ""
|
|||
msgid "negative shift count"
|
||||
msgstr ""
|
||||
|
||||
#: shared-module/sdcardio/SDCard.c
|
||||
msgid "no SD card"
|
||||
msgstr ""
|
||||
|
||||
#: py/vm.c
|
||||
msgid "no active exception to reraise"
|
||||
msgstr ""
|
||||
|
@ -2683,6 +2716,10 @@ msgstr ""
|
|||
msgid "no reset pin available"
|
||||
msgstr ""
|
||||
|
||||
#: shared-module/sdcardio/SDCard.c
|
||||
msgid "no response from SD card"
|
||||
msgstr ""
|
||||
|
||||
#: py/runtime.c
|
||||
msgid "no such attribute"
|
||||
msgstr ""
|
||||
|
@ -3073,6 +3110,14 @@ msgstr ""
|
|||
msgid "timeout must be >= 0.0"
|
||||
msgstr ""
|
||||
|
||||
#: shared-module/sdcardio/SDCard.c
|
||||
msgid "timeout waiting for v1 card"
|
||||
msgstr ""
|
||||
|
||||
#: shared-module/sdcardio/SDCard.c
|
||||
msgid "timeout waiting for v2 card"
|
||||
msgstr ""
|
||||
|
||||
#: shared-bindings/time/__init__.c
|
||||
msgid "timestamp out of range for platform time_t"
|
||||
msgstr ""
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit c0eef7b75124fc946af5f75e12d82d6d01315ab1
|
||||
Subproject commit 35a1525796c7ef8a3893d90befdad2f267fca20e
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 (0)
|
||||
#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) {
|
||||
}
|
|
@ -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;
|
|
@ -37,6 +37,8 @@ ifndef CIRCUITPY_TOUCHIO_USE_NATIVE
|
|||
CIRCUITPY_TOUCHIO_USE_NATIVE = 1
|
||||
endif
|
||||
|
||||
CIRCUITPY_SDCARDIO ?= 0
|
||||
|
||||
# SAMD21 needs separate endpoint pairs for MSC BULK IN and BULK OUT, otherwise it's erratic.
|
||||
USB_MSC_EP_NUM_OUT = 1
|
||||
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
/* Auto-generated config file conf_sd_mmc.h */
|
||||
#ifndef CONF_SD_MMC_H
|
||||
#define CONF_SD_MMC_H
|
||||
|
||||
// <<< Use Configuration Wizard in Context Menu >>>
|
||||
|
||||
// <q> Enable the SDIO support
|
||||
// <id> conf_sdio_support
|
||||
#ifndef CONF_SDIO_SUPPORT
|
||||
#define CONF_SDIO_SUPPORT 0
|
||||
#endif
|
||||
|
||||
// <q> Enable the MMC card support
|
||||
// <id> conf_mmc_support
|
||||
#ifndef CONF_MMC_SUPPORT
|
||||
#define CONF_MMC_SUPPORT 0
|
||||
#endif
|
||||
|
||||
// <q> Enable the OS support
|
||||
// <id> conf_sd_mmc_os_support
|
||||
#ifndef CONF_OS_SUPPORT
|
||||
#define CONF_OS_SUPPORT 0
|
||||
#endif
|
||||
|
||||
// Detection (card/write protect) timeout (ms/ticks)
|
||||
// conf_sd_mmc_debounce
|
||||
#ifndef CONF_SD_MMC_DEBOUNCE
|
||||
#define CONF_SD_MMC_DEBOUNCE 1000
|
||||
#endif
|
||||
|
||||
#ifndef CONF_SD_MMC_MEM_CNT
|
||||
#define CONF_SD_MMC_MEM_CNT 1
|
||||
#endif
|
||||
|
||||
// <e> SD/MMC Slot 0
|
||||
// <id> conf_sd_mmc_0_enable
|
||||
#ifndef CONF_SD_MMC_0_ENABLE
|
||||
#define CONF_SD_MMC_0_ENABLE 1
|
||||
#endif
|
||||
|
||||
// <e> Card Detect (CD) 0 Enable
|
||||
// <id> conf_sd_mmc_0_cd_detect_en
|
||||
#ifndef CONF_SD_MMC_0_CD_DETECT_EN
|
||||
#define CONF_SD_MMC_0_CD_DETECT_EN 0
|
||||
#endif
|
||||
|
||||
// <o> Card Detect (CD) detection level
|
||||
// <1=> High
|
||||
// <0=> Low
|
||||
// <id> conf_sd_mmc_0_cd_detect_value
|
||||
#ifndef CONF_SD_MMC_0_CD_DETECT_VALUE
|
||||
#define CONF_SD_MMC_0_CD_DETECT_VALUE 0
|
||||
#endif
|
||||
// </e>
|
||||
|
||||
// <e> Write Protect (WP) 0 Enable
|
||||
// <id> conf_sd_mmc_0_wp_detect_en
|
||||
#ifndef CONF_SD_MMC_0_WP_DETECT_EN
|
||||
#define CONF_SD_MMC_0_WP_DETECT_EN 0
|
||||
#endif
|
||||
|
||||
// <o> Write Protect (WP) detection level
|
||||
// <1=> High
|
||||
// <0=> Low
|
||||
// <id> conf_sd_mmc_0_wp_detect_value
|
||||
#ifndef CONF_SD_MMC_0_WP_DETECT_VALUE
|
||||
#define CONF_SD_MMC_0_WP_DETECT_VALUE 1
|
||||
#endif
|
||||
// </e>
|
||||
|
||||
// </e>
|
||||
|
||||
#ifndef CONF_MCI_OS_SUPPORT
|
||||
#define CONF_MCI_OS_SUPPORT 0
|
||||
#endif
|
||||
|
||||
// <<< end of configuration section >>>
|
||||
|
||||
#endif // CONF_SD_MMC_H
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,310 @@
|
|||
/**
|
||||
* \file
|
||||
*
|
||||
* \brief Common SD/MMC stack header file
|
||||
*
|
||||
* Copyright (c) 2012-2018 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \asf_license_start
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip
|
||||
* software and any derivatives exclusively with Microchip products.
|
||||
* It is your responsibility to comply with third party license terms applicable
|
||||
* to your use of third party software (including open source software) that
|
||||
* may accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
|
||||
* WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
|
||||
* INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
|
||||
* LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
|
||||
* LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
|
||||
* SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
|
||||
* POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
|
||||
* ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
|
||||
* RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
|
||||
* THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
|
||||
*
|
||||
* \asf_license_stop
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* Support and FAQ: visit <a href="https://www.microchip.com/support/">Microchip Support</a>
|
||||
*/
|
||||
|
||||
#ifndef SD_MMC_H_INCLUDED
|
||||
#define SD_MMC_H_INCLUDED
|
||||
|
||||
#include "compiler.h"
|
||||
#include "conf_sd_mmc.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \ingroup common_memory
|
||||
* \defgroup sd_mmc_stack_group SD/MMC/SDIO common stack
|
||||
*
|
||||
* SD/MMC/SDIO basic APIs used by SD/MMC/SDIO memory
|
||||
* APIs (\ref sd_mmc_stack_mem_group).
|
||||
* Also, it can be used by application which use the SDIO card
|
||||
* or specific application which does not need of File System.
|
||||
*
|
||||
* For usual application which use the SD/MMC card in
|
||||
* memory mode with a file system, please refer to
|
||||
* \ref sd_mmc_stack_mem_group.
|
||||
* @{
|
||||
*/
|
||||
|
||||
typedef uint8_t sd_mmc_err_t; /**< Type of return error code */
|
||||
|
||||
/** \name Return error codes */
|
||||
/** @{ */
|
||||
#define SD_MMC_OK 0 /**< No error */
|
||||
#define SD_MMC_INIT_ONGOING 1 /**< Card not initialized */
|
||||
#define SD_MMC_ERR_NO_CARD 2 /**< No SD/MMC card inserted */
|
||||
#define SD_MMC_ERR_UNUSABLE 3 /**< Unusable card */
|
||||
#define SD_MMC_ERR_SLOT 4 /**< Slot unknow */
|
||||
#define SD_MMC_ERR_COMM 5 /**< General communication error */
|
||||
#define SD_MMC_ERR_PARAM 6 /**< Illeage input parameter */
|
||||
#define SD_MMC_ERR_WP 7 /**< Card write protected */
|
||||
/** @} */
|
||||
|
||||
typedef uint8_t card_type_t; /**< Type of card type */
|
||||
|
||||
/** \name Card Types */
|
||||
/** @{ */
|
||||
#define CARD_TYPE_UNKNOWN (0) /**< Unknown type card */
|
||||
#define CARD_TYPE_SD (1 << 0) /**< SD card */
|
||||
#define CARD_TYPE_MMC (1 << 1) /**< MMC card */
|
||||
#define CARD_TYPE_SDIO (1 << 2) /**< SDIO card */
|
||||
#define CARD_TYPE_HC (1 << 3) /**< High capacity card */
|
||||
/** SD combo card (io + memory) */
|
||||
#define CARD_TYPE_SD_COMBO (CARD_TYPE_SD | CARD_TYPE_SDIO)
|
||||
/** @} */
|
||||
|
||||
typedef uint8_t card_version_t; /**< Type of card version */
|
||||
|
||||
/** \name Card Versions */
|
||||
/** @{ */
|
||||
#define CARD_VER_UNKNOWN (0) /**< Unknown card version */
|
||||
#define CARD_VER_SD_1_0 (0x10) /**< SD version 1.0 and 1.01 */
|
||||
#define CARD_VER_SD_1_10 (0x1A) /**< SD version 1.10 */
|
||||
#define CARD_VER_SD_2_0 (0X20) /**< SD version 2.00 */
|
||||
#define CARD_VER_SD_3_0 (0X30) /**< SD version 3.0X */
|
||||
#define CARD_VER_MMC_1_2 (0x12) /**< MMC version 1.2 */
|
||||
#define CARD_VER_MMC_1_4 (0x14) /**< MMC version 1.4 */
|
||||
#define CARD_VER_MMC_2_2 (0x22) /**< MMC version 2.2 */
|
||||
#define CARD_VER_MMC_3 (0x30) /**< MMC version 3 */
|
||||
#define CARD_VER_MMC_4 (0x40) /**< MMC version 4 */
|
||||
/** @} */
|
||||
|
||||
/** Card detect setting */
|
||||
typedef struct sd_mmc_detect {
|
||||
int16_t pin; /**< Detection pin, -1 if no such pin */
|
||||
uint16_t val; /**< Detection value */
|
||||
} sd_mmc_detect_t;
|
||||
|
||||
/** This SD MMC stack uses the maximum block size autorized (512 bytes) */
|
||||
#define SD_MMC_BLOCK_SIZE 512
|
||||
|
||||
/**
|
||||
* \brief Initialize the SD/MMC stack and low level driver required
|
||||
* \param[in] hal Pointer to HAL instance
|
||||
* \param[in] card_detects Pointer to list of card detect settings,
|
||||
* list size should be \ref CONF_SD_MMC_MEM_CNT
|
||||
* \param[in] wp_detects Pointer to list of write protect detect settings
|
||||
* list size should be \ref CONF_SD_MMC_MEM_CNT
|
||||
*/
|
||||
void sd_mmc_init(void *hal, sd_mmc_detect_t *card_detects, sd_mmc_detect_t *wp_detects);
|
||||
|
||||
/** \brief Return the number of slot available
|
||||
*
|
||||
* \return Number of card slot available
|
||||
*/
|
||||
uint8_t sd_mmc_nb_slot(void);
|
||||
|
||||
/** \brief Performs a card checks
|
||||
*
|
||||
* \param[in] slot Card slot to use
|
||||
*
|
||||
* \retval SD_MMC_OK Card ready
|
||||
* \retval SD_MMC_INIT_ONGOING Initialization on going
|
||||
* \retval SD_MMC_ERR_NO_CARD Card not present in slot
|
||||
* \retval Other value for error cases, see \ref sd_mmc_err_t
|
||||
*/
|
||||
sd_mmc_err_t sd_mmc_check(uint8_t slot);
|
||||
|
||||
/** \brief Get the card type
|
||||
*
|
||||
* \param[in] slot Card slot
|
||||
*
|
||||
* \return Card type (\ref card_type_t)
|
||||
*/
|
||||
card_type_t sd_mmc_get_type(uint8_t slot);
|
||||
|
||||
/** \brief Get the card version
|
||||
*
|
||||
* \param[in] slot Card slot
|
||||
*
|
||||
* \return Card version (\ref card_version_t)
|
||||
*/
|
||||
card_version_t sd_mmc_get_version(uint8_t slot);
|
||||
|
||||
/** \brief Get the memory capacity
|
||||
*
|
||||
* \param[in] slot Card slot
|
||||
*
|
||||
* \return Capacity (unit KB)
|
||||
*/
|
||||
uint32_t sd_mmc_get_capacity(uint8_t slot);
|
||||
|
||||
/** \brief Get the card write protection status
|
||||
*
|
||||
* \param[in] slot Card slot
|
||||
*
|
||||
* \return true, if write portected
|
||||
*/
|
||||
bool sd_mmc_is_write_protected(uint8_t slot);
|
||||
|
||||
/**
|
||||
* \brief Initialize the read blocks of data from the card.
|
||||
*
|
||||
* \param[in] slot Card slot to use
|
||||
* \param[in] start Start block number to to read.
|
||||
* \param[in] nb_block Total number of blocks to be read.
|
||||
*
|
||||
* \return return SD_MMC_OK if success,
|
||||
* otherwise return an error code (\ref sd_mmc_err_t).
|
||||
*/
|
||||
sd_mmc_err_t sd_mmc_init_read_blocks(uint8_t slot, uint32_t start, uint16_t nb_block);
|
||||
|
||||
/**
|
||||
* \brief Start the read blocks of data from the card.
|
||||
*
|
||||
* \param[out] dest Pointer to read buffer.
|
||||
* \param[in] nb_block Number of blocks to be read.
|
||||
*
|
||||
* \return return SD_MMC_OK if started,
|
||||
* otherwise return an error code (\ref sd_mmc_err_t).
|
||||
*/
|
||||
sd_mmc_err_t sd_mmc_start_read_blocks(void *dest, uint16_t nb_block);
|
||||
|
||||
/**
|
||||
* \brief Wait the end of read blocks of data from the card.
|
||||
*
|
||||
* \param[in] abort Abort reading process initialized by
|
||||
* \ref sd_mmc_init_read_blocks() after the reading issued by
|
||||
* \ref sd_mmc_start_read_blocks() is done
|
||||
*
|
||||
* \return return SD_MMC_OK if success,
|
||||
* otherwise return an error code (\ref sd_mmc_err_t).
|
||||
*/
|
||||
sd_mmc_err_t sd_mmc_wait_end_of_read_blocks(bool abort);
|
||||
|
||||
/**
|
||||
* \brief Initialize the write blocks of data
|
||||
*
|
||||
* \param[in] slot Card slot to use
|
||||
* \param[in] start Start block number to be written.
|
||||
* \param[in] nb_block Total number of blocks to be written.
|
||||
*
|
||||
* \return return SD_MMC_OK if success,
|
||||
* otherwise return an error code (\ref sd_mmc_err_t).
|
||||
*/
|
||||
sd_mmc_err_t sd_mmc_init_write_blocks(uint8_t slot, uint32_t start, uint16_t nb_block);
|
||||
|
||||
/**
|
||||
* \brief Start the write blocks of data
|
||||
*
|
||||
* \param[in] src Pointer to write buffer.
|
||||
* \param[in] nb_block Number of blocks to be written.
|
||||
*
|
||||
* \return return SD_MMC_OK if started,
|
||||
* otherwise return an error code (\ref sd_mmc_err_t).
|
||||
*/
|
||||
sd_mmc_err_t sd_mmc_start_write_blocks(const void *src, uint16_t nb_block);
|
||||
|
||||
/**
|
||||
* \brief Wait the end of write blocks of data
|
||||
*
|
||||
* \param[in] abort Abort writing process initialized by
|
||||
* \ref sd_mmc_init_write_blocks() after the writing issued by
|
||||
* \ref sd_mmc_start_write_blocks() is done
|
||||
*
|
||||
* \return return SD_MMC_OK if success,
|
||||
* otherwise return an error code (\ref sd_mmc_err_t).
|
||||
*/
|
||||
sd_mmc_err_t sd_mmc_wait_end_of_write_blocks(bool abort);
|
||||
|
||||
#if (CONF_SDIO_SUPPORT == 1)
|
||||
/**
|
||||
* \brief Read one byte from SDIO using RW_DIRECT command.
|
||||
*
|
||||
* \param[in] slot Card slot to use
|
||||
* \param[in] func_num Function number.
|
||||
* \param[in] addr Register address to read from.
|
||||
* \param[out] dest Pointer to read buffer.
|
||||
*
|
||||
* \return return SD_MMC_OK if success,
|
||||
* otherwise return an error code (\ref sd_mmc_err_t).
|
||||
*/
|
||||
sd_mmc_err_t sdio_read_direct(uint8_t slot, uint8_t func_num, uint32_t addr, uint8_t *dest);
|
||||
/**
|
||||
* \brief Write one byte to SDIO using RW_DIRECT command.
|
||||
*
|
||||
* \param[in] slot Card slot to use
|
||||
* \param[in] func_num Function number.
|
||||
* \param[in] addr Register address to read from.
|
||||
* \param[in] data Data to be written.
|
||||
*
|
||||
* \return return SD_MMC_OK if success,
|
||||
* otherwise return an error code (\ref sd_mmc_err_t).
|
||||
*/
|
||||
sd_mmc_err_t sdio_write_direct(uint8_t slot, uint8_t func_num, uint32_t addr, uint8_t data);
|
||||
|
||||
/**
|
||||
* \brief Read bytes from SDIO using RW_EXTENDED command.
|
||||
*
|
||||
* \param[in] slot Card slot to use
|
||||
* \param[in] func_num Function number.
|
||||
* \param[in] addr First register address to read from.
|
||||
* \param[in] inc_addr 0 - The data address is fixed.
|
||||
* 1 - The data address increase automatically.
|
||||
* \param[out] dest Pointer to read buffer.
|
||||
* \param[in] size Number of bytes to read (1 ~ 512).
|
||||
*
|
||||
* \return return SD_MMC_OK if success,
|
||||
* otherwise return an error code (\ref sd_mmc_err_t).
|
||||
*/
|
||||
sd_mmc_err_t sdio_read_extended(uint8_t slot, uint8_t func_num, uint32_t addr, uint8_t inc_addr, uint8_t *dest,
|
||||
uint16_t size);
|
||||
|
||||
/**
|
||||
* \brief Write bytes to SDIO using RW_EXTENDED command.
|
||||
*
|
||||
* \param[in] slot Card slot to use
|
||||
* \param[in] func_num Function number.
|
||||
* \param[in] addr First register address to write to.
|
||||
* \param[in] inc_addr 0 - The data address is fixed.
|
||||
* 1 - The data address increase automatically.
|
||||
* \param[in] src Pointer to write buffer.
|
||||
* \param[in] size Number of bytes to read (1 ~ 512).
|
||||
*
|
||||
* \return return SD_MMC_OK if success,
|
||||
* otherwise return an error code (\ref sd_mmc_err_t).
|
||||
*/
|
||||
sd_mmc_err_t sdio_write_extended(uint8_t slot, uint8_t func_num, uint32_t addr, uint8_t inc_addr, uint8_t *src,
|
||||
uint16_t size);
|
||||
#endif /* SDIO_SUPPORT_ENABLE */
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SD_MMC_H_INCLUDED */
|
File diff suppressed because it is too large
Load Diff
|
@ -18,6 +18,7 @@ CIRCUITPY_AUDIOIO = 0
|
|||
CIRCUITPY_BITBANGIO = 0
|
||||
CIRCUITPY_BOARD = 0
|
||||
CIRCUITPY_BUSIO = 0
|
||||
CIRCUITPY_COUNTIO = 0
|
||||
CIRCUITPY_DISPLAYIO = 0
|
||||
CIRCUITPY_FREQUENCYIO = 0
|
||||
CIRCUITPY_I2CPERIPHERAL = 0
|
||||
|
@ -25,7 +26,7 @@ CIRCUITPY_NVM = 0
|
|||
CIRCUITPY_PULSEIO = 0
|
||||
CIRCUITPY_ROTARYIO = 0
|
||||
CIRCUITPY_RTC = 0
|
||||
CIRCUITPY_COUNTIO = 0
|
||||
CIRCUITPY_SDCARDIO = 0
|
||||
# Enable USB support
|
||||
CIRCUITPY_USB_HID = 1
|
||||
CIRCUITPY_USB_MIDI = 1
|
||||
|
|
|
@ -21,6 +21,7 @@ CIRCUITPY_PIXELBUF = 0
|
|||
CIRCUITPY_RGBMATRIX = 0
|
||||
CIRCUITPY_ROTARYIO = 0
|
||||
CIRCUITPY_RTC = 1
|
||||
CIRCUITPY_SDCARDIO = 0
|
||||
CIRCUITPY_TOUCHIO = 0
|
||||
CIRCUITPY_ULAB = 0
|
||||
|
||||
|
|
|
@ -213,6 +213,12 @@ endif
|
|||
ifeq ($(CIRCUITPY_SAMD),1)
|
||||
SRC_PATTERNS += samd/%
|
||||
endif
|
||||
ifeq ($(CIRCUITPY_SDCARDIO),1)
|
||||
SRC_PATTERNS += sdcardio/%
|
||||
endif
|
||||
ifeq ($(CIRCUITPY_SDIOIO),1)
|
||||
SRC_PATTERNS += sdioio/%
|
||||
endif
|
||||
ifeq ($(CIRCUITPY_STAGE),1)
|
||||
SRC_PATTERNS += _stage/%
|
||||
endif
|
||||
|
@ -311,6 +317,8 @@ SRC_COMMON_HAL_ALL = \
|
|||
rotaryio/__init__.c \
|
||||
rtc/RTC.c \
|
||||
rtc/__init__.c \
|
||||
sdioio/SDCard.c \
|
||||
sdioio/__init__.c \
|
||||
supervisor/Runtime.c \
|
||||
supervisor/__init__.c \
|
||||
watchdog/WatchDogMode.c \
|
||||
|
@ -384,6 +392,8 @@ SRC_SHARED_MODULE_ALL = \
|
|||
fontio/__init__.c \
|
||||
framebufferio/FramebufferDisplay.c \
|
||||
framebufferio/__init__.c \
|
||||
sdcardio/SDCard.c \
|
||||
sdcardio/__init__.c \
|
||||
gamepad/GamePad.c \
|
||||
gamepad/__init__.c \
|
||||
gamepadshift/GamePadShift.c \
|
||||
|
|
|
@ -537,6 +537,20 @@ extern const struct _mp_obj_module_t samd_module;
|
|||
#define SAMD_MODULE
|
||||
#endif
|
||||
|
||||
#if CIRCUITPY_SDCARDIO
|
||||
extern const struct _mp_obj_module_t sdcardio_module;
|
||||
#define SDCARDIO_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_sdcardio), (mp_obj_t)&sdcardio_module },
|
||||
#else
|
||||
#define SDCARDIO_MODULE
|
||||
#endif
|
||||
|
||||
#if CIRCUITPY_SDIOIO
|
||||
extern const struct _mp_obj_module_t sdioio_module;
|
||||
#define SDIOIO_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_sdioio), (mp_obj_t)&sdioio_module },
|
||||
#else
|
||||
#define SDIOIO_MODULE
|
||||
#endif
|
||||
|
||||
#if CIRCUITPY_STAGE
|
||||
extern const struct _mp_obj_module_t stage_module;
|
||||
#define STAGE_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR__stage), (mp_obj_t)&stage_module },
|
||||
|
@ -709,6 +723,8 @@ extern const struct _mp_obj_module_t watchdog_module;
|
|||
ROTARYIO_MODULE \
|
||||
RTC_MODULE \
|
||||
SAMD_MODULE \
|
||||
SDCARDIO_MODULE \
|
||||
SDIOIO_MODULE \
|
||||
STAGE_MODULE \
|
||||
STORAGE_MODULE \
|
||||
STRUCT_MODULE \
|
||||
|
|
|
@ -166,6 +166,12 @@ CFLAGS += -DCIRCUITPY_RTC=$(CIRCUITPY_RTC)
|
|||
CIRCUITPY_SAMD ?= 0
|
||||
CFLAGS += -DCIRCUITPY_SAMD=$(CIRCUITPY_SAMD)
|
||||
|
||||
CIRCUITPY_SDCARDIO ?= $(CIRCUITPY_FULL_BUILD)
|
||||
CFLAGS += -DCIRCUITPY_SDCARDIO=$(CIRCUITPY_SDCARDIO)
|
||||
|
||||
CIRCUITPY_SDIOIO ?= 0
|
||||
CFLAGS += -DCIRCUITPY_SDIOIO=$(CIRCUITPY_SDIOIO)
|
||||
|
||||
# Currently always off.
|
||||
CIRCUITPY_STAGE ?= 0
|
||||
CFLAGS += -DCIRCUITPY_STAGE=$(CIRCUITPY_STAGE)
|
||||
|
|
|
@ -418,3 +418,10 @@ const mp_obj_type_t busio_spi_type = {
|
|||
.make_new = busio_spi_make_new,
|
||||
.locals_dict = (mp_obj_dict_t*)&busio_spi_locals_dict,
|
||||
};
|
||||
|
||||
busio_spi_obj_t *validate_obj_is_spi_bus(mp_obj_t obj) {
|
||||
if (!MP_OBJ_IS_TYPE(obj, &busio_spi_type)) {
|
||||
mp_raise_TypeError_varg(translate("Expected a %q"), busio_spi_type.name);
|
||||
}
|
||||
return MP_OBJ_TO_PTR(obj);
|
||||
}
|
||||
|
|
|
@ -70,4 +70,6 @@ uint8_t common_hal_busio_spi_get_polarity(busio_spi_obj_t* self);
|
|||
// This is used by the supervisor to claim SPI devices indefinitely.
|
||||
extern void common_hal_busio_spi_never_reset(busio_spi_obj_t *self);
|
||||
|
||||
extern busio_spi_obj_t *validate_obj_is_spi_bus(mp_obj_t obj_in);
|
||||
|
||||
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BUSIO_SPI_H
|
||||
|
|
|
@ -101,6 +101,18 @@ mcu_pin_obj_t *validate_obj_is_free_pin(mp_obj_t obj) {
|
|||
return pin;
|
||||
}
|
||||
|
||||
// Validate every element in the list to be a free pin.
|
||||
void validate_list_is_free_pins(qstr what, mcu_pin_obj_t **pins_out, mp_int_t max_pins, mp_obj_t seq, uint8_t *count_out) {
|
||||
mp_int_t len = MP_OBJ_SMALL_INT_VALUE(mp_obj_len(seq));
|
||||
if (len > max_pins) {
|
||||
mp_raise_ValueError_varg(translate("At most %d %q may be specified (not %d)"), max_pins, what, len);
|
||||
}
|
||||
*count_out = len;
|
||||
for (mp_int_t i=0; i<len; i++) {
|
||||
pins_out[i] = validate_obj_is_free_pin(mp_obj_subscr(seq, MP_OBJ_NEW_SMALL_INT(i), MP_OBJ_SENTINEL));
|
||||
}
|
||||
}
|
||||
|
||||
// Validate that the obj is a free pin or None. Return an mcu_pin_obj_t* or NULL, correspondingly.
|
||||
mcu_pin_obj_t *validate_obj_is_free_pin_or_none(mp_obj_t obj) {
|
||||
if (obj == mp_const_none) {
|
||||
|
|
|
@ -37,6 +37,7 @@ mcu_pin_obj_t *validate_obj_is_pin(mp_obj_t obj);
|
|||
mcu_pin_obj_t *validate_obj_is_pin_or_none(mp_obj_t obj);
|
||||
mcu_pin_obj_t *validate_obj_is_free_pin(mp_obj_t obj);
|
||||
mcu_pin_obj_t *validate_obj_is_free_pin_or_none(mp_obj_t obj);
|
||||
void validate_list_is_free_pins(qstr what, mcu_pin_obj_t **pins_out, mp_int_t max_pins, mp_obj_t seq, uint8_t *count_out);
|
||||
|
||||
void assert_pin_free(const mcu_pin_obj_t* pin);
|
||||
|
||||
|
|
|
@ -50,13 +50,10 @@ STATIC uint8_t validate_pin(mp_obj_t obj) {
|
|||
}
|
||||
|
||||
STATIC void validate_pins(qstr what, uint8_t* pin_nos, mp_int_t max_pins, mp_obj_t seq, uint8_t *count_out) {
|
||||
mp_int_t len = MP_OBJ_SMALL_INT_VALUE(mp_obj_len(seq));
|
||||
if (len > max_pins) {
|
||||
mp_raise_ValueError_varg(translate("At most %d %q may be specified (not %d)"), max_pins, what, len);
|
||||
}
|
||||
*count_out = len;
|
||||
for (mp_int_t i=0; i<len; i++) {
|
||||
pin_nos[i] = validate_pin(mp_obj_subscr(seq, MP_OBJ_NEW_SMALL_INT(i), MP_OBJ_SENTINEL));
|
||||
mcu_pin_obj_t *pins[max_pins];
|
||||
validate_list_is_free_pins(what, pins, max_pins, seq, count_out);
|
||||
for (mp_int_t i=0; i<*count_out; i++) {
|
||||
pin_nos[i] = common_hal_mcu_pin_number(pins[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,183 @@
|
|||
/*
|
||||
* This file is part of the Micro Python 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 "py/obj.h"
|
||||
#include "py/objproperty.h"
|
||||
#include "py/runtime.h"
|
||||
#include "py/objarray.h"
|
||||
|
||||
#include "shared-bindings/sdcardio/SDCard.h"
|
||||
#include "shared-module/sdcardio/SDCard.h"
|
||||
#include "common-hal/busio/SPI.h"
|
||||
#include "shared-bindings/busio/SPI.h"
|
||||
#include "shared-bindings/microcontroller/Pin.h"
|
||||
#include "supervisor/flash.h"
|
||||
|
||||
//| class SDCard:
|
||||
//| """SD Card Block Interface
|
||||
//|
|
||||
//| Controls an SD card over SPI. This built-in module has higher read
|
||||
//| performance than the library adafruit_sdcard, but it is only compatible with
|
||||
//| `busio.SPI`, not `bitbangio.SPI`. Usually an SDCard object is used
|
||||
//| with ``storage.VfsFat`` to allow file I/O to an SD card."""
|
||||
//|
|
||||
//| def __init__(bus:busio.SPI, cs=digitalio.DigitalInOut, baudrate=8000000):
|
||||
//| """Construct an SPI SD Card object with the given properties
|
||||
//|
|
||||
//| :param busio.SPI spi: The SPI bus
|
||||
//| :param microcontroller.Pin cs: The chip select connected to the card
|
||||
//| :param int baudrate: The SPI data rate to use after card setup
|
||||
//|
|
||||
//| Note that during detection and configuration, a hard-coded low baudrate is used.
|
||||
//| Data transfers use the specified baurate (rounded down to one that is supported by
|
||||
//| the microcontroller)
|
||||
//|
|
||||
//| Example usage:
|
||||
//|
|
||||
//| .. code-block:: python
|
||||
//|
|
||||
//| import os
|
||||
//|
|
||||
//| import board
|
||||
//| import sdcardio
|
||||
//| import storage
|
||||
//|
|
||||
//| sd = sdcardio.SDCard(board.SPI(), board.SD_CS)
|
||||
//| vfs = storage.VfsFat(sd)
|
||||
//| storage.mount(vfs, '/sd')
|
||||
//| os.listdir('/sd')"""
|
||||
|
||||
STATIC mp_obj_t sdcardio_sdcard_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
enum { ARG_spi, ARG_cs, ARG_baudrate, ARG_sdio, NUM_ARGS };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_spi, MP_ARG_OBJ, {.u_obj = mp_const_none } },
|
||||
{ MP_QSTR_cs, MP_ARG_OBJ, {.u_obj = mp_const_none } },
|
||||
{ MP_QSTR_baudrate, MP_ARG_INT, {.u_int = 8000000} },
|
||||
{ MP_QSTR_sdio, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_int = 8000000} },
|
||||
};
|
||||
MP_STATIC_ASSERT( MP_ARRAY_SIZE(allowed_args) == NUM_ARGS );
|
||||
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);
|
||||
|
||||
busio_spi_obj_t *spi = validate_obj_is_spi_bus(args[ARG_spi].u_obj);
|
||||
mcu_pin_obj_t *cs = validate_obj_is_free_pin(args[ARG_cs].u_obj);
|
||||
|
||||
sdcardio_sdcard_obj_t *self = m_new_obj(sdcardio_sdcard_obj_t);
|
||||
self->base.type = &sdcardio_SDCard_type;
|
||||
|
||||
common_hal_sdcardio_sdcard_construct(self, spi, cs, args[ARG_baudrate].u_int);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
//| def count() -> int:
|
||||
//| """Returns the total number of sectors
|
||||
//|
|
||||
//| Due to technical limitations, this is a function and not a property.
|
||||
//|
|
||||
//| :return: The number of 512-byte blocks, as a number"""
|
||||
//|
|
||||
mp_obj_t sdcardio_sdcard_count(mp_obj_t self_in) {
|
||||
sdcardio_sdcard_obj_t *self = (sdcardio_sdcard_obj_t*)self_in;
|
||||
return mp_obj_new_int_from_ull(common_hal_sdcardio_sdcard_get_blockcount(self));
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(sdcardio_sdcard_count_obj, sdcardio_sdcard_count);
|
||||
|
||||
//| def deinit() -> None:
|
||||
//| """Disable permanently.
|
||||
//|
|
||||
//| :return: None"""
|
||||
//|
|
||||
mp_obj_t sdcardio_sdcard_deinit(mp_obj_t self_in) {
|
||||
sdcardio_sdcard_obj_t *self = (sdcardio_sdcard_obj_t*)self_in;
|
||||
common_hal_sdcardio_sdcard_deinit(self);
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(sdcardio_sdcard_deinit_obj, sdcardio_sdcard_deinit);
|
||||
|
||||
|
||||
//| def readblocks(start_block: int, buf: bytearray) -> None:
|
||||
//|
|
||||
//| """Read one or more blocks from the card
|
||||
//|
|
||||
//| :param int start_block: The block to start reading from
|
||||
//| :param bytearray buf: The buffer to write into. Length must be multiple of 512.
|
||||
//|
|
||||
//| :return: None"""
|
||||
//|
|
||||
|
||||
mp_obj_t sdcardio_sdcard_readblocks(mp_obj_t self_in, mp_obj_t start_block_in, mp_obj_t buf_in) {
|
||||
uint32_t start_block = mp_obj_get_int(start_block_in);
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_WRITE);
|
||||
sdcardio_sdcard_obj_t *self = (sdcardio_sdcard_obj_t*)self_in;
|
||||
int result = common_hal_sdcardio_sdcard_readblocks(self, start_block, &bufinfo);
|
||||
if (result < 0) {
|
||||
mp_raise_OSError(-result);
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
MP_DEFINE_CONST_FUN_OBJ_3(sdcardio_sdcard_readblocks_obj, sdcardio_sdcard_readblocks);
|
||||
|
||||
//| def writeblocks(start_block: int, buf: bytearray) -> None:
|
||||
//|
|
||||
//| """Write one or more blocks to the card
|
||||
//|
|
||||
//| :param int start_block: The block to start writing from
|
||||
//| :param bytearray buf: The buffer to read from. Length must be multiple of 512.
|
||||
//|
|
||||
//| :return: None"""
|
||||
//|
|
||||
|
||||
mp_obj_t sdcardio_sdcard_writeblocks(mp_obj_t self_in, mp_obj_t start_block_in, mp_obj_t buf_in) {
|
||||
uint32_t start_block = mp_obj_get_int(start_block_in);
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ);
|
||||
sdcardio_sdcard_obj_t *self = (sdcardio_sdcard_obj_t*)self_in;
|
||||
int result = common_hal_sdcardio_sdcard_writeblocks(self, start_block, &bufinfo);
|
||||
if (result < 0) {
|
||||
mp_raise_OSError(-result);
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_3(sdcardio_sdcard_writeblocks_obj, sdcardio_sdcard_writeblocks);
|
||||
|
||||
STATIC const mp_rom_map_elem_t sdcardio_sdcard_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_count), MP_ROM_PTR(&sdcardio_sdcard_count_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&sdcardio_sdcard_deinit_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_readblocks), MP_ROM_PTR(&sdcardio_sdcard_readblocks_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_writeblocks), MP_ROM_PTR(&sdcardio_sdcard_writeblocks_obj) },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(sdcardio_sdcard_locals_dict, sdcardio_sdcard_locals_dict_table);
|
||||
|
||||
const mp_obj_type_t sdcardio_SDCard_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_SDCard,
|
||||
.make_new = sdcardio_sdcard_make_new,
|
||||
.locals_dict = (mp_obj_dict_t*)&sdcardio_sdcard_locals_dict,
|
||||
};
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* This file is part of the Micro Python project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017, 2018 Scott Shawcroft for Adafruit Industries
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
extern const mp_obj_type_t sdcardio_SDCard_type;
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* 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 <stdint.h>
|
||||
|
||||
#include "py/obj.h"
|
||||
#include "py/runtime.h"
|
||||
|
||||
#include "shared-bindings/sdcardio/SDCard.h"
|
||||
|
||||
//| """Interface to an SD card via the SPI bus"""
|
||||
|
||||
STATIC const mp_rom_map_elem_t sdcardio_module_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_sdcardio) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_SDCard), MP_ROM_PTR(&sdcardio_SDCard_type) },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(sdcardio_module_globals, sdcardio_module_globals_table);
|
||||
|
||||
const mp_obj_module_t sdcardio_module = {
|
||||
.base = { &mp_type_module },
|
||||
.globals = (mp_obj_dict_t*)&sdcardio_module_globals,
|
||||
};
|
|
@ -0,0 +1,296 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// This file contains all of the Python API definitions for the
|
||||
// sdioio.SDCard class.
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "shared-bindings/microcontroller/Pin.h"
|
||||
#include "shared-bindings/sdioio/SDCard.h"
|
||||
#include "shared-bindings/util.h"
|
||||
|
||||
#include "lib/utils/buffer_helper.h"
|
||||
#include "lib/utils/context_manager_helpers.h"
|
||||
#include "py/mperrno.h"
|
||||
#include "py/objproperty.h"
|
||||
#include "py/runtime.h"
|
||||
#include "supervisor/shared/translate.h"
|
||||
|
||||
//| class SDCard:
|
||||
//| """SD Card Block Interface with SDIO
|
||||
//|
|
||||
//| Controls an SD card over SDIO. SDIO is a parallel protocol designed
|
||||
//| for SD cards. It uses a clock pin, a command pin, and 1 or 4
|
||||
//| data pins. It can be operated at a high frequency such as
|
||||
//| 25MHz. Usually an SDCard object is used with ``storage.VfsFat``
|
||||
//| to allow file I/O to an SD card."""
|
||||
//|
|
||||
//| def __init__(*, clock: digitalio.DigitalInOut, command: digitalio.DigitalInOut, data: List[digitalio.DigitalInOut], frequency: int):
|
||||
//| """Construct an SDIO SD Card object with the given properties
|
||||
//|
|
||||
//| :param ~microcontroller.Pin clock: the pin to use for the clock.
|
||||
//| :param ~microcontroller.Pin command: the pin to use for the command.
|
||||
//| :param data: A sequence of pins to use for data.
|
||||
//| :param frequency: The frequency of the bus in Hz
|
||||
//|
|
||||
//| Example usage:
|
||||
//|
|
||||
//| .. code-block:: python
|
||||
//|
|
||||
//| import os
|
||||
//|
|
||||
//| import board
|
||||
//| import sdioio
|
||||
//| import storage
|
||||
//|
|
||||
//| sd = sdioio.SDCard(
|
||||
//| clock=board.SDIO_CLOCK,
|
||||
//| command=board.SDIO_COMMAND,
|
||||
//| data=board.SDIO_DATA,
|
||||
//| frequency=25000000)
|
||||
//| vfs = storage.VfsFat(sd)
|
||||
//| storage.mount(vfs, '/sd')
|
||||
//| os.listdir('/sd')"""
|
||||
//| ...
|
||||
//|
|
||||
|
||||
STATIC mp_obj_t sdioio_sdcard_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
sdioio_sdcard_obj_t *self = m_new_obj(sdioio_sdcard_obj_t);
|
||||
self->base.type = &sdioio_SDCard_type;
|
||||
enum { ARG_clock, ARG_command, ARG_data, ARG_frequency, NUM_ARGS };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_clock, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_OBJ },
|
||||
{ MP_QSTR_command, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_OBJ },
|
||||
{ MP_QSTR_data, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_OBJ },
|
||||
{ MP_QSTR_frequency, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT },
|
||||
};
|
||||
MP_STATIC_ASSERT( MP_ARRAY_SIZE(allowed_args) == NUM_ARGS );
|
||||
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);
|
||||
|
||||
const mcu_pin_obj_t* clock = validate_obj_is_free_pin(args[ARG_clock].u_obj);
|
||||
const mcu_pin_obj_t* command = validate_obj_is_free_pin(args[ARG_command].u_obj);
|
||||
mcu_pin_obj_t *data_pins[4];
|
||||
uint8_t num_data;
|
||||
validate_list_is_free_pins(MP_QSTR_data, data_pins, MP_ARRAY_SIZE(data_pins), args[ARG_data].u_obj, &num_data);
|
||||
|
||||
common_hal_sdioio_sdcard_construct(self, clock, command, num_data, data_pins, args[ARG_frequency].u_int);
|
||||
return MP_OBJ_FROM_PTR(self);
|
||||
}
|
||||
|
||||
STATIC void check_for_deinit(sdioio_sdcard_obj_t *self) {
|
||||
if (common_hal_sdioio_sdcard_deinited(self)) {
|
||||
raise_deinited_error();
|
||||
}
|
||||
}
|
||||
|
||||
//| def configure(*, frequency=0, width=0) -> None:
|
||||
//| """Configures the SDIO bus.
|
||||
//|
|
||||
//| :param int frequency: the desired clock rate in Hertz. The actual clock rate may be higher or lower due to the granularity of available clock settings. Check the `frequency` attribute for the actual clock rate.
|
||||
//| :param int width: the number of data lines to use. Must be 1 or 4 and must also not exceed the number of data lines at construction
|
||||
//|
|
||||
//| .. note:: Leaving a value unspecified or 0 means the current setting is kept"""
|
||||
//|
|
||||
STATIC mp_obj_t sdioio_sdcard_configure(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
enum { ARG_frequency, ARG_width, NUM_ARGS };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_frequency, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
|
||||
{ MP_QSTR_width, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
|
||||
};
|
||||
sdioio_sdcard_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
|
||||
check_for_deinit(self);
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||
MP_STATIC_ASSERT( MP_ARRAY_SIZE(allowed_args) == NUM_ARGS );
|
||||
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
|
||||
mp_int_t frequency = args[ARG_frequency].u_int;
|
||||
if (frequency < 0) {
|
||||
mp_raise_ValueError_varg(translate("Invalid %q"), MP_QSTR_baudrate);
|
||||
}
|
||||
|
||||
uint8_t width = args[ARG_width].u_int;
|
||||
if (width != 0 && width != 1 && width != 4) {
|
||||
mp_raise_ValueError_varg(translate("Invalid %q"), MP_QSTR_width);
|
||||
}
|
||||
|
||||
if (!common_hal_sdioio_sdcard_configure(self, frequency, width)) {
|
||||
mp_raise_OSError(MP_EIO);
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_KW(sdioio_sdcard_configure_obj, 1, sdioio_sdcard_configure);
|
||||
|
||||
//| def count() -> int:
|
||||
//| """Returns the total number of sectors
|
||||
//|
|
||||
//| Due to technical limitations, this is a function and not a property.
|
||||
//|
|
||||
//| :return: The number of 512-byte blocks, as a number"""
|
||||
//|
|
||||
STATIC mp_obj_t sdioio_sdcard_count(mp_obj_t self_in) {
|
||||
sdioio_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
check_for_deinit(self);
|
||||
return MP_OBJ_NEW_SMALL_INT(common_hal_sdioio_sdcard_get_count(self));
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(sdioio_sdcard_count_obj, sdioio_sdcard_count);
|
||||
|
||||
//| def readblocks(start_block: int, buf: bytearray) -> None:
|
||||
//|
|
||||
//| """Read one or more blocks from the card
|
||||
//|
|
||||
//| :param int start_block: The block to start reading from
|
||||
//| :param bytearray buf: The buffer to write into. Length must be multiple of 512.
|
||||
//|
|
||||
//| :return: None"""
|
||||
mp_obj_t sdioio_sdcard_readblocks(mp_obj_t self_in, mp_obj_t start_block_in, mp_obj_t buf_in) {
|
||||
uint32_t start_block = mp_obj_get_int(start_block_in);
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_WRITE);
|
||||
sdioio_sdcard_obj_t *self = (sdioio_sdcard_obj_t*)self_in;
|
||||
int result = common_hal_sdioio_sdcard_readblocks(self, start_block, &bufinfo);
|
||||
if (result < 0) {
|
||||
mp_raise_OSError(-result);
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
MP_DEFINE_CONST_FUN_OBJ_3(sdioio_sdcard_readblocks_obj, sdioio_sdcard_readblocks);
|
||||
|
||||
//| def writeblocks(start_block: int, buf: bytearray) -> None:
|
||||
//|
|
||||
//| """Write one or more blocks to the card
|
||||
//|
|
||||
//| :param int start_block: The block to start writing from
|
||||
//| :param bytearray buf: The buffer to read from. Length must be multiple of 512.
|
||||
//|
|
||||
//| :return: None"""
|
||||
//|
|
||||
mp_obj_t sdioio_sdcard_writeblocks(mp_obj_t self_in, mp_obj_t start_block_in, mp_obj_t buf_in) {
|
||||
uint32_t start_block = mp_obj_get_int(start_block_in);
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_WRITE);
|
||||
sdioio_sdcard_obj_t *self = (sdioio_sdcard_obj_t*)self_in;
|
||||
int result = common_hal_sdioio_sdcard_writeblocks(self, start_block, &bufinfo);
|
||||
if (result < 0) {
|
||||
mp_raise_OSError(-result);
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
MP_DEFINE_CONST_FUN_OBJ_3(sdioio_sdcard_writeblocks_obj, sdioio_sdcard_writeblocks);
|
||||
|
||||
//| @property
|
||||
//| def frequency(self) -> int:
|
||||
//| """The actual SDIO bus frequency. This may not match the frequency
|
||||
//| requested due to internal limitations."""
|
||||
//| ...
|
||||
//|
|
||||
STATIC mp_obj_t sdioio_sdcard_obj_get_frequency(mp_obj_t self_in) {
|
||||
sdioio_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
check_for_deinit(self);
|
||||
return MP_OBJ_NEW_SMALL_INT(common_hal_sdioio_sdcard_get_frequency(self));
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(sdioio_sdcard_get_frequency_obj, sdioio_sdcard_obj_get_frequency);
|
||||
|
||||
const mp_obj_property_t sdioio_sdcard_frequency_obj = {
|
||||
.base.type = &mp_type_property,
|
||||
.proxy = {(mp_obj_t)&sdioio_sdcard_get_frequency_obj,
|
||||
(mp_obj_t)&mp_const_none_obj,
|
||||
(mp_obj_t)&mp_const_none_obj},
|
||||
};
|
||||
|
||||
//| @property
|
||||
//| def width(self) -> int:
|
||||
//| """The actual SDIO bus width, in bits"""
|
||||
//| ...
|
||||
//|
|
||||
STATIC mp_obj_t sdioio_sdcard_obj_get_width(mp_obj_t self_in) {
|
||||
sdioio_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
check_for_deinit(self);
|
||||
return MP_OBJ_NEW_SMALL_INT(common_hal_sdioio_sdcard_get_width(self));
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(sdioio_sdcard_get_width_obj, sdioio_sdcard_obj_get_width);
|
||||
|
||||
const mp_obj_property_t sdioio_sdcard_width_obj = {
|
||||
.base.type = &mp_type_property,
|
||||
.proxy = {(mp_obj_t)&sdioio_sdcard_get_width_obj,
|
||||
(mp_obj_t)&mp_const_none_obj,
|
||||
(mp_obj_t)&mp_const_none_obj},
|
||||
};
|
||||
|
||||
//| def deinit() -> None:
|
||||
//| """Disable permanently.
|
||||
//|
|
||||
//| :return: None"""
|
||||
STATIC mp_obj_t sdioio_sdcard_obj_deinit(mp_obj_t self_in) {
|
||||
sdioio_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
common_hal_sdioio_sdcard_deinit(self);
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(sdioio_sdcard_deinit_obj, sdioio_sdcard_obj_deinit);
|
||||
|
||||
//| def __enter__(self, ) -> Any:
|
||||
//| """No-op used by Context Managers.
|
||||
//| Provided by context manager helper."""
|
||||
//| ...
|
||||
//|
|
||||
|
||||
//| def __exit__(self, ) -> Any:
|
||||
//| """Automatically deinitializes the hardware when exiting a context. See
|
||||
//| :ref:`lifetime-and-contextmanagers` for more info."""
|
||||
//| ...
|
||||
//|
|
||||
STATIC mp_obj_t sdioio_sdcard_obj___exit__(size_t n_args, const mp_obj_t *args) {
|
||||
(void)n_args;
|
||||
common_hal_sdioio_sdcard_deinit(args[0]);
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(sdioio_sdcard_obj___exit___obj, 4, 4, sdioio_sdcard_obj___exit__);
|
||||
|
||||
STATIC const mp_rom_map_elem_t sdioio_sdcard_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&sdioio_sdcard_deinit_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&sdioio_sdcard_obj___exit___obj) },
|
||||
|
||||
{ MP_ROM_QSTR(MP_QSTR_configure), MP_ROM_PTR(&sdioio_sdcard_configure_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_frequency), MP_ROM_PTR(&sdioio_sdcard_frequency_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_width), MP_ROM_PTR(&sdioio_sdcard_width_obj) },
|
||||
|
||||
{ MP_ROM_QSTR(MP_QSTR_count), MP_ROM_PTR(&sdioio_sdcard_count_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_readblocks), MP_ROM_PTR(&sdioio_sdcard_readblocks_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_writeblocks), MP_ROM_PTR(&sdioio_sdcard_writeblocks_obj) },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(sdioio_sdcard_locals_dict, sdioio_sdcard_locals_dict_table);
|
||||
|
||||
const mp_obj_type_t sdioio_SDCard_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_SDCard,
|
||||
.make_new = sdioio_sdcard_make_new,
|
||||
.locals_dict = (mp_obj_dict_t*)&sdioio_sdcard_locals_dict,
|
||||
};
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BUSIO_SDIO_H
|
||||
#define MICROPY_INCLUDED_SHARED_BINDINGS_BUSIO_SDIO_H
|
||||
|
||||
#include "py/obj.h"
|
||||
|
||||
#include "common-hal/microcontroller/Pin.h"
|
||||
#include "common-hal/sdioio/SDCard.h"
|
||||
|
||||
// Type object used in Python. Should be shared between ports.
|
||||
extern const mp_obj_type_t sdioio_SDCard_type;
|
||||
|
||||
// Construct an underlying SDIO object.
|
||||
extern 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);
|
||||
|
||||
extern void common_hal_sdioio_sdcard_deinit(sdioio_sdcard_obj_t *self);
|
||||
extern bool common_hal_sdioio_sdcard_deinited(sdioio_sdcard_obj_t *self);
|
||||
|
||||
extern bool common_hal_sdioio_sdcard_configure(sdioio_sdcard_obj_t *self, uint32_t baudrate, uint8_t width);
|
||||
|
||||
extern void common_hal_sdioio_sdcard_unlock(sdioio_sdcard_obj_t *self);
|
||||
|
||||
// Return actual SDIO bus frequency.
|
||||
uint32_t common_hal_sdioio_sdcard_get_frequency(sdioio_sdcard_obj_t* self);
|
||||
|
||||
// Return SDIO bus width.
|
||||
uint8_t common_hal_sdioio_sdcard_get_width(sdioio_sdcard_obj_t* self);
|
||||
|
||||
// Return number of device blocks
|
||||
uint32_t common_hal_sdioio_sdcard_get_count(sdioio_sdcard_obj_t* self);
|
||||
|
||||
// Read or write blocks
|
||||
int common_hal_sdioio_sdcard_readblocks(sdioio_sdcard_obj_t* self, uint32_t start_block, mp_buffer_info_t *bufinfo);
|
||||
int common_hal_sdioio_sdcard_writeblocks(sdioio_sdcard_obj_t* self, uint32_t start_block, mp_buffer_info_t *bufinfo);
|
||||
|
||||
// This is used by the supervisor to claim SDIO devices indefinitely.
|
||||
extern void common_hal_sdioio_sdcard_never_reset(sdioio_sdcard_obj_t *self);
|
||||
|
||||
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BUSIO_SDIO_H
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* 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 <stdint.h>
|
||||
|
||||
#include "py/obj.h"
|
||||
#include "py/runtime.h"
|
||||
|
||||
#include "shared-bindings/sdioio/SDCard.h"
|
||||
|
||||
//| """Interface to an SD card via the SDIO bus"""
|
||||
|
||||
STATIC const mp_rom_map_elem_t sdioio_module_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_sdio) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_SDCard), MP_ROM_PTR(&sdioio_SDCard_type) },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(sdioio_module_globals, sdioio_module_globals_table);
|
||||
|
||||
const mp_obj_module_t sdioio_module = {
|
||||
.base = { &mp_type_module },
|
||||
.globals = (mp_obj_dict_t*)&sdioio_module_globals,
|
||||
};
|
|
@ -0,0 +1,466 @@
|
|||
/*
|
||||
* This file is part of the Micro Python 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.
|
||||
*/
|
||||
|
||||
// This implementation largely follows the structure of adafruit_sdcard.py
|
||||
|
||||
#include "shared-bindings/busio/SPI.h"
|
||||
#include "shared-bindings/digitalio/DigitalInOut.h"
|
||||
#include "shared-bindings/time/__init__.h"
|
||||
#include "shared-bindings/util.h"
|
||||
#include "shared-module/sdcardio/SDCard.h"
|
||||
|
||||
#include "py/mperrno.h"
|
||||
|
||||
#if 0
|
||||
#define DEBUG_PRINT(...) ((void)mp_printf(&mp_plat_print, ## __VA_ARGS__))
|
||||
#else
|
||||
#define DEBUG_PRINT(...) ((void)0)
|
||||
#endif
|
||||
|
||||
#define CMD_TIMEOUT (200)
|
||||
|
||||
#define R1_IDLE_STATE (1<<0)
|
||||
#define R1_ILLEGAL_COMMAND (1<<2)
|
||||
|
||||
#define TOKEN_CMD25 (0xFC)
|
||||
#define TOKEN_STOP_TRAN (0xFD)
|
||||
#define TOKEN_DATA (0xFE)
|
||||
|
||||
STATIC bool lock_and_configure_bus(sdcardio_sdcard_obj_t *self) {
|
||||
if (!common_hal_busio_spi_try_lock(self->bus)) {
|
||||
return false;
|
||||
}
|
||||
common_hal_busio_spi_configure(self->bus, self->baudrate, 0, 0, 8);
|
||||
common_hal_digitalio_digitalinout_set_value(&self->cs, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
STATIC void lock_bus_or_throw(sdcardio_sdcard_obj_t *self) {
|
||||
if (!lock_and_configure_bus(self)) {
|
||||
mp_raise_OSError(EAGAIN);
|
||||
}
|
||||
}
|
||||
|
||||
STATIC void clock_card(sdcardio_sdcard_obj_t *self, int bytes) {
|
||||
uint8_t buf[] = {0xff};
|
||||
common_hal_digitalio_digitalinout_set_value(&self->cs, true);
|
||||
for (int i=0; i<bytes; i++) {
|
||||
common_hal_busio_spi_write(self->bus, buf, 1);
|
||||
}
|
||||
}
|
||||
|
||||
STATIC void extraclock_and_unlock_bus(sdcardio_sdcard_obj_t *self) {
|
||||
clock_card(self, 1);
|
||||
common_hal_busio_spi_unlock(self->bus);
|
||||
}
|
||||
|
||||
static uint8_t CRC7(const uint8_t* data, uint8_t n) {
|
||||
uint8_t crc = 0;
|
||||
for (uint8_t i = 0; i < n; i++) {
|
||||
uint8_t d = data[i];
|
||||
for (uint8_t j = 0; j < 8; j++) {
|
||||
crc <<= 1;
|
||||
if ((d & 0x80) ^ (crc & 0x80)) {
|
||||
crc ^= 0x09;
|
||||
}
|
||||
d <<= 1;
|
||||
}
|
||||
}
|
||||
return (crc << 1) | 1;
|
||||
}
|
||||
|
||||
#define READY_TIMEOUT_NS (300 * 1000 * 1000) // 300ms
|
||||
STATIC void wait_for_ready(sdcardio_sdcard_obj_t *self) {
|
||||
uint64_t deadline = common_hal_time_monotonic_ns() + READY_TIMEOUT_NS;
|
||||
while (common_hal_time_monotonic_ns() < deadline) {
|
||||
uint8_t b;
|
||||
common_hal_busio_spi_read(self->bus, &b, 1, 0xff);
|
||||
if (b == 0xff) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// In Python API, defaults are response=None, data_block=True, wait=True
|
||||
STATIC int cmd(sdcardio_sdcard_obj_t *self, int cmd, int arg, void *response_buf, size_t response_len, bool data_block, bool wait) {
|
||||
DEBUG_PRINT("cmd % 3d [%02x] arg=% 11d [%08x] len=%d%s%s\n", cmd, cmd, arg, arg, response_len, data_block ? " data" : "", wait ? " wait" : "");
|
||||
uint8_t cmdbuf[6];
|
||||
cmdbuf[0] = cmd | 0x40;
|
||||
cmdbuf[1] = (arg >> 24) & 0xff;
|
||||
cmdbuf[2] = (arg >> 16) & 0xff;
|
||||
cmdbuf[3] = (arg >> 8) & 0xff;
|
||||
cmdbuf[4] = arg & 0xff;
|
||||
cmdbuf[5] = CRC7(cmdbuf, 5);
|
||||
|
||||
if (wait) {
|
||||
wait_for_ready(self);
|
||||
}
|
||||
|
||||
common_hal_busio_spi_write(self->bus, cmdbuf, sizeof(cmdbuf));
|
||||
|
||||
// Wait for the response (response[7] == 0)
|
||||
bool response_received = false;
|
||||
for (int i=0; i<CMD_TIMEOUT; i++) {
|
||||
common_hal_busio_spi_read(self->bus, cmdbuf, 1, 0xff);
|
||||
if ((cmdbuf[0] & 0x80) == 0) {
|
||||
response_received = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!response_received) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (response_buf) {
|
||||
|
||||
if (data_block) {
|
||||
cmdbuf[1] = 0xff;
|
||||
do {
|
||||
// Wait for the start block byte
|
||||
common_hal_busio_spi_read(self->bus, cmdbuf+1, 1, 0xff);
|
||||
} while (cmdbuf[1] != 0xfe);
|
||||
}
|
||||
|
||||
common_hal_busio_spi_read(self->bus, response_buf, response_len, 0xff);
|
||||
|
||||
if (data_block) {
|
||||
// Read and discard the CRC-CCITT checksum
|
||||
common_hal_busio_spi_read(self->bus, cmdbuf+1, 2, 0xff);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return cmdbuf[0];
|
||||
}
|
||||
|
||||
STATIC int block_cmd(sdcardio_sdcard_obj_t *self, int cmd_, int block, void *response_buf, size_t response_len, bool data_block, bool wait) {
|
||||
return cmd(self, cmd_, block * self->cdv, response_buf, response_len, true, true);
|
||||
}
|
||||
|
||||
STATIC bool cmd_nodata(sdcardio_sdcard_obj_t* self, int cmd, int response) {
|
||||
uint8_t cmdbuf[2] = {cmd, 0xff};
|
||||
|
||||
common_hal_busio_spi_write(self->bus, cmdbuf, sizeof(cmdbuf));
|
||||
|
||||
// Wait for the response (response[7] == response)
|
||||
for (int i=0; i<CMD_TIMEOUT; i++) {
|
||||
common_hal_busio_spi_read(self->bus, cmdbuf, 1, 0xff);
|
||||
if (cmdbuf[0] == response) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
STATIC const compressed_string_t *init_card_v1(sdcardio_sdcard_obj_t *self) {
|
||||
for (int i=0; i<CMD_TIMEOUT; i++) {
|
||||
if (cmd(self, 41, 0, NULL, 0, true, true) == 0) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return translate("timeout waiting for v1 card");
|
||||
}
|
||||
|
||||
STATIC const compressed_string_t *init_card_v2(sdcardio_sdcard_obj_t *self) {
|
||||
for (int i=0; i<CMD_TIMEOUT; i++) {
|
||||
uint8_t ocr[4];
|
||||
common_hal_time_delay_ms(50);
|
||||
cmd(self, 58, 0, ocr, sizeof(ocr), false, true);
|
||||
cmd(self, 55, 0, NULL, 0, true, true);
|
||||
if (cmd(self, 41, 0x40000000, NULL, 0, true, true) == 0) {
|
||||
cmd(self, 58, 0, ocr, sizeof(ocr), false, true);
|
||||
if ((ocr[0] & 0x40) != 0) {
|
||||
self->cdv = 1;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return translate("timeout waiting for v2 card");
|
||||
}
|
||||
|
||||
STATIC const compressed_string_t *init_card(sdcardio_sdcard_obj_t *self) {
|
||||
clock_card(self, 10);
|
||||
|
||||
common_hal_digitalio_digitalinout_set_value(&self->cs, false);
|
||||
|
||||
// CMD0: init card: should return _R1_IDLE_STATE (allow 5 attempts)
|
||||
{
|
||||
bool reached_idle_state = false;
|
||||
for (int i=0; i<5; i++) {
|
||||
if (cmd(self, 0, 0, NULL, 0, true, true) == R1_IDLE_STATE) {
|
||||
reached_idle_state = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!reached_idle_state) {
|
||||
return translate("no SD card");
|
||||
}
|
||||
}
|
||||
|
||||
// CMD8: determine card version
|
||||
{
|
||||
uint8_t rb7[4];
|
||||
int response = cmd(self, 8, 0x1AA, rb7, sizeof(rb7), false, true);
|
||||
if (response == R1_IDLE_STATE) {
|
||||
const compressed_string_t *result =init_card_v2(self);
|
||||
if (result != NULL) {
|
||||
return result;
|
||||
}
|
||||
} else if (response == (R1_IDLE_STATE | R1_ILLEGAL_COMMAND)) {
|
||||
const compressed_string_t *result =init_card_v1(self);
|
||||
if (result != NULL) {
|
||||
return result;
|
||||
}
|
||||
} else {
|
||||
return translate("couldn't determine SD card version");
|
||||
}
|
||||
}
|
||||
|
||||
// CMD9: get number of sectors
|
||||
{
|
||||
uint8_t csd[16];
|
||||
int response = cmd(self, 9, 0, csd, sizeof(csd), true, true);
|
||||
if (response != 0) {
|
||||
return translate("no response from SD card");
|
||||
}
|
||||
int csd_version = (csd[0] & 0xC0) >> 6;
|
||||
if (csd_version >= 2) {
|
||||
return translate("SD card CSD format not supported");
|
||||
}
|
||||
|
||||
if (csd_version == 1) {
|
||||
self->sectors = ((csd[8] << 8 | csd[9]) + 1) * 1024;
|
||||
} else {
|
||||
uint32_t block_length = 1 << (csd[5] & 0xF);
|
||||
uint32_t c_size = ((csd[6] & 0x3) << 10) | (csd[7] << 2) | ((csd[8] & 0xC) >> 6);
|
||||
uint32_t mult = 1 << (((csd[9] & 0x3) << 1 | (csd[10] & 0x80) >> 7) + 2);
|
||||
self->sectors = block_length / 512 * mult * (c_size + 1);
|
||||
}
|
||||
}
|
||||
|
||||
// CMD16: set block length to 512 bytes
|
||||
{
|
||||
int response = cmd(self, 16, 512, NULL, 0, true, true);
|
||||
if (response != 0) {
|
||||
return translate("can't set 512 block size");
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void common_hal_sdcardio_sdcard_construct(sdcardio_sdcard_obj_t *self, busio_spi_obj_t *bus, mcu_pin_obj_t *cs, int baudrate) {
|
||||
self->bus = bus;
|
||||
common_hal_digitalio_digitalinout_construct(&self->cs, cs);
|
||||
common_hal_digitalio_digitalinout_switch_to_output(&self->cs, true, DRIVE_MODE_PUSH_PULL);
|
||||
|
||||
self->cdv = 512;
|
||||
self->sectors = 0;
|
||||
self->baudrate = 250000;
|
||||
|
||||
lock_bus_or_throw(self);
|
||||
const compressed_string_t *result = init_card(self);
|
||||
extraclock_and_unlock_bus(self);
|
||||
|
||||
if (result != NULL) {
|
||||
common_hal_digitalio_digitalinout_deinit(&self->cs);
|
||||
mp_raise_OSError_msg(result);
|
||||
}
|
||||
|
||||
self->baudrate = baudrate;
|
||||
}
|
||||
|
||||
void common_hal_sdcardio_sdcard_deinit(sdcardio_sdcard_obj_t *self) {
|
||||
if (!self->bus) {
|
||||
return;
|
||||
}
|
||||
self->bus = 0;
|
||||
common_hal_digitalio_digitalinout_deinit(&self->cs);
|
||||
}
|
||||
|
||||
void common_hal_sdcardio_check_for_deinit(sdcardio_sdcard_obj_t *self) {
|
||||
if (!self->bus) {
|
||||
raise_deinited_error();
|
||||
}
|
||||
}
|
||||
|
||||
int common_hal_sdcardio_sdcard_get_blockcount(sdcardio_sdcard_obj_t *self) {
|
||||
common_hal_sdcardio_check_for_deinit(self);
|
||||
return self->sectors;
|
||||
}
|
||||
|
||||
int readinto(sdcardio_sdcard_obj_t *self, void *buf, size_t size) {
|
||||
uint8_t aux[2] = {0, 0};
|
||||
while (aux[0] != 0xfe) {
|
||||
common_hal_busio_spi_read(self->bus, aux, 1, 0xff);
|
||||
}
|
||||
|
||||
common_hal_busio_spi_read(self->bus, buf, size, 0xff);
|
||||
|
||||
// Read checksum and throw it away
|
||||
common_hal_busio_spi_read(self->bus, aux, sizeof(aux), 0xff);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int readblocks(sdcardio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *buf) {
|
||||
uint32_t nblocks = buf->len / 512;
|
||||
if (nblocks == 1) {
|
||||
// Use CMD17 to read a single block
|
||||
return block_cmd(self, 17, start_block, buf->buf, buf->len, true, true);
|
||||
} else {
|
||||
// Use CMD18 to read multiple blocks
|
||||
int r = block_cmd(self, 18, start_block, NULL, 0, true, true);
|
||||
if (r < 0) {
|
||||
return r;
|
||||
}
|
||||
|
||||
uint8_t *ptr = buf->buf;
|
||||
while (nblocks--) {
|
||||
r = readinto(self, ptr, 512);
|
||||
if (r < 0) {
|
||||
return r;
|
||||
}
|
||||
ptr += 512;
|
||||
}
|
||||
|
||||
// End the multi-block read
|
||||
r = cmd(self, 12, 0, NULL, 0, true, false);
|
||||
|
||||
// Return first status 0 or last before card ready (0xff)
|
||||
while (r != 0) {
|
||||
uint8_t single_byte;
|
||||
common_hal_busio_spi_read(self->bus, &single_byte, 1, 0xff);
|
||||
if (single_byte & 0x80) {
|
||||
return r;
|
||||
}
|
||||
r = single_byte;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int common_hal_sdcardio_sdcard_readblocks(sdcardio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *buf) {
|
||||
common_hal_sdcardio_check_for_deinit(self);
|
||||
if (buf->len % 512 != 0) {
|
||||
mp_raise_ValueError(translate("Buffer length must be a multiple of 512"));
|
||||
}
|
||||
|
||||
lock_and_configure_bus(self);
|
||||
int r = readblocks(self, start_block, buf);
|
||||
extraclock_and_unlock_bus(self);
|
||||
return r;
|
||||
}
|
||||
|
||||
int _write(sdcardio_sdcard_obj_t *self, uint8_t token, void *buf, size_t size) {
|
||||
wait_for_ready(self);
|
||||
|
||||
uint8_t cmd[2];
|
||||
cmd[0] = token;
|
||||
|
||||
common_hal_busio_spi_write(self->bus, cmd, 1);
|
||||
common_hal_busio_spi_write(self->bus, buf, size);
|
||||
|
||||
cmd[0] = cmd[1] = 0xff;
|
||||
common_hal_busio_spi_write(self->bus, cmd, 2);
|
||||
|
||||
// Check the response
|
||||
// This differs from the traditional adafruit_sdcard handling,
|
||||
// but adafruit_sdcard also ignored the return value of SDCard._write(!)
|
||||
// so nobody noticed
|
||||
//
|
||||
//
|
||||
// Response is as follows:
|
||||
// x x x 0 STAT 1
|
||||
// 7 6 5 4 3..1 0
|
||||
// with STATUS 010 indicating "data accepted", and other status bit
|
||||
// combinations indicating failure.
|
||||
// In practice, I was seeing cmd[0] as 0xe5, indicating success
|
||||
for (int i=0; i<CMD_TIMEOUT; i++) {
|
||||
common_hal_busio_spi_read(self->bus, cmd, 1, 0xff);
|
||||
DEBUG_PRINT("i=%02d cmd[0] = 0x%02x\n", i, cmd[0]);
|
||||
if ((cmd[0] & 0b00010001) == 0b00000001) {
|
||||
if ((cmd[0] & 0x1f) != 0x5) {
|
||||
return -EIO;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Wait for the write to finish
|
||||
do {
|
||||
common_hal_busio_spi_read(self->bus, cmd, 1, 0xff);
|
||||
} while (cmd[0] == 0);
|
||||
|
||||
// Success
|
||||
return 0;
|
||||
}
|
||||
|
||||
int writeblocks(sdcardio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *buf) {
|
||||
common_hal_sdcardio_check_for_deinit(self);
|
||||
uint32_t nblocks = buf->len / 512;
|
||||
if (nblocks == 1) {
|
||||
// Use CMD24 to write a single block
|
||||
int r = block_cmd(self, 24, start_block, NULL, 0, true, true);
|
||||
if (r < 0) {
|
||||
return r;
|
||||
}
|
||||
r = _write(self, TOKEN_DATA, buf->buf, buf->len);
|
||||
if (r < 0) {
|
||||
return r;
|
||||
}
|
||||
} else {
|
||||
// Use CMD25 to write multiple block
|
||||
int r = block_cmd(self, 25, start_block, NULL, 0, true, true);
|
||||
if (r < 0) {
|
||||
return r;
|
||||
}
|
||||
|
||||
uint8_t *ptr = buf->buf;
|
||||
while (nblocks--) {
|
||||
r = _write(self, TOKEN_CMD25, ptr, 512);
|
||||
if (r < 0) {
|
||||
return r;
|
||||
}
|
||||
ptr += 512;
|
||||
}
|
||||
|
||||
cmd_nodata(self, TOKEN_STOP_TRAN, 0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int common_hal_sdcardio_sdcard_writeblocks(sdcardio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *buf) {
|
||||
common_hal_sdcardio_check_for_deinit(self);
|
||||
if (buf->len % 512 != 0) {
|
||||
mp_raise_ValueError(translate("Buffer length must be a multiple of 512"));
|
||||
}
|
||||
lock_and_configure_bus(self);
|
||||
int r = writeblocks(self, start_block, buf);
|
||||
extraclock_and_unlock_bus(self);
|
||||
return r;
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* This file is part of the Micro Python 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "py/obj.h"
|
||||
#include "py/objproperty.h"
|
||||
#include "py/runtime.h"
|
||||
#include "py/objarray.h"
|
||||
|
||||
#include "common-hal/busio/SPI.h"
|
||||
#include "common-hal/digitalio/DigitalInOut.h"
|
||||
|
||||
typedef struct {
|
||||
mp_obj_base_t base;
|
||||
busio_spi_obj_t *bus;
|
||||
digitalio_digitalinout_obj_t cs;
|
||||
int cdv;
|
||||
int baudrate;
|
||||
uint32_t sectors;
|
||||
} sdcardio_sdcard_obj_t;
|
||||
|
||||
void common_hal_sdcardio_sdcard_construct(sdcardio_sdcard_obj_t *self, busio_spi_obj_t *spi, mcu_pin_obj_t *cs, int baudrate);
|
||||
void common_hal_sdcardio_sdcard_deinit(sdcardio_sdcard_obj_t *self);
|
||||
void common_hal_sdcardio_sdcard_check_for_deinit(sdcardio_sdcard_obj_t *self);
|
||||
int common_hal_sdcardio_sdcard_get_blockcount(sdcardio_sdcard_obj_t *self);
|
||||
int common_hal_sdcardio_sdcard_readblocks(sdcardio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *buf);
|
||||
int common_hal_sdcardio_sdcard_writeblocks(sdcardio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *buf);
|
|
@ -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')
|
Loading…
Reference in New Issue