Перейти к содержанию
    

Очень долго инициализируется SD-карта.

6 часов назад, MementoMori сказал:
7 часов назад, _4afc_ сказал:

На CMD есть внешняя подтяжка?

Нет. А эта линия наиболее критична? 

Проц IMX6 длина линий до SD карты 7см, выровнены, никаких подтяжек нет, время инита SD2.0 и SDHC менее пол-секунды, клок 25МГц. Инит карт 1.0 8 Мб  (мегабайт - это не опечатка) 1-2сек, хотя в режиме spi- пол-секунды, х.з. почему, но такие карты сейчас только в музее есть, поэтому забил...

3 часа назад, MementoMori сказал:

Как мне кажется, если бы были проблемы с железом, то это отражалось бы на всех этапах работы. Если я не прав - поправьте. 

Так-то да, нужно проверять чтение и запись больших блоков в течении 10 мин. хотя бы. И еще, при ините требуется снижать клок до 100КГц или мегагерца уже не помню, и прочитав регистр конфигурации, можно повышать чатоту...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 час назад, mantech сказал:

хотя в режиме spi- пол-секунды, х.з. почему, но такие карты сейчас только в музее есть, поэтому забил...

А что - современные SD-карты не поддерживают SPI? Как так, ведь спецификация вроде обязывает?...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

 

Итак, схема

FEA9WNkw.png?download=1&name=%D0%A1%D0%B

 

Настройка портов 

4A7EZAVY.png?download=1&name=%D0%A1%D0%B

Только не подумайте, что я настолько окалокубился, что даже не умею вручную настраивать ножки, я картинку из куба выложил для наглядности.

 

Тактирование

 

NeZzFzER.png?download=1&name=%D0%A1%D0%B

 

Трассировка (интуитивно понятно, где TOP, а где BOTTOM)

A3Oc2TfS.png?download=1&name=%D0%A1%D0%B

 

Плата со слотом

cvVfApsg.png?download=1&name=%D0%A1%D0%B

 

 

И вот CallStack до зависания

QUY6LrA4.png?download=1&name=%D0%A1%D0%B

Пройдемся по этому списку

 

static void MX_SDMMC1_SD_Init(void)
{

  /* USER CODE BEGIN SDMMC1_Init 0 */

  /* USER CODE END SDMMC1_Init 0 */

  /* USER CODE BEGIN SDMMC1_Init 1 */

  /* USER CODE END SDMMC1_Init 1 */
  hsd1.Instance = SDMMC1;
  hsd1.Init.ClockEdge = SDMMC_CLOCK_EDGE_RISING;
  hsd1.Init.ClockBypass = SDMMC_CLOCK_BYPASS_DISABLE;
  hsd1.Init.ClockPowerSave = SDMMC_CLOCK_POWER_SAVE_DISABLE;
  hsd1.Init.BusWide = SDMMC_BUS_WIDE_1B;
  hsd1.Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE;
  hsd1.Init.ClockDiv = 0;
	  /* USER CODE BEGIN SDMMC1_Init 2 */
   BSP_SD_Init();	//  ЭТУ ФУНКЦИЮ ПРИВЕДУ НИЖЕ
	
  /* USER CODE END SDMMC1_Init 2 */

}

 

