Jump to content
    

MementoMori

Свой
  • Posts

    1,213
  • Joined

  • Last visited

Everything posted by MementoMori


  1. Удаление оного не решает проблемы.
  2. Давайте так... карта читает и пишет файлы, без нареканий. Длительно, большими объемами не проверял, но она работает. В моей длинной простынке (может ее тяжело читать?) я написал, что проблема возникает при вызове SD_PowerON Понимаете, я вам жалуюсь на то, что машина ездит нормально, после остановки долго заводится, потом снова едет нормально, а вы мне предлагаете проверить, не заклинило ли подшипник колеса.
  3. Может с DMA что не так? Хотя врядли...
  4. Так и есть - во время инициализации на клоке 400 кгц, потом включается 24 МГЦ (почему-то, мож где делитель). Поставил в OD - инициализируется так же долго, а после инициализации ничего не читает. Кстати в Кубе при настройке SDMMC вообще нет варианта включить эту ногу в OD
  5. Проверю, конечно. Отмечу только, что такой же проект, сгенерированный тем же Кубом для платы Discovery работает нормально. Там, правда, резисторы есть.... Но частоты не переключаются. По крайней мере пользователем, может быть HAL в своих недрах дает какие-то команды....Единственное - инициализация идет в однобитном режиме.
  6. Есть конденсатор. P.S. Ну вы мою простынку почитали? Понятно, что что-то с определением вольтажа не так?
  7. На всякиий случай - осциллограмма с CMD во время ожидания Клок аналогичного качества На остальных линиях лог.1, шумов нет.
  8. Итак, схема Настройка портов Только не подумайте, что я настолько окалокубился, что даже не умею вручную настраивать ножки, я картинку из куба выложил для наглядности. Тактирование Трассировка (интуитивно понятно, где 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;
  9. Друзья, спасибо за советы, но хочу напомнить - проблема именно с инициализацией. Чтение идёт нормально. Как мне кажется, если бы были проблемы с железом, то это отражалось бы на всех этапах работы. Если я не прав - поправьте.
  10. Спасибо. Вечером доберусь до дома. Приведу схему, трассировку, даже кабель и плату разъёма сфоткаю. Нет. А эта линия наиболее критична? У меня платка китайская для 3д принтера, на ней 4 линии, конденсатор, резисторов нет. Подключеная к контроллеру 3д принтера она работает. Ладно, остальная информация вечером.
  11. Я бы в дополнение еще отметил интересный факт. Если включать на "холодную", то это происходит всегда. Если же подключаться отладчиком, то первый раз - долго, а потом можно долго ресетить контроллер, прежде чем такая ситуация возникнет вновь. Кстати.... у меня нет резисторов на линиях, но есть внутренние подтяжки, а кабель короткий - 7 см. Так можно делать?
  12. STM32F746, Код сгенерирован калокубом. Есть такая функция в нем SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_APP_CMD, SDMMC_CMDTIMEOUT); Так вот когда в теле этой функции проверяется регистр SDMMCx->STA, то проверка идет очень долго, так как бит CMDACT в единице. Спустя 20-30 секунд бит сбрасывается и карта работает идеально. Что характерно, время инициализации может быть и меньшим, иногда все сразу проходит. режим 4 битный, частота 48 МГц. Куда копать?
  13. Задолбался отлавливать один глюк, возникающий при обновлении списка файлов. Есть один вопрос, ответ на который приблизить меня к пониманию причины этого глюка. Скажите, функция f_readdir() читает данные обращаясь к карте, или же из находящегося в оперативной памяти некоего массива?
  14. Еще один вопрос. Когда-то я писал просмотрщик папок, это было еще под DOS. Был там удобный способ переходить из директории в директорию, с помощью добавления в путь двух точек. Например если задать путь "\.." - то попадешь в предыдущую директорию. А если написать "С:\FOLDER\.." то попадешь в "С:\". И в списке файлов первая запись это "..". Удобно - парсить строку не надо. А можно ли как-то так же с FatFS?
  15. Хорошо телепатируете. Не только на прием, но и на передачу - я ведь сделал именно так, как вы сейчас написали, но до прочтения вашего поста (и чуть позже после того, как он был оставлен) Угадайте мою следующую проблему и ее решение)
  16. Вопрос следующий. Получил я текст, читаемый в cp1251, записанный в переменную fn, представляющую собой массив uint8_t. Хочу вывести его в виджет библиотеки TouchGFX рукописной функцией SetItemFName(fn); Но загвоздка в том, что нужен юникод, для этого, как я понял из таблицы кодировок, нужно прибавить к символу число 848. Соответственно нужно преобразовать в uint16_t пытаюсь это сделать. У меня строка "абвгд", то есть последовательость 0xE0, 0xE1, 0xE2, 0xE3, 0xE4. Преобразовываю SetItemFName((uint16_t*)fn) Получаю массив не из 0x00E0,0x00E1,0x00E2,0x00E3, а нечто иное - 0xE1E0, 0xE3E2,0xE5E4. Я конечно уже сделал все ручками, побайтово заполнив массив в цикле, но что-то мне подсказывает, что есть более изящное решение. Есть ли оно и каково оно?
  17. Поддерживаю идею о работе по частям. Правда у меня свои причины. Я пытаюсь читать SD карту при помощи интерфейса touchgfx. А в случае отображения информации на экране, память в любом случае будет забита - в scrolllist, если будет 5000 файлов, все 5 тысяч и загрузится и займут память. Зачем дублировать эти данные массивом, необходимым только для передачи информации из системной области в интерфейсу. Я полагаю, создатели touchgfx озаботились обработкой scrollist, количество элементов которого заранее неизвестно Правда, я поступил коряво - не стал транспортировать данные, а тупо подключил Fatfs.h к файлу, описыващему конкретный экран и вызываю функции работы с файловой системой прямо из интерфейса. Чем разрушаю идею создателей о разделении интерфейса и системы. Но работает без глюков. Хочу, правда, переделать - подавать команды из интерфейса в системную область программы, читать по одному имени файла и передавать его куда следует.
  18. Так если бы этой кодировки не было вообще, а то ж ведь до 0.12С была, а потом пропала. Так русский Иван набросал функцию перекодирования, но все же недоумевает, почему китайский Хунь так кастрировал свое творение.
  19. Вот товарищ http://forum.easyelectronics.ru/viewtopic.php?f=35&t=33457 (вроде бы его ник видел и на этом форуме) пишет Раньше я решал эту проблему подсовыванием нужных макросов/таблиц из каких-то старых версий FatFS, где Win1251 ещё была. Но оказалось, что в R0.13 (может одной-двух предыдущих - не знаю) сильно изменилась система перекодировок и просто подсунуть нужные таблицы не получается.
  20. Спас вот такой костыль for(uint8_t i=0; i<strlen(fn);i++) { if ((fn[i]>=128) && (fn[i]<=175)) fn[i]+=64; //A...Я,а..п else if ((fn[i]>=224) && (fn[i]<=239)) fn[i]+=16; //р..я else if (fn[i]==240) fn[i]=168; // Ё else if (fn[i]==241) fn[i]=184;// ё }
  21. Вывожу через uart. Вот как выглядит файл "абвгдеж.txt" Это наверное и правда win1251 161->193 162->194 163->195 и дальше по тексту. Я когда искал решение своей проблемы, наткнулся на тему, где товарищ сетовал, что у него русские буквы читаются только если указать cp1251, но это в версии FatFS 0.12b, а он хочет Fat 0.13. Китайцы ему ответитили, что 0.12b- последняя версия, которая поддерживает cp1251. У меня версия 0.12c (то есть уже не b) Я создавал файлы ручками, из под винды. Так же может сделать и пользователь. Что же это получается, последняя версия принципиально не годится для русского Ивана?
  22. Добрый вечер. Ковыряю FatFS R0.12c Не получается читать русские буквы. Настраиваю так #define FF_CODE_PAGE 866#define FF_USE_LFN 2#define FF_LFN_UNICODE 0 Ну или #define FF_CODE_PAGE 855 Вместо русских букв белеберда. Хотя в библиотеке есть не просто кириллица (855), но и "Russian" - 866. Что я делаю не так?
×
×
  • Create New...