mantech 53 23 декабря, 2020 Опубликовано 23 декабря, 2020 · Жалоба 6 часов назад, MementoMori сказал: 7 часов назад, _4afc_ сказал: На CMD есть внешняя подтяжка? Нет. А эта линия наиболее критична? Проц IMX6 длина линий до SD карты 7см, выровнены, никаких подтяжек нет, время инита SD2.0 и SDHC менее пол-секунды, клок 25МГц. Инит карт 1.0 8 Мб (мегабайт - это не опечатка) 1-2сек, хотя в режиме spi- пол-секунды, х.з. почему, но такие карты сейчас только в музее есть, поэтому забил... 3 часа назад, MementoMori сказал: Как мне кажется, если бы были проблемы с железом, то это отражалось бы на всех этапах работы. Если я не прав - поправьте. Так-то да, нужно проверять чтение и запись больших блоков в течении 10 мин. хотя бы. И еще, при ините требуется снижать клок до 100КГц или мегагерца уже не помню, и прочитав регистр конфигурации, можно повышать чатоту... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 243 23 декабря, 2020 Опубликовано 23 декабря, 2020 · Жалоба 1 час назад, mantech сказал: хотя в режиме spi- пол-секунды, х.з. почему, но такие карты сейчас только в музее есть, поэтому забил... А что - современные SD-карты не поддерживают SPI? Как так, ведь спецификация вроде обязывает?... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MementoMori 4 23 декабря, 2020 Опубликовано 23 декабря, 2020 · Жалоба Итак, схема Настройка портов Только не подумайте, что я настолько окалокубился, что даже не умею вручную настраивать ножки, я картинку из куба выложил для наглядности. Тактирование Трассировка (интуитивно понятно, где TOP, а где BOTTOM) Плата со слотом И вот CallStack до зависания Пройдемся по этому списку 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; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MementoMori 4 23 декабря, 2020 Опубликовано 23 декабря, 2020 · Жалоба На всякиий случай - осциллограмма с CMD во время ожидания Клок аналогичного качества На остальных линиях лог.1, шумов нет. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 69 23 декабря, 2020 Опубликовано 23 декабря, 2020 · Жалоба Конденсатора рядом с картой нет? Если нет, добавьте 1мкФ. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MementoMori 4 23 декабря, 2020 Опубликовано 23 декабря, 2020 · Жалоба Just now, aaarrr said: Конденсатора рядом с картой нет? Если нет, добавьте 1мкФ. Есть конденсатор. P.S. Ну вы мою простынку почитали? Понятно, что что-то с определением вольтажа не так? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adnega 11 23 декабря, 2020 Опубликовано 23 декабря, 2020 · Жалоба 8 часов назад, MementoMori сказал: проблема именно с инициализацией. Чтение идёт нормально. Тогда проверьте частоты: инициализация, вроде, порядка 400 кГц, а чтение можно хоть 48 МГц (вроде). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MementoMori 4 23 декабря, 2020 Опубликовано 23 декабря, 2020 · Жалоба 2 minutes ago, adnega said: Тогда проверьте частоты: инициализация, вроде, порядка 400 кГц, а чтение можно хоть 48 МГц (вроде). Проверю, конечно. Отмечу только, что такой же проект, сгенерированный тем же Кубом для платы Discovery работает нормально. Там, правда, резисторы есть.... Но частоты не переключаются. По крайней мере пользователем, может быть HAL в своих недрах дает какие-то команды....Единственное - инициализация идет в однобитном режиме. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adnega 11 23 декабря, 2020 Опубликовано 23 декабря, 2020 · Жалоба Вывод CMD (PD2) не должен быть OD? У вас PP. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MementoMori 4 23 декабря, 2020 Опубликовано 23 декабря, 2020 · Жалоба 5 minutes ago, MementoMori said: По крайней мере пользователем, может быть HAL в своих недрах дает какие-то команды.... Так и есть - во время инициализации на клоке 400 кгц, потом включается 24 МГЦ (почему-то, мож где делитель). 18 minutes ago, adnega said: Вывод CMD (PD2) не должен быть OD? У вас PP. Поставил в OD - инициализируется так же долго, а после инициализации ничего не читает. Кстати в Кубе при настройке SDMMC вообще нет варианта включить эту ногу в OD Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MementoMori 4 23 декабря, 2020 Опубликовано 23 декабря, 2020 · Жалоба Может с DMA что не так? Хотя врядли... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adnega 11 23 декабря, 2020 Опубликовано 23 декабря, 2020 · Жалоба Что насчет: "Вывод CMD (PD2) не должен быть OD? У вас PP. " Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MementoMori 4 23 декабря, 2020 Опубликовано 23 декабря, 2020 · Жалоба 1 minute ago, adnega said: Что насчет: "Вывод CMD (PD2) не должен быть OD? У вас PP. " Написал же выше ))) Quote Поставил в OD - инициализируется так же долго, а после инициализации ничего не читает. Кстати в Кубе при настройке SDMMC вообще нет варианта включить эту ногу в OD Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
mantech 53 23 декабря, 2020 Опубликовано 23 декабря, 2020 · Жалоба 4 часа назад, jcxz сказал: А что - современные SD-карты не поддерживают SPI? Поддерживают, только 6-8 мегабайт\сек по нему сложно получить, поэтому в ИМХ6 использовал 4бит СД 9 минут назад, MementoMori сказал: Кстати в Кубе при настройке SDMMC вообще нет варианта включить эту ногу в OD Так если эти ноги переключают от гпио в СД режим, там уже автоматом МК переводит их в нужное "русло"... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MementoMori 4 23 декабря, 2020 Опубликовано 23 декабря, 2020 · Жалоба 3 minutes ago, mantech said: Так если эти ноги переключают от гпио в СД режим, там уже автоматом МК переводит их в нужное "русло"... Давайте так... карта читает и пишет файлы, без нареканий. Длительно, большими объемами не проверял, но она работает. В моей длинной простынке (может ее тяжело читать?) я написал, что проблема возникает при вызове SD_PowerON Понимаете, я вам жалуюсь на то, что машина ездит нормально, после остановки долго заводится, потом снова едет нормально, а вы мне предлагаете проверить, не заклинило ли подшипник колеса. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться