mimxrt/sdcard: Implement SDCard driver.

- Configures `PLL2->PFD0` with **198MHz** as base clock of
	`USDHCx` peripheral.
- Adds guards for SDCard related files via `MICROPY_PY_MACHINE_SDCARD`
- Adds creation of pin defines for SDCard to make-pins.py
- Adds new configuration option for SDCard peripheral pinout
        to mpconfigport.h
- Adds interrupt handling support instead of polling
- Adds support for `ADMA2` powered data transfer
- Configures SDCard to run in HS (high-speed mode) with **50MHz** only!

SDCard support is optional and requires `USDHC` peripheral.
Thus this driver is not available on `MIMXRT1010_EVK`.
SDCard support is enabled by setting `MICROPY_PY_MACHINE_SDCARD = 1`
in mpconfigboard.mk.

Signed-off-by: Philipp Ebensberger
This commit is contained in:
Philipp Ebensberger 2021-08-01 11:20:39 +02:00
parent bbbdef4cc1
commit 87f97e490c
30 changed files with 1672 additions and 70 deletions

View File

@ -20,6 +20,7 @@ QSTR_GLOBAL_DEPENDENCIES = $(BOARD_DIR)/mpconfigboard.h
# MicroPython feature configurations
FROZEN_MANIFEST ?= boards/manifest.py
MICROPY_VFS_LFS2 ?= 1
MICROPY_VFS_FAT ?= 1
# Include py core make definitions
include $(TOP)/py/py.mk
@ -44,27 +45,32 @@ GEN_PINS_AF_PY = $(BUILD)/pins_af.py
CFLAGS += -Wno-error=unused-parameter
INC += -I.
INC += -I$(TOP)
INC += -I$(BUILD)
INC += -I$(BOARD_DIR)
INC += -I$(TOP)/lib/cmsis/inc
INC += -I$(BUILD)
INC += -I$(TOP)
INC += -I$(TOP)/$(MCU_DIR)
INC += -I$(TOP)/$(MCU_DIR)/drivers
INC += -I$(TOP)/$(MCU_DIR)/project_template
INC += -I$(TOP)/lib/tinyusb/src
INC += -I$(TOP)/lib/cmsis/inc
INC += -I$(TOP)/lib/oofatfs
INC += -I$(TOP)/lib/tinyusb/hw
INC += -I$(TOP)/lib/tinyusb/hw/bsp/teensy_40
INC += -I$(TOP)/lib/tinyusb/src
CFLAGS_MCU = -mtune=cortex-m7 -mcpu=cortex-m7 -mfloat-abi=hard -mfpu=fpv5-d16
CFLAGS += $(INC) -Wall -Werror -Wdouble-promotion -Wfloat-conversion -std=c99 -nostdlib -mthumb $(CFLAGS_MCU)
CFLAGS += -DCPU_$(MCU_SERIES) -DCPU_$(MCU_VARIANT)
CFLAGS += -DXIP_EXTERNAL_FLASH=1 \
-DXIP_BOOT_HEADER_ENABLE=1 \
-DFSL_SDK_ENABLE_DRIVER_CACHE_CONTROL=1 \
-DCFG_TUSB_MCU=OPT_MCU_MIMXRT10XX \
-D__STARTUP_CLEAR_BSS \
-D__STARTUP_INITIALIZE_RAMFUNCTION \
-D__START=main \
-DCPU_HEADER_H='<$(MCU_SERIES).h>'
ifeq ($(MICROPY_PY_MACHINE_SDCARD),1)
CFLAGS += -DMICROPY_PY_MACHINE_SDCARD=1
endif
CFLAGS += $(CFLAGS_MOD) $(CFLAGS_EXTRA)
# Configure floating point support
@ -98,64 +104,71 @@ endif
# TinyUSB Stack source
SRC_TINYUSB_C += \
lib/tinyusb/src/tusb.c \
lib/tinyusb/src/common/tusb_fifo.c \
lib/tinyusb/src/device/usbd.c \
lib/tinyusb/src/device/usbd_control.c \
lib/tinyusb/src/class/msc/msc_device.c \
lib/tinyusb/src/class/cdc/cdc_device.c \
lib/tinyusb/src/class/dfu/dfu_rt_device.c \
lib/tinyusb/src/class/hid/hid_device.c \
lib/tinyusb/src/class/midi/midi_device.c \
lib/tinyusb/src/class/msc/msc_device.c \
lib/tinyusb/src/class/usbtmc/usbtmc_device.c \
lib/tinyusb/src/class/vendor/vendor_device.c \
lib/tinyusb/src/portable/nxp/transdimension/dcd_transdimension.c
lib/tinyusb/src/common/tusb_fifo.c \
lib/tinyusb/src/device/usbd.c \
lib/tinyusb/src/device/usbd_control.c \
lib/tinyusb/src/portable/nxp/transdimension/dcd_transdimension.c \
lib/tinyusb/src/tusb.c
SRC_HAL_IMX_C += \
$(MCU_DIR)/system_$(MCU_SERIES).c \
$(MCU_DIR)/xip/fsl_flexspi_nor_boot.c \
$(MCU_DIR)/project_template/clock_config.c \
$(MCU_DIR)/drivers/fsl_adc.c \
$(MCU_DIR)/drivers/fsl_cache.c \
$(MCU_DIR)/drivers/fsl_clock.c \
$(MCU_DIR)/drivers/fsl_common.c \
$(MCU_DIR)/drivers/fsl_dmamux.c \
$(MCU_DIR)/drivers/fsl_edma.c \
$(MCU_DIR)/drivers/fsl_flexram.c \
$(MCU_DIR)/drivers/fsl_flexspi.c \
$(MCU_DIR)/drivers/fsl_gpio.c \
$(MCU_DIR)/drivers/fsl_gpt.c \
$(MCU_DIR)/drivers/fsl_common.c \
$(MCU_DIR)/drivers/fsl_lpi2c.c \
$(MCU_DIR)/drivers/fsl_lpspi.c \
$(MCU_DIR)/drivers/fsl_lpspi_edma.c \
$(MCU_DIR)/drivers/fsl_lpuart.c \
$(MCU_DIR)/drivers/fsl_flexram.c \
$(MCU_DIR)/drivers/fsl_flexspi.c \
$(MCU_DIR)/drivers/fsl_pit.c \
$(MCU_DIR)/drivers/fsl_snvs_lp.c \
$(MCU_DIR)/drivers/fsl_trng.c \
$(MCU_DIR)/project_template/clock_config.c \
$(MCU_DIR)/system_$(MCU_SERIES).c \
$(MCU_DIR)/xip/fsl_flexspi_nor_boot.c \
ifeq ($(MICROPY_PY_MACHINE_SDCARD),1)
SRC_HAL_IMX_C += $(MCU_DIR)/drivers/fsl_usdhc.c
endif
SRC_C += \
main.c \
led.c \
pin.c \
ticks.c \
tusb_port.c \
$(BOARD_DIR)/flash_config.c \
board_init.c \
dma_channel.c \
$(BOARD_DIR)/flash_config.c \
drivers/bus/softspi.c \
extmod/modonewire.c \
fatfs_port.c \
led.c \
machine_adc.c \
machine_i2c.c \
machine_led.c \
machine_pin.c \
machine_rtc.c \
machine_sdcard.c \
machine_spi.c \
machine_timer.c \
machine_uart.c \
main.c \
mimxrt_flash.c \
modutime.c \
modmachine.c \
modmimxrt.c \
moduos.c \
modutime.c \
mphalport.c \
pin.c \
sdcard.c \
shared/libc/printf.c \
shared/libc/string0.c \
shared/readline/readline.c \
@ -165,8 +178,8 @@ SRC_C += \
shared/runtime/stdout_helpers.c \
shared/runtime/sys_stdio_mphal.c \
shared/timeutils/timeutils.c \
drivers/bus/softspi.c \
extmod/modonewire.c \
ticks.c \
tusb_port.c \
$(SRC_TINYUSB_C) \
$(SRC_HAL_IMX_C) \
@ -188,9 +201,9 @@ LIBM_SRC_C += $(addprefix lib/libm_dbl/,\
atan2.c \
atanh.c \
ceil.c \
copysign.c \
cos.c \
cosh.c \
copysign.c \
erf.c \
exp.c \
expm1.c \
@ -222,7 +235,6 @@ LIBM_SRC_C += lib/libm_dbl/sqrt.c
endif
else
LIBM_SRC_C += $(addprefix lib/libm/,\
math.c \
acoshf.c \
asinfacosf.c \
asinhf.c \
@ -237,6 +249,7 @@ LIBM_SRC_C += $(addprefix lib/libm/,\
kf_sin.c \
kf_tan.c \
log1pf.c \
math.c \
nearbyintf.c \
roundf.c \
sf_cos.c \
@ -263,28 +276,29 @@ ifeq ($(MICROPY_FLOAT_IMPL),double)
$(LIBM_O): CFLAGS := $(filter-out -Wdouble-promotion -Wfloat-conversion, $(CFLAGS))
endif
SRC_SS = $(MCU_DIR)/gcc/startup_$(MCU_SERIES).S
SRC_SS += $(MCU_DIR)/gcc/startup_$(MCU_SERIES).S
SRC_S = shared/runtime/gchelper_m3.s \
SRC_S += shared/runtime/gchelper_m3.s \
# List of sources for qstr extraction
SRC_QSTR += \
extmod/modonewire.c \
machine_adc.c \
machine_led.c \
machine_pin.c \
machine_rtc.c \
machine_sdcard.c \
machine_spi.c \
machine_timer.c \
machine_uart.c \
mimxrt_flash.c \
modutime.c \
modmachine.c \
modmimxrt.c \
moduos.c \
modutime.c \
pin.c \
shared/runtime/mpirq.c \
shared/runtime/sys_stdio_mphal.c \
extmod/modonewire.c \
$(GEN_PINS_SRC) \
OBJ += $(PY_O)
@ -327,6 +341,7 @@ $(HEADER_BUILD)/qstrdefs.generated.h: $(BOARD_DIR)/mpconfigboard.h
$(BUILD)/%_gen.c $(HEADER_BUILD)/%.h: $(BOARD_PINS) $(MAKE_PINS) $(AF_FILE) $(PREFIX_FILE) | $(HEADER_BUILD)
$(ECHO) "Create $@"
$(Q)$(PYTHON) $(MAKE_PINS) --board $(BOARD_PINS) --af $(AF_FILE)\
--iomux $(abspath $(TOP)/$(MCU_DIR)/drivers/fsl_iomuxc.h) \
--prefix $(PREFIX_FILE) --hdr $(GEN_PINS_HDR) > $(GEN_PINS_SRC)
$(BUILD)/pins_gen.o: $(BUILD)/pins_gen.c

View File

@ -40,7 +40,6 @@
#include "clock_config.h"
#include "modmachine.h"
volatile uint32_t systick_ms = 0;
const uint8_t dcd_data[] = { 0x00 };
@ -85,6 +84,11 @@ void board_init(void) {
// PIT
machine_timer_init_PIT();
// SDCard
#if MICROPY_PY_MACHINE_SDCARD
machine_sdcard_init0();
#endif
}
void USB_OTG1_IRQHandler(void) {

View File

@ -2,6 +2,7 @@ MCU_SERIES = MIMXRT1011
MCU_VARIANT = MIMXRT1011DAE5A
MICROPY_FLOAT_IMPL = single
MICROPY_PY_MACHINE_SDCARD = 0
SRC_C += \
hal/flexspi_nor_flash.c \

View File

@ -64,3 +64,15 @@
{ IOMUXC_GPIO_AD_B1_08_LPI2C2_SCL }, { IOMUXC_GPIO_AD_B1_09_LPI2C2_SDA }, \
{ 0 }, { 0 }, \
{ IOMUXC_GPIO_SD_B1_02_LPI2C4_SCL }, { IOMUXC_GPIO_SD_B1_03_LPI2C4_SDA },
#define USDHC_DUMMY_PIN NULL , 0
#define MICROPY_USDHC1 \
{ \
.cmd = {GPIO_SD_B0_02_USDHC1_CMD}, \
.clk = { GPIO_SD_B0_03_USDHC1_CLK }, \
.cd_b = { GPIO_SD_B0_06_USDHC1_CD_B },\
.data0 = { GPIO_SD_B0_04_USDHC1_DATA0 },\
.data1 = { GPIO_SD_B0_05_USDHC1_DATA1 },\
.data2 = { GPIO_SD_B0_00_USDHC1_DATA2 },\
.data3 = { GPIO_SD_B0_01_USDHC1_DATA3 },\
}

View File

@ -2,9 +2,7 @@ MCU_SERIES = MIMXRT1021
MCU_VARIANT = MIMXRT1021DAG5A
MICROPY_FLOAT_IMPL = double
SRC_C += \
hal/flexspi_nor_flash.c \
MICROPY_PY_MACHINE_SDCARD = 1
JLINK_PATH ?= /media/RT1020-EVK/
JLINK_COMMANDER_SCRIPT = $(BUILD)/script.jlink
@ -16,6 +14,8 @@ else
JLINK_CONNECTION_SETTINGS =
endif
SRC_C += \
hal/flexspi_nor_flash.c
deploy_jlink: $(BUILD)/firmware.hex
$(ECHO) "ExitOnError 1" > $(JLINK_COMMANDER_SCRIPT)

View File

@ -54,3 +54,15 @@
{ IOMUXC_GPIO_AD_B1_00_LPI2C1_SCL }, { IOMUXC_GPIO_AD_B1_01_LPI2C1_SDA }, \
{ 0 }, { 0 }, \
{ IOMUXC_GPIO_AD_B1_07_LPI2C3_SCL }, { IOMUXC_GPIO_AD_B1_06_LPI2C3_SDA },
#define USDHC_DUMMY_PIN NULL, 0
#define MICROPY_USDHC1 \
{ \
.cmd = {GPIO_SD_B0_00_USDHC1_CMD}, \
.clk = { GPIO_SD_B0_01_USDHC1_CLK }, \
.cd_b = { GPIO_B1_12_USDHC1_CD_B },\
.data0 = { GPIO_SD_B0_02_USDHC1_DATA0 },\
.data1 = { GPIO_SD_B0_03_USDHC1_DATA1 },\
.data2 = { GPIO_SD_B0_04_USDHC1_DATA2 },\
.data3 = { GPIO_SD_B0_05_USDHC1_DATA3 },\
}

View File

@ -2,11 +2,12 @@ MCU_SERIES = MIMXRT1052
MCU_VARIANT = MIMXRT1052DVL6B
MICROPY_FLOAT_IMPL = double
SRC_C += \
hal/flexspi_nor_flash.c \
MICROPY_PY_MACHINE_SDCARD = 1
JLINK_PATH ?= /media/RT1050-EVK/
deploy: $(BUILD)/firmware.bin
cp $< $(JLINK_PATH)
SRC_C += \
hal/flexspi_nor_flash.c

View File

@ -56,7 +56,6 @@
{ IOMUXC_GPIO_AD_B1_07_LPI2C3_SCL }, { IOMUXC_GPIO_AD_B1_06_LPI2C3_SDA },
#define USDHC_DUMMY_PIN NULL , 0
#define MICROPY_USDHC1 \
{ \
.cmd = {GPIO_SD_B0_00_USDHC1_CMD}, \

View File

@ -2,11 +2,12 @@ MCU_SERIES = MIMXRT1052
MCU_VARIANT = MIMXRT1052DVL6B
MICROPY_FLOAT_IMPL = double
SRC_C += \
hal/flexspi_hyper_flash.c \
MICROPY_PY_MACHINE_SDCARD = 1
JLINK_PATH ?= /media/RT1050-EVKB/
SRC_C += \
hal/flexspi_hyper_flash.c
deploy: $(BUILD)/firmware.bin
cp $< $(JLINK_PATH)

View File

@ -54,3 +54,15 @@
{ IOMUXC_GPIO_AD_B1_00_LPI2C1_SCL }, { IOMUXC_GPIO_AD_B1_01_LPI2C1_SDA }, \
{ 0 }, { 0 }, \
{ IOMUXC_GPIO_AD_B1_07_LPI2C3_SCL }, { IOMUXC_GPIO_AD_B1_06_LPI2C3_SDA },
#define USDHC_DUMMY_PIN NULL, 0
#define MICROPY_USDHC1 \
{ \
.cmd = {GPIO_SD_B0_00_USDHC1_CMD}, \
.clk = { GPIO_SD_B0_01_USDHC1_CLK }, \
.cd_b = { GPIO_B1_12_USDHC1_CD_B },\
.data0 = { GPIO_SD_B0_02_USDHC1_DATA0 },\
.data1 = { GPIO_SD_B0_03_USDHC1_DATA1 },\
.data2 = { GPIO_SD_B0_04_USDHC1_DATA2 },\
.data3 = { GPIO_SD_B0_05_USDHC1_DATA3 },\
}

View File

@ -2,9 +2,7 @@ MCU_SERIES = MIMXRT1062
MCU_VARIANT = MIMXRT1062DVJ6A
MICROPY_FLOAT_IMPL = double
SRC_C += \
hal/flexspi_hyper_flash.c \
MICROPY_PY_MACHINE_SDCARD = 1
JLINK_PATH ?= /media/RT1060-EVK/
JLINK_COMMANDER_SCRIPT = $(BUILD)/script.jlink
@ -16,6 +14,8 @@ else
JLINK_CONNECTION_SETTINGS = -USB
endif
SRC_C += \
hal/flexspi_hyper_flash.c
deploy_jlink: $(BUILD)/firmware.hex
$(Q)$(TOUCH) $(JLINK_COMMANDER_SCRIPT)

View File

@ -52,3 +52,15 @@
{ IOMUXC_GPIO_AD_B1_00_LPI2C1_SCL }, { IOMUXC_GPIO_AD_B1_01_LPI2C1_SDA }, \
{ 0 }, { 0 }, \
{ IOMUXC_GPIO_AD_B1_07_LPI2C3_SCL }, { IOMUXC_GPIO_AD_B1_06_LPI2C3_SDA },
#define USDHC_DUMMY_PIN NULL, 0
#define MICROPY_USDHC1 \
{ \
.cmd = {GPIO_SD_B0_00_USDHC1_CMD}, \
.clk = { GPIO_SD_B0_01_USDHC1_CLK }, \
.cd_b = { GPIO_B1_12_USDHC1_CD_B },\
.data0 = { GPIO_SD_B0_02_USDHC1_DATA0 },\
.data1 = { GPIO_SD_B0_03_USDHC1_DATA1 },\
.data2 = { GPIO_SD_B0_04_USDHC1_DATA2 },\
.data3 = { GPIO_SD_B0_05_USDHC1_DATA3 },\
}

View File

@ -2,9 +2,7 @@ MCU_SERIES = MIMXRT1064
MCU_VARIANT = MIMXRT1064DVL6A
MICROPY_FLOAT_IMPL = double
SRC_C += \
hal/flexspi_hyper_flash.c \
MICROPY_PY_MACHINE_SDCARD = 1
JLINK_PATH ?= /media/RT1064-EVK/
@ -12,3 +10,6 @@ CFLAGS += -DBOARD_FLASH_SIZE=0x400000
deploy: $(BUILD)/firmware.bin
cp $< $(JLINK_PATH)
SRC_C += \
hal/flexspi_hyper_flash.c

View File

@ -57,3 +57,15 @@
{ 0 }, { 0 }, \
{ IOMUXC_GPIO_AD_B1_07_LPI2C3_SCL }, { IOMUXC_GPIO_AD_B1_06_LPI2C3_SDA }, \
{ IOMUXC_GPIO_AD_B0_12_LPI2C4_SCL }, { IOMUXC_GPIO_AD_B0_13_LPI2C4_SDA },
#define USDHC_DUMMY_PIN NULL, 0
#define MICROPY_USDHC1 \
{ \
.cmd = {GPIO_SD_B0_00_USDHC1_CMD}, \
.clk = { GPIO_SD_B0_01_USDHC1_CLK }, \
.cd_b = { USDHC_DUMMY_PIN },\
.data0 = { GPIO_SD_B0_02_USDHC1_DATA0 },\
.data1 = { GPIO_SD_B0_03_USDHC1_DATA1 },\
.data2 = { GPIO_SD_B0_04_USDHC1_DATA2 },\
.data3 = { GPIO_SD_B0_05_USDHC1_DATA3 },\
}

View File

@ -2,9 +2,10 @@ MCU_SERIES = MIMXRT1062
MCU_VARIANT = MIMXRT1062DVJ6A
MICROPY_FLOAT_IMPL = double
SRC_C += \
hal/flexspi_nor_flash.c \
MICROPY_PY_MACHINE_SDCARD = 1
deploy: $(BUILD)/firmware.hex
teensy_loader_cli --mcu=imxrt1062 -v -w $<
SRC_C += \
hal/flexspi_nor_flash.c

View File

@ -32,12 +32,12 @@ D30,GPIO_EMC_37
D31,GPIO_EMC_36
D32,GPIO_B0_12
D33,GPIO_EMC_07
DAT1,GPIO_AD_B0_03
DAT0,GPIO_AD_B0_02
CLK,GPIO_AD_B0_01
CMD,GPIO_ASD_B0_00
DAT3,GPIO_SD_B0_05
CMD,GPIO_SD_B0_00
CLK,GPIO_SD_B0_01
DAT0,GPIO_SD_B0_02
DAT1,GPIO_SD_B0_03
DAT2,GPIO_SD_B0_04
DAT3,GPIO_SD_B0_05
A0,GPIO_AD_B1_02
A1,GPIO_AD_B1_03
A2,GPIO_AD_B1_07

1 D0 GPIO_AD_B0_03
32 D31 GPIO_EMC_36
33 D32 GPIO_B0_12
34 D33 GPIO_EMC_07
35 DAT1 CMD GPIO_AD_B0_03 GPIO_SD_B0_00
36 DAT0 CLK GPIO_AD_B0_02 GPIO_SD_B0_01
37 CLK DAT0 GPIO_AD_B0_01 GPIO_SD_B0_02
38 CMD DAT1 GPIO_ASD_B0_00 GPIO_SD_B0_03
DAT3 GPIO_SD_B0_05
39 DAT2 GPIO_SD_B0_04
40 DAT3 GPIO_SD_B0_05
41 A0 GPIO_AD_B1_02
42 A1 GPIO_AD_B1_03
43 A2 GPIO_AD_B1_07

View File

@ -57,3 +57,15 @@
{ 0 }, { 0 }, \
{ IOMUXC_GPIO_AD_B1_07_LPI2C3_SCL }, { IOMUXC_GPIO_AD_B1_06_LPI2C3_SDA }, \
{ IOMUXC_GPIO_AD_B0_12_LPI2C4_SCL }, { IOMUXC_GPIO_AD_B0_13_LPI2C4_SDA },
#define USDHC_DUMMY_PIN NULL, 0
#define MICROPY_USDHC1 \
{ \
.cmd = {GPIO_SD_B0_00_USDHC1_CMD}, \
.clk = { GPIO_SD_B0_01_USDHC1_CLK }, \
.cd_b = { USDHC_DUMMY_PIN },\
.data0 = { GPIO_SD_B0_02_USDHC1_DATA0 },\
.data1 = { GPIO_SD_B0_03_USDHC1_DATA1 },\
.data2 = { GPIO_SD_B0_04_USDHC1_DATA2 },\
.data3 = { GPIO_SD_B0_05_USDHC1_DATA3 },\
}

View File

@ -2,9 +2,10 @@ MCU_SERIES = MIMXRT1062
MCU_VARIANT = MIMXRT1062DVJ6A
MICROPY_FLOAT_IMPL = double
SRC_C += \
hal/flexspi_nor_flash.c \
MICROPY_PY_MACHINE_SDCARD = 1
deploy: $(BUILD)/firmware.hex
teensy_loader_cli --mcu=imxrt1062 -v -w $<
SRC_C += \
hal/flexspi_nor_flash.c

View File

@ -8,11 +8,22 @@ import sys
import csv
import re
SUPPORTED_AFS = {"GPIO"}
SUPPORTED_AFS = {"GPIO", "USDHC"}
MAX_AF = 10 # AF0 .. AF9
ADC_COL = 11
regexes = [
r"IOMUXC_(?P<pin>GPIO_SD_B\d_\d\d)_(?P<function>\w+) (?P<muxRegister>\w+), (?P<muxMode>\w+), (?P<inputRegister>\w+), (?P<inputDaisy>\w+), (?P<configRegister>\w+)",
r"IOMUXC_(?P<pin>GPIO_AD_B\d_\d\d)_(?P<function>\w+) (?P<muxRegister>\w+), (?P<muxMode>\w+), (?P<inputRegister>\w+), (?P<inputDaisy>\w+), (?P<configRegister>\w+)",
r"IOMUXC_(?P<pin>GPIO_EMC_\d\d)_(?P<function>\w+) (?P<muxRegister>\w+), (?P<muxMode>\w+), (?P<inputRegister>\w+), (?P<inputDaisy>\w+), (?P<configRegister>\w+)",
r"IOMUXC_(?P<pin>GPIO_B\d_\d\d)_(?P<function>\w+) (?P<muxRegister>\w+), (?P<muxMode>\w+), (?P<inputRegister>\w+), (?P<inputDaisy>\w+), (?P<configRegister>\w+)",
r"IOMUXC_(?P<pin>GPIO_\d\d)_(?P<function>\w+) (?P<muxRegister>\w+), (?P<muxMode>\w+), (?P<inputRegister>\w+), (?P<inputDaisy>\w+), (?P<configRegister>\w+)",
r"IOMUXC_(?P<pin>GPIO_AD_\d\d)_(?P<function>\w+) (?P<muxRegister>\w+), (?P<muxMode>\w+), (?P<inputRegister>\w+), (?P<inputDaisy>\w+), (?P<configRegister>\w+)",
r"IOMUXC_(?P<pin>GPIO_SD_\d\d)_(?P<function>\w+) (?P<muxRegister>\w+), (?P<muxMode>\w+), (?P<inputRegister>\w+), (?P<inputDaisy>\w+), (?P<configRegister>\w+)",
]
def parse_pad(pad_str):
"""Parses a string and returns a (port, gpio_bit) tuple."""
if len(pad_str) < 4:
@ -127,16 +138,18 @@ class AdcFunction(object):
class AlternateFunction(object):
"""Holds the information associated with a pins alternate function."""
def __init__(self, idx, af_str):
def __init__(self, idx, input_reg, input_daisy, af_str):
self.idx = idx
self.af_str = af_str
self.input_reg = input_reg
self.input_daisy = input_daisy
self.instance = self.af_str.split("_")[0]
def print(self):
"""Prints the C representation of this AF."""
print(
" PIN_AF({0}, PIN_AF_MODE_ALT{1}, {2}, {3}),".format(
self.af_str, self.idx, self.instance, "0x10B0U"
" PIN_AF({0}, PIN_AF_MODE_ALT{1}, {2}, {3}, {4}, {5}),".format(
self.af_str, self.idx, self.input_daisy, self.instance, self.input_reg, "0x10B0U"
)
)
@ -171,8 +184,26 @@ class Pins(object):
if pin and row[0]: # Only add board pins that have a name
self.board_pins.append(NamedPin(row[0], pin.pad, pin.idx))
def parse_af_file(self, filename, pad_col, af_start_col):
def parse_af_file(self, filename, iomux_filename, pad_col, af_start_col):
af_end_col = af_start_col + MAX_AF
iomux_pin_config = dict()
with open(iomux_filename, "r") as ipt:
input_str = ipt.read()
for regex in regexes:
matches = re.finditer(regex, input_str, re.MULTILINE)
for match in matches:
if match.group("pin") not in iomux_pin_config:
iomux_pin_config[match.group("pin")] = {
int((match.groupdict()["muxMode"].strip("U")), 16): match.groupdict()
}
else:
iomux_pin_config[match.group("pin")][
int((match.groupdict()["muxMode"].strip("U")), 16)
] = match.groupdict()
with open(filename, "r") as csvfile:
rows = csv.reader(csvfile)
header = next(rows)
@ -187,7 +218,16 @@ class Pins(object):
af_idx = 0
for af_idx, af in enumerate(row[af_start_col:af_end_col]):
if af and af_supported(af):
pin.add_af(AlternateFunction(af_idx, af))
pin.add_af(
AlternateFunction(
af_idx,
iomux_pin_config[pin.name][af_idx]["inputRegister"].strip("U"),
int(
iomux_pin_config[pin.name][af_idx]["inputDaisy"].strip("U"), 16
),
af,
)
)
pin.parse_adc(row[ADC_COL])
@ -235,6 +275,33 @@ class Pins(object):
hdr_file.write("extern const mp_obj_dict_t machine_pin_cpu_pins_locals_dict;\n")
hdr_file.write("extern const mp_obj_dict_t machine_pin_board_pins_locals_dict;\n")
hdr_file.write("\n// Defines\n")
usdhc_instance_factory(self.cpu_pins, hdr_file)
def usdhc_instance_factory(pins, output_file):
usdhc_pins = filter(lambda p: any([af for af in p.alt_fn if "USDHC" in af.af_str]), pins)
usdhc_instances = dict()
for pin in usdhc_pins:
for idx, alt_fn in enumerate(pin.alt_fn):
if "USDHC" in alt_fn.instance:
format_string = "#define {0}_{1} &pin_{0}, {2}"
if alt_fn.instance not in usdhc_instances:
usdhc_instances[alt_fn.instance] = [
format_string.format(pin.name, alt_fn.af_str, idx)
]
else:
usdhc_instances[alt_fn.instance].append(
format_string.format(pin.name, alt_fn.af_str, idx)
)
for k, v in usdhc_instances.items():
output_file.write(f"// {k}\n")
output_file.write(f"#define {k}_AVAIL (1)\n")
for i in v:
output_file.write(i + "\n")
def main():
parser = argparse.ArgumentParser(
@ -249,6 +316,13 @@ def main():
help="Specifies the alternate function file for the chip",
default="mimxrt1021_af.csv",
)
parser.add_argument(
"-i",
"--iomux",
dest="iomux_filename",
help="Specifies the fsl_iomux.h file for the chip",
default="fsl_iomuxc.h",
)
parser.add_argument(
"-b",
"--board",
@ -279,7 +353,7 @@ def main():
if args.af_filename:
print("// --af {:s}".format(args.af_filename))
pins.parse_af_file(args.af_filename, 0, 1)
pins.parse_af_file(args.af_filename, args.iomux_filename, 0, 1)
if args.board_filename:
print("// --board {:s}".format(args.board_filename))

View File

@ -4,12 +4,14 @@
#include "py/mphal.h"
#include "pin.h"
#define PIN_AF(_name, _af_mode, _instance, _pad_config) \
#define PIN_AF(_name, _af_mode, _input_daisy, _instance, _input_register, _pad_config) \
{ \
.base = { &machine_pin_af_type }, \
.name = MP_QSTR_##_name, \
.af_mode = (uint32_t)(_af_mode), \
.input_daisy = (uint8_t)(_input_daisy), \
.instance = (void *)(_instance), \
.input_register = (uint32_t)(_input_register), \
.pad_config = (uint32_t)(_pad_config), \
} \
@ -32,3 +34,4 @@
.af_list = (_af_list), \
.adc_list = (_adc_list), \
} \

39
ports/mimxrt/fatfs_port.c Normal file
View File

@ -0,0 +1,39 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2013, 2014 Damien P. George
* Copyright (c) 2021 Robert Hammelrath
*
* 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 "lib/oofatfs/ff.h"
#include "fsl_snvs_lp.h"
MP_WEAK DWORD get_fattime(void) {
snvs_lp_srtc_datetime_t srtcDate;
SNVS_LP_SRTC_GetDatetime(SNVS, &srtcDate);
return ((srtcDate.year - 1980) << 25) | (srtcDate.month << 21) | (srtcDate.day << 16) |
(srtcDate.hour << 11) | ((srtcDate.minute << 5) | (srtcDate.second / 2));
}

View File

@ -0,0 +1,222 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Philipp Ebensberger
*
* 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.
*/
#if MICROPY_PY_MACHINE_SDCARD
#include "py/runtime.h"
#include "py/mperrno.h"
#include "extmod/vfs.h"
#include "ticks.h"
#include "fsl_cache.h"
#include "sdcard.h"
enum { SDCARD_INIT_ARG_ID };
STATIC const mp_arg_t sdcard_init_allowed_args[] = {
[SDCARD_INIT_ARG_ID] = { MP_QSTR_id, MP_ARG_INT, {.u_int = 1} },
};
STATIC void machine_sdcard_init_helper(mimxrt_sdcard_obj_t *self) {
sdcard_init(self, 198000000UL); // Initialize SDCard Host with 198MHz base clock
sdcard_init_pins(self);
ticks_delay_us64(2ULL * 1000ULL); // Wait 2ms to allow USDHC signals to settle/debounce
}
STATIC mp_obj_t sdcard_obj_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
mp_map_t kw_args;
mp_map_init_fixed_table(&kw_args, n_kw, all_args + n_args);
// Parse args
mp_arg_val_t args[MP_ARRAY_SIZE(sdcard_init_allowed_args)];
mp_arg_parse_all(n_args, all_args, &kw_args, MP_ARRAY_SIZE(sdcard_init_allowed_args), sdcard_init_allowed_args, args);
// Extract arguments
mp_int_t sdcard_id = args[SDCARD_INIT_ARG_ID].u_int;
if (!(1 <= sdcard_id && sdcard_id <= MP_ARRAY_SIZE(mimxrt_sdcard_objs))) {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "SDCard(%d) doesn't exist", sdcard_id));
}
mimxrt_sdcard_obj_t *self = &mimxrt_sdcard_objs[(sdcard_id - 1)];
// Initialize SDCard Host
if (!sdcard_state_initialized(self)) {
machine_sdcard_init_helper(self);
}
return MP_OBJ_FROM_PTR(self);
}
// init()
STATIC mp_obj_t machine_sdcard_init(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
mimxrt_sdcard_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
if (!sdcard_state_initialized(self)) {
machine_sdcard_init_helper(self);
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_sdcard_init_obj, 1, machine_sdcard_init);
// deinit()
STATIC mp_obj_t machine_sdcard_deinit(mp_obj_t self_in) {
mimxrt_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in);
sdcard_deinit(self);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_sdcard_deinit_obj, machine_sdcard_deinit);
// readblocks(block_num, buf)
STATIC mp_obj_t machine_sdcard_readblocks(mp_obj_t self_in, mp_obj_t block_num, mp_obj_t buf) {
mp_buffer_info_t bufinfo;
mimxrt_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in);
mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_WRITE);
if (sdcard_read(self, bufinfo.buf, mp_obj_get_int(block_num), bufinfo.len / SDCARD_DEFAULT_BLOCK_SIZE)) {
return MP_OBJ_NEW_SMALL_INT(0);
} else {
return MP_OBJ_NEW_SMALL_INT(-MP_EIO);
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(machine_sdcard_readblocks_obj, machine_sdcard_readblocks);
// present()
STATIC mp_obj_t machine_sdcard_present(mp_obj_t self_in) {
mimxrt_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in);
return mp_obj_new_bool(sdcard_detect(self));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_sdcard_present_obj, machine_sdcard_present);
STATIC mp_obj_t machine_sdcard_info(mp_obj_t self_in) {
mimxrt_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in);
if (sdcard_detect(self) && sdcard_state_initialized(self)) {
uint32_t log_block_nbr = self->block_count;
uint32_t log_block_size = self->block_len;
mp_obj_t tuple[2] = {
mp_obj_new_int_from_ull((uint64_t)log_block_nbr * (uint64_t)log_block_size),
mp_obj_new_int_from_uint(log_block_size),
};
return mp_obj_new_tuple(2, tuple);
} else {
return mp_const_none;
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_sdcard_info_obj, machine_sdcard_info);
// writeblocks(block_num, buf)
STATIC mp_obj_t machine_sdcard_writeblocks(mp_obj_t self_in, mp_obj_t block_num, mp_obj_t buf) {
mp_buffer_info_t bufinfo;
mimxrt_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in);
mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_WRITE);
if (sdcard_write(self, bufinfo.buf, mp_obj_get_int(block_num), bufinfo.len / SDCARD_DEFAULT_BLOCK_SIZE)) {
return MP_OBJ_NEW_SMALL_INT(0);
} else {
return MP_OBJ_NEW_SMALL_INT(-MP_EIO);
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(machine_sdcard_writeblocks_obj, machine_sdcard_writeblocks);
// ioctl(op, arg)
STATIC mp_obj_t machine_sdcard_ioctl(mp_obj_t self_in, mp_obj_t cmd_in, mp_obj_t arg_in) {
mimxrt_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in);
mp_int_t cmd = mp_obj_get_int(cmd_in);
switch (cmd) {
case MP_BLOCKDEV_IOCTL_INIT: {
if (sdcard_detect(self)) {
if (sdcard_power_on(self)) {
return MP_OBJ_NEW_SMALL_INT(0);
} else {
sdcard_power_off(self);
return MP_OBJ_NEW_SMALL_INT(-MP_EIO); // Initialization failed
}
} else {
return MP_OBJ_NEW_SMALL_INT(-MP_EIO); // Initialization failed
}
}
case MP_BLOCKDEV_IOCTL_DEINIT: {
if (sdcard_power_off(self)) {
return MP_OBJ_NEW_SMALL_INT(0);
} else {
return MP_OBJ_NEW_SMALL_INT(-MP_EIO); // Deinitialization failed
}
}
case MP_BLOCKDEV_IOCTL_SYNC: {
return MP_OBJ_NEW_SMALL_INT(0);
}
case MP_BLOCKDEV_IOCTL_BLOCK_COUNT: {
if (sdcard_state_initialized(self)) {
return MP_OBJ_NEW_SMALL_INT(self->block_count);
} else {
return MP_OBJ_NEW_SMALL_INT(-MP_EIO); // Card not initialized
}
}
case MP_BLOCKDEV_IOCTL_BLOCK_SIZE: {
if (sdcard_state_initialized(self)) {
return MP_OBJ_NEW_SMALL_INT(self->block_len);
} else {
return MP_OBJ_NEW_SMALL_INT(-MP_EIO); // Card not initialized
}
}
default: // unknown command
{
return mp_const_none;
}
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(machine_sdcard_ioctl_obj, machine_sdcard_ioctl);
STATIC const mp_rom_map_elem_t sdcard_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_sdcard_init_obj) },
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_sdcard_deinit_obj) },
{ MP_ROM_QSTR(MP_QSTR_present), MP_ROM_PTR(&machine_sdcard_present_obj) },
{ MP_ROM_QSTR(MP_QSTR_info), MP_ROM_PTR(&machine_sdcard_info_obj) },
// block device protocol
{ MP_ROM_QSTR(MP_QSTR_readblocks), MP_ROM_PTR(&machine_sdcard_readblocks_obj) },
{ MP_ROM_QSTR(MP_QSTR_writeblocks), MP_ROM_PTR(&machine_sdcard_writeblocks_obj) },
{ MP_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&machine_sdcard_ioctl_obj) },
};
STATIC MP_DEFINE_CONST_DICT(sdcard_locals_dict, sdcard_locals_dict_table);
const mp_obj_type_t machine_sdcard_type = {
{ &mp_type_type },
.name = MP_QSTR_SDCard,
.make_new = sdcard_obj_make_new,
.locals_dict = (mp_obj_dict_t *)&sdcard_locals_dict,
};
void machine_sdcard_init0(void) {
return;
}
#endif // MICROPY_PY_MACHINE_SDCARD