__weak uint8_t BSP_SD_Init(void)
{
  uint8_t sd_state = MSD_OK;
  /* Check if the SD card is plugged in the slot */
  if (BSP_SD_IsDetected() != SD_PRESENT)
  {
    return MSD_ERROR_SD_NOT_PRESENT;
  }
  /* HAL SD initialization */
  sd_state = HAL_SD_Init(&hsd1);
  
  // ПОДВИСАЕТ В ВЫШЕУКАЗАННОЙ ФУНКЦИИ, ВСЕ ЧТО НИЖЕ ВЫПОЛНЯЕТСЯ ПОТОМ
  
  /* Configure SD Bus width (4 bits mode selected) */
  	if (sd_state == MSD_OK)
  {
    /* Enable wide operation */
    if (HAL_SD_ConfigWideBusOperation(&hsd1, SDMMC_BUS_WIDE_4B) != HAL_OK)
    {
      sd_state = MSD_ERROR;
    }
  }

  return sd_state;
}
void HAL_SD_MspInit(SD_HandleTypeDef* hsd)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(hsd->Instance==SDMMC1)
  {
  /* USER CODE BEGIN SDMMC1_MspInit 0 */

  /* USER CODE END SDMMC1_MspInit 0 */
    /* Peripheral clock enable */
    __HAL_RCC_SDMMC1_CLK_ENABLE();

    __HAL_RCC_GPIOC_CLK_ENABLE();
    __HAL_RCC_GPIOD_CLK_ENABLE();
    /**SDMMC1 GPIO Configuration
    PC8     ------> SDMMC1_D0
    PC9     ------> SDMMC1_D1
    PC10     ------> SDMMC1_D2
    PC11     ------> SDMMC1_D3
    PC12     ------> SDMMC1_CK
    PD2     ------> SDMMC1_CMD
    */
    GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF12_SDMMC1;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_12;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF12_SDMMC1;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_2;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF12_SDMMC1;
    HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);

    /* SDMMC1 DMA Init */
    /* SDMMC1_RX Init */
    hdma_sdmmc1_rx.Instance = DMA2_Stream3;
    hdma_sdmmc1_rx.Init.Channel = DMA_CHANNEL_4;
    hdma_sdmmc1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_sdmmc1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_sdmmc1_rx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_sdmmc1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
    hdma_sdmmc1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
    hdma_sdmmc1_rx.Init.Mode = DMA_PFCTRL;
    hdma_sdmmc1_rx.Init.Priority = DMA_PRIORITY_LOW;
    hdma_sdmmc1_rx.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
    hdma_sdmmc1_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
    hdma_sdmmc1_rx.Init.MemBurst = DMA_MBURST_INC4;
    hdma_sdmmc1_rx.Init.PeriphBurst = DMA_PBURST_INC4;
    if (HAL_DMA_Init(&hdma_sdmmc1_rx) != HAL_OK)
    {
      Error_Handler();
    }

    __HAL_LINKDMA(hsd,hdmarx,hdma_sdmmc1_rx);

    /* SDMMC1_TX Init */
    hdma_sdmmc1_tx.Instance = DMA2_Stream6;
    hdma_sdmmc1_tx.Init.Channel = DMA_CHANNEL_4;
    hdma_sdmmc1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
    hdma_sdmmc1_tx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_sdmmc1_tx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_sdmmc1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
    hdma_sdmmc1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
    hdma_sdmmc1_tx.Init.Mode = DMA_PFCTRL;
    hdma_sdmmc1_tx.Init.Priority = DMA_PRIORITY_LOW;
    hdma_sdmmc1_tx.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
    hdma_sdmmc1_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
    hdma_sdmmc1_tx.Init.MemBurst = DMA_MBURST_INC4;
    hdma_sdmmc1_tx.Init.PeriphBurst = DMA_PBURST_INC4;
    if (HAL_DMA_Init(&hdma_sdmmc1_tx) != HAL_OK)
    {
      Error_Handler();
    }

    __HAL_LINKDMA(hsd,hdmatx,hdma_sdmmc1_tx);

    /* SDMMC1 interrupt Init */
    HAL_NVIC_SetPriority(SDMMC1_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(SDMMC1_IRQn);
  /* USER CODE BEGIN SDMMC1_MspInit 1 */

  /* USER CODE END SDMMC1_MspInit 1 */
  }

}

ВЫШЕУКАЗАННАЯ ФУНКЦИЯ ВЫПОЛНЯЕТСЯ ОТ И ДО

HAL_StatusTypeDef HAL_SD_InitCard(SD_HandleTypeDef *hsd)
{
  uint32_t errorstate;
  HAL_StatusTypeDef status;
  SD_InitTypeDef Init;
  
  /* Default SDMMC peripheral configuration for SD card initialization */
  Init.ClockEdge           = SDMMC_CLOCK_EDGE_RISING;
  Init.ClockBypass         = SDMMC_CLOCK_BYPASS_DISABLE;
  Init.ClockPowerSave      = SDMMC_CLOCK_POWER_SAVE_DISABLE;
  Init.BusWide             = SDMMC_BUS_WIDE_1B;
  Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE;
  Init.ClockDiv            = SDMMC_INIT_CLK_DIV;

  /* Initialize SDMMC peripheral interface with default configuration */
  status = SDMMC_Init(hsd->Instance, Init);
  if(status != HAL_OK)
  {
    return HAL_ERROR;
  }

  /* Disable SDMMC Clock */
  __HAL_SD_DISABLE(hsd);

  /* Set Power State to ON */
  (void)SDMMC_PowerState_ON(hsd->Instance);

  /* Enable SDMMC Clock */
  __HAL_SD_ENABLE(hsd);

  /* Identify card operating voltage */
  errorstate = SD_PowerON(hsd);
  
  // ПОДВИСАЕТ В ВЫШЕУКАЗАННОЙ ФУНКЦИИ, ВСЕ ЧТО НИЖЕ ВЫПОЛНЯЕТСЯ ПОТОМ
  
  if(errorstate != HAL_SD_ERROR_NONE)
  {
    hsd->State = HAL_SD_STATE_READY;
    hsd->ErrorCode |= errorstate;
    return HAL_ERROR;
  }

  /* Card initialization */
  errorstate = SD_InitCard(hsd);
  if(errorstate != HAL_SD_ERROR_NONE)
  {
    hsd->State = HAL_SD_STATE_READY;
    hsd->ErrorCode |= errorstate;
    return HAL_ERROR;
  }

  return HAL_OK;
}

