NXP i.MX7D контроллер SD/MMC

На эволюхе PICO-PI-GL порт SD используется в двух местах: доступ к eMMC флеш-памяти и ВайФай модему.

Приоритет для публикации кода на сайте, отдан микросхемке eMMC.


	@ Отдать ножки флешке
	MOV32 R0, IOMUXC_BASE
	MOV R1, 0 @ Режим ALT0 для uSDHC3
	STR R1, [R0, SW_MUX_CTL_PAD_SD3_CLK] @ SD3 CLK
	STR R1, [R0, SW_MUX_CTL_PAD_SD3_CMD] @ SD3 CMD
	STR R1, [R0, SW_MUX_CTL_PAD_SD3_DATA0] @ SD3 DATA0
	STR R1, [R0, SW_MUX_CTL_PAD_SD3_DATA1] @ SD3 DATA1
	STR R1, [R0, SW_MUX_CTL_PAD_SD3_DATA2] @ SD3 DATA2
	STR R1, [R0, SW_MUX_CTL_PAD_SD3_DATA3] @ SD3 DATA3
	STR R1, [R0, SW_MUX_CTL_PAD_SD3_DATA4] @ SD3 DATA4
	STR R1, [R0, SW_MUX_CTL_PAD_SD3_DATA5] @ SD3 DATA5
	STR R1, [R0, SW_MUX_CTL_PAD_SD3_DATA6] @ SD3 DATA6
	STR R1, [R0, SW_MUX_CTL_PAD_SD3_DATA7] @ SD3 DATA7
	MOV R1, 1 @ Режим ALT1 для SD3_CD_B
	STR R1, [R0, SW_MUX_CTL_PAD_GPIO1_IO14] @ SD3 CD_B

	@ Настроить параметры ножек
	@ Pull Disabled, Hysteresis Enabled, Slow Slew Rate, Drive Strength ~40 ом
	MOV R1, 0 << 5 + 0 << 4 + 1 << 3 + 1 << 2 + 3 << 0
	STR R1, [R0, SW_PAD_CTL_PAD_SD3_CLK] @ SD3 CLK
	STR R1, [R0, SW_PAD_CTL_PAD_SD3_CMD] @ SD3 CMD
	STR R1, [R0, SW_PAD_CTL_PAD_SD3_DATA0] @ SD3 DATA0
	STR R1, [R0, SW_PAD_CTL_PAD_SD3_DATA1] @ SD3 DATA1
	STR R1, [R0, SW_PAD_CTL_PAD_SD3_DATA2] @ SD3 DATA2
	STR R1, [R0, SW_PAD_CTL_PAD_SD3_DATA3] @ SD3 DATA3
	STR R1, [R0, SW_PAD_CTL_PAD_SD3_DATA4] @ SD3 DATA4
	STR R1, [R0, SW_PAD_CTL_PAD_SD3_DATA5] @ SD3 DATA5
	STR R1, [R0, SW_PAD_CTL_PAD_SD3_DATA6] @ SD3 DATA6
	STR R1, [R0, SW_PAD_CTL_PAD_SD3_DATA7] @ SD3 DATA7
	STR R1, [R0, SW_PAD_CTL_PAD_GPIO1_IO14] @ SD3 CD_B

	@ Определить источник тактовых импульсов и настроить делитель
	MOV32 R0, CCM_BASE + TARGET_ROOT88 @ uSDHC3_CLK_ROOT
	MOV32 R1, 1 << ROOT_ENABLE + 1 << MUX + (1-1) << PRE_PODF + (1-1) << POST_PODF
	STR R1, [R0] @ Источник: SYS_PLL_PFD0, оверклокерская частота 392МГц
	@ Частота 392МГц в 2 раза выше допустимой
	@ Это пригодится нам при тестовом разгоне
	@ Хотя частоты модулей лучше не превышать. Сгорит!
	@ И в этом месте верните делитель на 2: (2-1) << PRE_PODF
	@ Что бы получить штатные 196 МГц

	@ Затактировать модуль
	MOV32 R0, CCM_BASE + CCGR110 @ uSDHC3 clock gate
	MOV R1, 0x00003333
	STR R1, [R0]


	@ Базовый адрес модуля
	MOV32 R0, uSDHC3_BASE

	@ Так как загрузчик до вас уже поковырялся в модуле
	@ Выискивая прошивку на флешке
	@ То модуль лучше полностью сбросить и настроить заново
	MOV R1, 1 << SD_RSTA
	STR R1, [R0, SYS_CTRL]
	@ Дождаться завершения сброса
	1:
	LDR R1, [R0, SYS_CTRL]
	TST R1, 1 << SD_RSTA @ Должен стать = 0
	BNE 1b

	@ Установить начальную частоту SDIO
	@ Если входная @196 МГц / 64 / 8 = 382 килогерца
	MOV32 R1, 1 << IPP_RST_N + 14 << DTOCV + 0x20 << SDCLKFS + (8-1) << DVS + 0x0F
	STR R1, [R0, SYS_CTRL]
	@ Дождаться стабилизации частоты
	1:
	LDR R1, [R0, PRES_STATE]
	TST R1, 1 << SDSTB
	BEQ 1b

	@ Настроить DMA
	LDR R1, [R0, MIX_CTRL]
	BIS R1, 1 << DMAEN @ Использовать DMA вместо внутреннего буфера
	BIS R1, 1 << BCEN @ Включить счётчик блоков
	BIS R1, 1 << AC12EN @ CMD12 в конце потока
	BIS R1, 1 << MSBSEL @ Передача более 1 блока
	STR R1, [R0, MIX_CTRL]

	@ Настройки буфера
	LDR R1, [R0, WTMK_LVL]
	MOV32 R1, 8 << 24 + 128 << 16 + 8 << 8 + 128
	STR R1, [R0, WTMK_LVL]

	@ Включить статусы
	@ И сбросить флаги прерываний
	SER R1
	STR R1, [R0, INT_STATUS_EN]
	STR R1, [R0, uSDHC_INT_STATUS]

	@ Отправить 80 клоков в карту
	LDR R1, [R0, SYS_CTRL]
	BIS R1, 1 << INITA
	STR R1, [R0, SYS_CTRL]
	@ Дождаться завершения
	1:
	LDR R1, [R0, SYS_CTRL]
	TST R1, 1 << INITA @ Должен стать = 0
	BNE 1b
	
Вот и всё. И даже не больно.

Далее: с карточкой необходимо произвести определённую работу.
Назначить ей адрес и перевести в режим 8bit DDR.
Что бы всё так быстренько читалось и писалось.

После этого, можно прочитать файл из карточки и посчитать его сумму SHA1.
Это такая простая задача, когда уже всё сделано до вас!
Бери и копируй!

Ищите примеры и коды в файлах чистого проекта.

Там же, вы найдёте код подъёма ВайФай модема.
Который пока что болтается без дела на порту uSDHC2.