View File

@ -82,6 +82,9 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_ADC), MP_ROM_PTR(&machine_adc_type) },
{ MP_ROM_QSTR(MP_QSTR_Timer), MP_ROM_PTR(&machine_timer_type) },
{ MP_ROM_QSTR(MP_QSTR_RTC), MP_ROM_PTR(&machine_rtc_type) },
#if MICROPY_PY_MACHINE_SDCARD
{ MP_ROM_QSTR(MP_QSTR_SDCard), MP_ROM_PTR(&machine_sdcard_type) },
#endif
{ MP_ROM_QSTR(MP_QSTR_Signal), MP_ROM_PTR(&machine_signal_type) },
{ MP_ROM_QSTR(MP_QSTR_SoftI2C), MP_ROM_PTR(&mp_machine_soft_i2c_type) },
{ MP_ROM_QSTR(MP_QSTR_SoftSPI), MP_ROM_PTR(&mp_machine_soft_spi_type) },

View File

@ -35,9 +35,11 @@ extern const mp_obj_type_t machine_rtc_type;
extern const mp_obj_type_t machine_i2c_type;
extern const mp_obj_type_t machine_spi_type;
extern const mp_obj_type_t machine_uart_type;
extern const mp_obj_type_t machine_sdcard_type;
void machine_adc_init(void);
void machine_pin_irq_deinit(void);
void machine_timer_init_PIT(void);
void machine_sdcard_init0(void);
#endif // MICROPY_INCLUDED_MIMXRT_MODMACHINE_H

