lift_indicator_suite/bsp/generated/sdmmc_config.c

209 lines
9.6 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* sdmmc_config.c — board-level реализация SDMMC для MIMXRT1052CVJ5B.
*/
#define SD_ENABLED /* нужен для fsl_sd.h, до включений */
#include "sdmmc_config.h"
#include "fsl_iomuxc.h"
/* ---------------------------------------------------------------------------
* Статические объекты хоста (не экспортируются)
* ------------------------------------------------------------------------- */
/* DMA-дескрипторы: некэшируемая секция, выравнивание по требованию USDHC. */
AT_NONCACHEABLE_SECTION_ALIGN(
static uint32_t s_dma_buf[BOARD_SDMMC_HOST_DMA_DESCRIPTOR_BUFFER_SIZE],
SDMMCHOST_DMA_DESCRIPTOR_BUFFER_ALIGN_SIZE);
static sdmmchost_t s_host;
static sd_detect_card_t s_cd;
static sd_io_voltage_t s_io_voltage = {
.type = BOARD_SDMMC_SD_IO_VOLTAGE_TYPE,
.func = NULL, /* управление через регистры USDHC, не через внешний LDO */
};
/* Debug markers for runtime verification in debugger. */
volatile uint32_t g_sdmmc_dbg_dma_buf_addr = 0U;
volatile uint32_t g_sdmmc_dbg_usdhc1_src_clock_hz = 0U;
/*
* Детект карты через USDHC PRES_STATE.CINST — ЕДИНЫЙ механизм и для нашего
* гейта bsp_sd_is_inserted() (bsp/sd/src/sd.c), и для внутреннего
* SD_PollingCardInsert() SDK (тот зовёт этот callback при kSD_DetectCardByGpioCD).
* Не GPIO_PinRead — исторически детект через GPIO2/28 давал ложный "card
* present" на пустом слоте (Фаза 3, симптом 1; DEBUG_LOG_PHASE3_SD.md, раунд 3).
* Работает, пока пин D13 замаплен на USDHC1_CD_B (см. BOARD_SD_Config ниже:
* прежний remux на GPIO2_IO28 убран, пин остаётся на USDHC1_CD_B постоянно —
* консолидация, item 1). Тактирование USDHC1 включается идемпотентно на случай
* вызова до полного SD_HostInit().
*
* Тот же PRSSTAT-бит читает и штатный host-CD путь SDK
* (SDMMCHOST_CardDetectStatus), но kSD_DetectCardByHostCD дополнительно взводит
* USDHC card-detect ПРЕРЫВАНИЯ — не нужны загрузчику (лишний источник IRQ перед
* прыжком), поэтому оставляем polling через callback (kSD_DetectCardByGpioCD).
*/
static bool sd_card_detect_prsstat(void)
{
CLOCK_EnableClock(kCLOCK_Usdhc1);
return (USDHC_GetPresentStatusFlags(BOARD_SDMMC_SD_HOST_BASEADDR) &
(uint32_t) kUSDHC_CardInsertedFlag) != 0U;
}
/* ---------------------------------------------------------------------------
* Внутренние функции
* ------------------------------------------------------------------------- */
/*
* Возвращает частоту источника USDHC1.
*
* BOARD_BootClockRUN() уже настроил SysPll и PFD0 → не трогаем PLL.
* Просто возвращаем известное значение из clock_config.h.
*/
static uint32_t get_usdhc1_src_clock_hz(void)
{
return BOARD_BOOTCLOCKRUN_USDHC1_CLK_ROOT;
}
/*
* Управление питанием карты: GPIO1[19] (SdPwr). Регистрируется как
* usrParam.pwr — SDK дёргает её из SD_SetCardPower().
*/
static void sd_power_control(bool enable)
{
#if BOARD_SDMMC_SD_PWR_ACTIVE_HIGH
GPIO_PinWrite(BOARD_SDMMC_SD_PWR_GPIO_BASE, BOARD_SDMMC_SD_PWR_GPIO_PIN, enable ? 1U : 0U);
#else
GPIO_PinWrite(BOARD_SDMMC_SD_PWR_GPIO_BASE, BOARD_SDMMC_SD_PWR_GPIO_PIN, enable ? 0U : 1U);
#endif
}
/*
* Инициализация GPIO питания карты как выход, начальное состояние — выкл.
* Вызывается однократно из BOARD_SD_Config().
*/
static void sd_power_init(void)
{
const gpio_pin_config_t cfg = {
.direction = kGPIO_DigitalOutput,
#if BOARD_SDMMC_SD_PWR_ACTIVE_HIGH
.outputLogic = 0U, /* питание выключено при старте */
#else
.outputLogic = 1U, /* питание выключено при старте */
#endif
.interruptMode = kGPIO_NoIntmode,
};
GPIO_PinInit(BOARD_SDMMC_SD_PWR_GPIO_BASE, BOARD_SDMMC_SD_PWR_GPIO_PIN, &cfg);
}
/*
* Динамическая настройка пад-конфигурации линий SD в зависимости от частоты.
* Вызывается SDMMC стеком при смене скорости (HS, SDR50, SDR104).
*
* speed/strength подобраны по таблице EVK — для данной платы проверить
* при трассировке > 50 MHz.
*/
static void sd_pin_config(uint32_t freq)
{
uint32_t speed;
uint32_t strength;
if (freq <= 50000000U)
{
speed = 0U;
strength = 7U;
}
else if (freq <= 100000000U)
{
speed = 2U;
strength = 7U;
}
else
{
speed = 3U;
strength = 7U;
}
const uint32_t pad = IOMUXC_SW_PAD_CTL_PAD_SPEED(speed) | IOMUXC_SW_PAD_CTL_PAD_SRE_MASK |
IOMUXC_SW_PAD_CTL_PAD_PKE_MASK | IOMUXC_SW_PAD_CTL_PAD_PUE_MASK |
IOMUXC_SW_PAD_CTL_PAD_HYS_MASK |
IOMUXC_SW_PAD_CTL_PAD_PUS(1) /* 47k pull-up */
| IOMUXC_SW_PAD_CTL_PAD_DSE(strength);
const uint32_t clk_pad = IOMUXC_SW_PAD_CTL_PAD_SPEED(speed) | IOMUXC_SW_PAD_CTL_PAD_SRE_MASK |
IOMUXC_SW_PAD_CTL_PAD_HYS_MASK |
IOMUXC_SW_PAD_CTL_PAD_PUS(0) /* no pull on CLK */
| IOMUXC_SW_PAD_CTL_PAD_DSE(strength);
IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_B0_00_USDHC1_CMD, pad);
IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_B0_01_USDHC1_CLK, clk_pad);
IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_B0_02_USDHC1_DATA0, pad);
IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_B0_03_USDHC1_DATA1, pad);
IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_B0_04_USDHC1_DATA2, pad);
IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_B0_05_USDHC1_DATA3, pad);
/*
* CD (D13) здесь НЕ конфигурируем: пин на USDHC1_CD_B (см. BOARD_SD_Config),
* pad задан в BOARD_InitPins() и на железе даёт корректный CINST. Прежняя
* настройка pad'а GPIO2_IO28 убрана вместе с GPIO-детектом (item 1,
* DEBUG_LOG_PHASE3_SD.md).
*/
}
/* ---------------------------------------------------------------------------
* Публичный API
* ------------------------------------------------------------------------- */
#ifdef SD_ENABLED
void BOARD_SD_Config(void *card, sd_cd_t cd, uint32_t host_irq_priority, void *user_data)
{
assert(card != NULL);
/* --- host --- */
s_host.dmaDesBuffer = s_dma_buf;
s_host.dmaDesBufferWordsNum = BOARD_SDMMC_HOST_DMA_DESCRIPTOR_BUFFER_SIZE;
s_host.enableCacheControl = BOARD_SDMMC_HOST_CACHE_CONTROL;
sd_card_t *sd = (sd_card_t *) card;
sd->host = &s_host;
sd->host->hostController.base = BOARD_SDMMC_SD_HOST_BASEADDR;
sd->host->hostController.sourceClock_Hz = get_usdhc1_src_clock_hz();
g_sdmmc_dbg_dma_buf_addr = (uint32_t)(uintptr_t)s_dma_buf;
g_sdmmc_dbg_usdhc1_src_clock_hz = sd->host->hostController.sourceClock_Hz;
/* --- card detect: USDHC PRES_STATE.CINST через callback (polling, без IRQ) --- */
s_cd.cdDebounce_ms = BOARD_SDMMC_SD_CD_DEBOUNCE_MS;
s_cd.type = BOARD_SDMMC_SD_CD_TYPE; /* kSD_DetectCardByGpioCD → callback ниже */
s_cd.cardDetected = sd_card_detect_prsstat;
s_cd.callback = cd; /* обычно NULL из bsp_sd */
s_cd.userData = user_data;
sd->usrParam.cd = &s_cd;
sd->usrParam.pwr = sd_power_control;
sd->usrParam.ioStrength = sd_pin_config;
sd->usrParam.ioVoltage = &s_io_voltage;
sd->usrParam.maxFreq = BOARD_SDMMC_SD_HOST_SUPPORT_SDR104_FREQ;
/* --- GPIO питания --- */
sd_power_init();
/*
* CD_B (GPIO_B1_12 / physical D13) остаётся на USDHC1_CD_B постоянно —
* единый механизм детекта через PRES_STATE.CINST (sd_card_detect_prsstat
* выше + гейт bsp_sd_is_inserted). Прежней двойной маршрутизации
* (remux на GPIO2_IO28 для GPIO-чтения внутри f_mount) больше нет —
* см. DEBUG_LOG_PHASE3_SD.md, раунд 3 «консолидация детекта» (item 1);
* она убирала латентную хрупкость: после первого bsp_sd_init() пин уходил
* на GPIO2_IO28 и повторный PRSSTAT-скан ослеп бы. Явно переустанавливаем
* альт-функцию (BOARD_InitPins() её тоже ставит — так модуль не зависит от
* порядка инициализации). Pad этого пина оставляем как задал BOARD_InitPins:
* на железе CINST на нём читается корректно (Фаза 3, все сценарии).
*/
IOMUXC_SetPinMux(IOMUXC_GPIO_B1_12_USDHC1_CD_B, 0U);
/* Pad-конфиг линий SD (CMD/CLK/DATA) сразу для ранних CMD (CMD0/CMD8/CMD55/ACMD41). */
sd_pin_config(400000U);
/* --- приоритет прерывания хоста --- */
NVIC_SetPriority(BOARD_SDMMC_SD_HOST_IRQ, host_irq_priority);
}
#endif /* SD_ENABLED */