А вот функция, в которой происходит подвисание

static uint32_t SD_PowerON(SD_HandleTypeDef *hsd)
{
  __IO uint32_t count = 0U;
  uint32_t response = 0U, validvoltage = 0U;
  uint32_t errorstate;

  /* CMD0: GO_IDLE_STATE */
  errorstate = SDMMC_CmdGoIdleState(hsd->Instance);
  if(errorstate != HAL_SD_ERROR_NONE)
  {
    return errorstate;
  }

  /* CMD8: SEND_IF_COND: Command available only on V2.0 cards */
  errorstate = SDMMC_CmdOperCond(hsd->Instance);
  if(errorstate != HAL_SD_ERROR_NONE)
  {
    hsd->SdCard.CardVersion = CARD_V1_X;
    /* CMD0: GO_IDLE_STATE */
    errorstate = SDMMC_CmdGoIdleState(hsd->Instance);
    if(errorstate != HAL_SD_ERROR_NONE)
    {
      return errorstate;
    }

  }
  else
  {
    hsd->SdCard.CardVersion = CARD_V2_X;
  }

  if( hsd->SdCard.CardVersion == CARD_V2_X)
  {
    /* SEND CMD55 APP_CMD with RCA as 0 */
    errorstate = SDMMC_CmdAppCommand(hsd->Instance, 0);
    if(errorstate != HAL_SD_ERROR_NONE)
    {
      return HAL_SD_ERROR_UNSUPPORTED_FEATURE;
    }
  }
  /* SD CARD */
  /* Send ACMD41 SD_APP_OP_COND with Argument 0x80100000 */
  
  // ЭТОТ ЦИКЛ КРУТИТСЯ ОЧЕНЬ ДОЛГО, ПОЧЕМУ - ОБЪЯСНЮ НИЖЕ
  
  while((count < SDMMC_MAX_VOLT_TRIAL) && (validvoltage == 0U))
  {
    /* SEND CMD55 APP_CMD with RCA as 0 */
    errorstate = SDMMC_CmdAppCommand(hsd->Instance, 0);
    if(errorstate != HAL_SD_ERROR_NONE)
    {
      return errorstate;
    }

    /* Send CMD41 */
    errorstate = SDMMC_CmdAppOperCommand(hsd->Instance, SDMMC_VOLTAGE_WINDOW_SD | SDMMC_HIGH_CAPACITY | SD_SWITCH_1_8V_CAPACITY);
    if(errorstate != HAL_SD_ERROR_NONE)
    {
      return HAL_SD_ERROR_UNSUPPORTED_FEATURE;
    }

    /* Get command response */
    response = SDMMC_GetResponse(hsd->Instance, SDMMC_RESP1);

    /* Get operating voltage*/
    validvoltage = (((response >> 31U) == 1U) ? 1U : 0U);

    count++;
  }

  if(count >= SDMMC_MAX_VOLT_TRIAL)
  {
    return HAL_SD_ERROR_INVALID_VOLTRANGE;
  }

  if((response & SDMMC_HIGH_CAPACITY) == SDMMC_HIGH_CAPACITY) /* (response &= SD_HIGH_CAPACITY) */
  {
    hsd->SdCard.CardType = CARD_SDHC_SDXC;
  }
  else
  {
    hsd->SdCard.CardType = CARD_SDSC;
  }


  return HAL_SD_ERROR_NONE;
}

 

Засада кроется вот где

 