View File

@ -3,13 +3,32 @@
# Note: the flash requires the programming size to be aligned to 256 bytes.
import os
import sys
import mimxrt
from machine import Pin
bdev = mimxrt.Flash()
try:
vfs = os.VfsLfs2(bdev, progsize=256)
except:
os.VfsLfs2.mkfs(bdev, progsize=256)
vfs = os.VfsLfs2(bdev, progsize=256)
os.mount(vfs, "/")
os.mount(vfs, "/flash")
os.chdir("/flash")
sys.path.append("/flash")
# do not mount the SD card if SKIPSD exists.
try:
os.stat("SKIPSD")
except:
try:
from machine import SDCard
sdcard = SDCard(1)
fat = os.VfsFat(sdcard)
os.mount(fat, "/sdcard")
os.chdir("/sdcard")
sys.path.append("/sdcard")
except:
pass # Fail silently

View File

@ -31,6 +31,7 @@
#include "py/objstr.h"
#include "py/runtime.h"
#include "extmod/vfs.h"
#include "extmod/vfs_fat.h"
#include "extmod/vfs_lfs.h"
#include "genhdr/mpversion.h"
#include "fsl_trng.h"

View File

@ -132,6 +132,12 @@ uint32_t trng_random_u32(void);
#define MICROPY_PY_FRAMEBUF (1)
#define MICROPY_PY_ONEWIRE (1)
// fatfs configuration used in ffconf.h
#define MICROPY_FATFS_ENABLE_LFN (1)
#define MICROPY_FATFS_RPATH (2)
#define MICROPY_FATFS_MAX_SS (4096)
#define MICROPY_FATFS_LFN_CODE_PAGE 437 /* 1=SFN/ANSI 437=LFN/U.S.(OEM) */
// Use VfsLfs2's types for fileio/textio
#define mp_type_fileio mp_type_vfs_lfs2_fileio
#define mp_type_textio mp_type_vfs_lfs2_textio

View File

@ -58,7 +58,8 @@ enum {
};
enum {
PIN_AF_MODE_ALT1 = 1,
PIN_AF_MODE_ALT0 = 0,
PIN_AF_MODE_ALT1,
PIN_AF_MODE_ALT2,
PIN_AF_MODE_ALT3,
PIN_AF_MODE_ALT4,
@ -97,7 +98,9 @@ typedef struct {
mp_obj_base_t base;
qstr name; // port name
uint8_t af_mode; // alternate function
uint8_t input_daisy;
void *instance; // pointer to peripheral instance for alternate function
uint32_t input_register;
uint32_t pad_config; // pad configuration for alternate function
} machine_pin_af_obj_t;

1023
ports/mimxrt/sdcard.c Normal file

File diff suppressed because it is too large Load Diff

111
ports/mimxrt/sdcard.h Normal file
View File

@ -0,0 +1,111 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Philipp Ebensberger
*
* 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_MIMXRT_SDCARD_H
#define MICROPY_INCLUDED_MIMXRT_SDCARD_H
#include "modmachine.h"
#include "pin.h"
#include "fsl_usdhc.h"
// ---
// SD Card public defines
// ---
#define SDCARD_DEFAULT_BLOCK_SIZE (512U)
#define SDCARD_CLOCK_400KHZ (400000U)
#define SDCARD_CLOCK_25MHZ (25000000U)
#define SDCARD_CLOCK_50MHZ (50000000U)
typedef struct _mimxrt_sdcard_pin_t {
const machine_pin_obj_t *pin;
uint8_t af_idx;
} mimxrt_sdcard_pin_t;
typedef struct _mimxrt_sdcard_obj_pins_t {
mimxrt_sdcard_pin_t cmd;
mimxrt_sdcard_pin_t clk;
mimxrt_sdcard_pin_t cd_b;
mimxrt_sdcard_pin_t data0;
mimxrt_sdcard_pin_t data1;
mimxrt_sdcard_pin_t data2;
mimxrt_sdcard_pin_t data3;
} mimxrt_sdcard_obj_pins_t;
typedef volatile struct _mimxrt_sdcard_status_obj_t {
bool initialized;
bool inserted;
} mimxrt_sdcard_status_obj_t;
typedef struct _mimxrt_sdcard_obj_t {
mp_obj_base_t base;
USDHC_Type *usdhc_inst;
usdhc_handle_t handle;
mimxrt_sdcard_status_obj_t *state;
uint16_t block_len;
uint32_t base_clk;
uint32_t bus_clk;
uint32_t rca;
uint32_t block_count;
uint32_t status;
uint32_t oper_cond;
const mimxrt_sdcard_obj_pins_t *pins;
} mimxrt_sdcard_obj_t;
// ---
// SD Card object instances
// ---
#if MICROPY_PY_MACHINE_SDCARD && (defined MICROPY_USDHC1 || defined MICROPY_USDHC2)
enum {
#if defined MICROPY_USDHC1 && USDHC1_AVAIL
SDCARD_OBJ_USDHC1_IDX,
#endif
#if defined MICROPY_USDHC2 && USDHC2_AVAIL
SDCARD_OBJ_USDHC2_IDX,
#endif
SDCARD_OBJ_USDHC_N
};
#endif
extern mimxrt_sdcard_obj_t mimxrt_sdcard_objs[SDCARD_OBJ_USDHC_N];
// ---
// SD Card functions
// ---
void sdcard_init(mimxrt_sdcard_obj_t *card, uint32_t base_clk);
void sdcard_deinit(mimxrt_sdcard_obj_t *card);
void sdcard_init_pins(mimxrt_sdcard_obj_t *card);
bool sdcard_read(mimxrt_sdcard_obj_t *card, uint8_t *buffer, uint32_t block_num, uint32_t block_count);
bool sdcard_write(mimxrt_sdcard_obj_t *card, uint8_t *buffer, uint32_t block_num, uint32_t block_count);
bool sdcard_set_active(mimxrt_sdcard_obj_t *card);
bool sdcard_volt_validation(mimxrt_sdcard_obj_t *card);
bool sdcard_power_on(mimxrt_sdcard_obj_t *self);
bool sdcard_power_off(mimxrt_sdcard_obj_t *self);
bool sdcard_detect(mimxrt_sdcard_obj_t *self);
static inline bool sdcard_state_initialized(mimxrt_sdcard_obj_t *card) {
return card->state->initialized;
}
#endif // MICROPY_INCLUDED_MIMXRT_SDCARD_H