while((count < SDMMC_MAX_VOLT_TRIAL) && (validvoltage == 0U))
  {
    /* SEND CMD55 APP_CMD with RCA as 0 */
    errorstate = SDMMC_CmdAppCommand(hsd->Instance, 0);
    if(errorstate != HAL_SD_ERROR_NONE)
    {
      return errorstate;
    }

    /* Send CMD41 */
    errorstate = SDMMC_CmdAppOperCommand(hsd->Instance, SDMMC_VOLTAGE_WINDOW_SD | SDMMC_HIGH_CAPACITY | SD_SWITCH_1_8V_CAPACITY);
    if(errorstate != HAL_SD_ERROR_NONE)
    {
      return HAL_SD_ERROR_UNSUPPORTED_FEATURE;
    }

    /* Get command response */
    response = SDMMC_GetResponse(hsd->Instance, SDMMC_RESP1);

    /* Get operating voltage*/
    validvoltage = (((response >> 31U) == 1U) ? 1U : 0U);

    count++;
  }

Если посмотреть на условие while, то этот цикл крутится пока не произойдет одно из событий - либо validvoltage не станет неравным нулю, либо пока count не дотикает до 0xFF

Как только он дотикает, программа идет дальше.

response всегда равен 0xFF8000, validvoltage=0;

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

На всякиий случай - осциллограмма с CMD во время ожидания

HjQCBY53.png?download=1&name=%D0%A1%D0%B

 

Клок аналогичного качества

На остальных линиях лог.1, шумов нет.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Just now, aaarrr said:

Конденсатора рядом с картой нет? Если нет, добавьте 1мкФ.

Есть конденсатор.

P.S. Ну вы мою простынку почитали? Понятно, что что-то с определением вольтажа не так?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

8 часов назад, MementoMori сказал:

проблема именно с инициализацией. Чтение идёт нормально.

Тогда проверьте частоты: инициализация, вроде, порядка 400 кГц, а чтение можно хоть 48 МГц (вроде).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 minutes ago, adnega said:

Тогда проверьте частоты: инициализация, вроде, порядка 400 кГц, а чтение можно хоть 48 МГц (вроде).

Проверю, конечно. Отмечу только, что такой же проект, сгенерированный тем же Кубом для платы Discovery работает нормально. Там, правда, резисторы есть....

Но частоты не переключаются. По крайней мере пользователем, может быть HAL в своих недрах дает какие-то команды....Единственное - инициализация идет в однобитном режиме.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

5 minutes ago, MementoMori said:

По крайней мере пользователем, может быть HAL в своих недрах дает какие-то команды....

Так и есть - во время инициализации на клоке 400 кгц, потом включается 24 МГЦ (почему-то, мож где делитель).

18 minutes ago, adnega said:

Вывод CMD (PD2) не должен быть OD? У вас PP.

Поставил в OD - инициализируется так же долго, а после инициализации ничего не читает. Кстати в Кубе при настройке SDMMC вообще нет варианта включить эту ногу в OD 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 minute ago, adnega said:

Что насчет: "Вывод CMD (PD2) не должен быть OD? У вас PP. "

Написал же выше )))

Quote

Поставил в OD - инициализируется так же долго, а после инициализации ничего не читает. Кстати в Кубе при настройке SDMMC вообще нет варианта включить эту ногу в OD 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

4 часа назад, jcxz сказал:

А что - современные SD-карты не поддерживают SPI?

Поддерживают, только 6-8 мегабайт\сек по нему сложно получить, поэтому в ИМХ6 использовал 4бит СД

9 минут назад, MementoMori сказал:

Кстати в Кубе при настройке SDMMC вообще нет варианта включить эту ногу в OD 

Так если эти ноги переключают от гпио в СД режим, там уже автоматом МК переводит их в нужное "русло"...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

3 minutes ago, mantech said:

Так если эти ноги переключают от гпио в СД режим, там уже автоматом МК переводит их в нужное "русло"...

Давайте так... карта читает и пишет файлы, без нареканий. Длительно, большими объемами не проверял, но она работает.

 В моей длинной простынке (может ее тяжело читать?) я написал, что проблема возникает при вызове 

SD_PowerON

Понимаете, я вам жалуюсь на то, что машина ездит нормально, после остановки долго заводится, потом снова едет нормально, а вы мне предлагаете проверить, не заклинило ли подшипник колеса. 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...