UniSoft 15 4 марта, 2019 Опубликовано 4 марта, 2019 · Жалоба Этот контроллер мне уже весь мозг вынес... Что ему блин нужно? Может кто подскажет что-то дельное... Итак, контроллер STM32F722... + FatFs... проблема в чтении SD, а точнее в DMA и кэше, не хотят они никак дружить. Все работало... проект рос... и хрясь с того ни с сего и больше не работает... Со временем выяснилось, что перестало работать как только буферы оказались в SRAM1 (ну т.е. выше 0x20010000)... Данные просто повреждены и все. И это реально взрыв мозга, вроде все правильно но не работает, и в то же время работает при определенных условиях, откуда же я мог догадаться, что проблема именно в кэше, в коде ведь есть очистка но она видимо не работает, из-за этого перебрал весь код. Итак, что помогает: 1. выключение (а точнее не включение) DCache... (Но это как-то не правильно) 2. Размещение буферов в области DTCM... (Не распределять же мне теперь вручную все буферы, (от)куда идут данные) 3. Возможно поможет переход на IT вместо DMA (пока не пробовал) Так вот кто-нибудь может что-то порекомендовать? Может уже решали подобную задачу? Вот функции чтения и записи //---------------------------------------------------------------------------- //! @brief Reads block(s) from a specified address in a card. The Data transfer //! is managed by DMA mode. //! @param pData : Pointer to the buffer that will contain the received data //! @param BlockAdd : Block Address from where data is to be read //! @param NumOfBlocks : Number of blocks to read. //! @retval DRESULT: Operation result //---------------------------------------------------------------------------- static DRESULT sd_read(void *pData, uint32_t BlockAdd, uint32_t NumOfBlocks) { // Read block(s) in DMA transfer mode if (SD_ReadBlocks_DMA((uint32_t *)pData, BlockAdd, NumOfBlocks) == MSD_OK) { // Wait that the reading process is completed or a timeout occurs uint32_t flags = osEventFlagsWait(SDEventID, SD_READ_CPLT_MSG | SD_ERROR_MSG | SD_ABORT_MSG, osFlagsWaitAny, SD_TIMEOUT); if ((flags & (osFlagsError | SD_READ_CPLT_MSG)) == SD_READ_CPLT_MSG) { // block until SDIO IP is ready or a timeout occur uint32_t tc = osKernelSysTick(); do { if (SD_GetCardState() == SD_CARD_TRANSFER) { #if (ENABLE_SD_DMA_CACHE_MAINTENANCE == 1) // the SCB_InvalidateDCache_by_Addr() requires a 32-Byte aligned address, // adjust the address and the D-Cache size to invalidate accordingly. uint32_t alignedAddr = (uint32_t)pData & ~0x1FUL; SCB_InvalidateDCache_by_Addr((uint32_t *)alignedAddr, NumOfBlocks * SD_BLOCKSIZE + ((uint32_t)pData - alignedAddr)); #endif return RES_OK; } } while ((osKernelSysTick() - tc) < SD_TIMEOUT); } } return RES_ERROR; } //---------------------------------------------------------------------------- //! @brief Writes block(s) to a specified address in a card. The Data transfer //! is managed by DMA mode. //! @param pData : Pointer to the buffer that will contain the data to transmit //! @param BlockAdd : Block Address where data will be written //! @param NumOfBlocks : Number of blocks to write //! @retval DRESULT: Operation status //---------------------------------------------------------------------------- static DRESULT sd_write(const void *pData, uint32_t BlockAdd, uint32_t NumOfBlocks) { #if (ENABLE_SD_DMA_CACHE_MAINTENANCE == 1) // Invalidate the chache before writting into the buffer. // This is not needed if the memory region is configured as W/T. uint32_t alignedAddr = (uint32_t)pData & ~0x1FUL; //SCB_InvalidateDCache_by_Addr((uint32_t *)alignedAddr, NumOfBlocks * SD_BLOCKSIZE + ((uint32_t)pData - alignedAddr)); SCB_CleanDCache_by_Addr((uint32_t *)alignedAddr, NumOfBlocks * SD_BLOCKSIZE + ((uint32_t)pData - alignedAddr)); #endif // Write block(s) in DMA transfer mode if (SD_WriteBlocks_DMA((uint32_t *)pData, BlockAdd, NumOfBlocks) == MSD_OK) { // wait until the read operation is finished uint32_t flags = osEventFlagsWait(SDEventID, SD_WRITE_CPLT_MSG | SD_ERROR_MSG | SD_ABORT_MSG, osFlagsWaitAny, SD_TIMEOUT); if ((flags & (osFlagsError | SD_WRITE_CPLT_MSG)) == SD_WRITE_CPLT_MSG) { // block until SDIO IP is ready or a timeout occur uint32_t tc = osKernelSysTick(); do { if (SD_GetCardState() == SD_CARD_TRANSFER) { return RES_OK; } } while ((osKernelSysTick() - tc) < SD_TIMEOUT); } } return RES_ERROR; } Пробовал Configure the MPU attributes as WT for SRAM но это не помогает //---------------------------------------------------------------------------- //! @brief Configure the MPU attributes as Write Through for SRAM1/2. //! @note The Base Address is 0x20010000 since this memory interface is the AXI. //! The Region Size is 256KB, it is related to SRAM1 and SRAM2 memory size. //! @param None //! @retval None //---------------------------------------------------------------------------- static void MPU_Config(void) { // Disable MPU LL_MPU_Disable(); // Configure the MPU attributes as WT for SRAM LL_MPU_ConfigRegion(LL_MPU_REGION_NUMBER1, 0x00, 0x20010000UL, LL_MPU_REGION_SIZE_256KB | LL_MPU_REGION_FULL_ACCESS | LL_MPU_ACCESS_NOT_BUFFERABLE | MPU_ACCESS_CACHEABLE | MPU_ACCESS_NOT_SHAREABLE | LL_MPU_TEX_LEVEL1 | LL_MPU_INSTRUCTION_ACCESS_ENABLE); // Enable MPU (any access not covered by any enabled region will cause a fault) LL_MPU_Enable(LL_MPU_CTRL_PRIVILEGED_DEFAULT); } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 69 4 марта, 2019 Опубликовано 4 марта, 2019 · Жалоба Дурацкий вопрос, но значение ENABLE_SD_DMA_CACHE_MAINTENANCE проверяли? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
UniSoft 15 4 марта, 2019 Опубликовано 4 марта, 2019 · Жалоба 10 minutes ago, aaarrr said: Дурацкий вопрос, но значение ENABLE_SD_DMA_CACHE_MAINTENANCE проверяли? Оно установлено верно. Я уже тоже засомневался, и не только по этому дефайну, а еще и по __DCACHE_PRESENT (что используется в SCB_CleanDCache_by_Addr()) Посмотрел в дизассемблере, все с этим ок Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 69 4 марта, 2019 Опубликовано 4 марта, 2019 · Жалоба Не знаю, где этот дефайн должен определяться, но в приведенном коде проверка присутствует: 21 minutes ago, UniSoft said: #if (ENABLE_SD_DMA_CACHE_MAINTENANCE == 1) Поэтому и вопрос. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
UniSoft 15 4 марта, 2019 Опубликовано 4 марта, 2019 · Жалоба 2 minutes ago, aaarrr said: Не знаю, где этот дефайн должен определяться, но в приведенном коде проверка присутствует: Поэтому и вопрос. не сразу уловил, про какое значение говорите... Определен верно, в коде все присутствует (смотрел в дизассемблере). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 69 4 марта, 2019 Опубликовано 4 марта, 2019 · Жалоба 8 minutes ago, UniSoft said: не сразу уловил, про какое значение говорите... Определен верно, в коде все присутствует (смотрел в дизассемблере). Понятно, просто иногда очевидные моменты выпадают из поля зрения. А реализацию SCB_InvalidateDCache_by_Addr() проверяли? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GenaSPB 11 4 марта, 2019 Опубликовано 4 марта, 2019 · Жалоба При чтении подготовить область памяьи (CleanInvalidate) ДО ЧТЕНИЯ. При записи Clean ДО ЗАПИСИ. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 236 4 марта, 2019 Опубликовано 4 марта, 2019 · Жалоба 45 минут назад, UniSoft сказал: (Не распределять же мне теперь вручную все буферы, (от)куда идут данные) А почему нет? Так собственно и надо бы делать. 45 минут назад, UniSoft сказал: Так вот кто-нибудь может что-то порекомендовать? Покурить атрибуты областей памяти в MPU. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
UniSoft 15 4 марта, 2019 Опубликовано 4 марта, 2019 · Жалоба 3 minutes ago, aaarrr said: А реализацию SCB_InvalidateDCache_by_Addr() проверяли? Да смотрел, а что толку... 1 minute ago, GenaSPB said: При чтении подготовить область памяьи (CleanInvalidate) ДО ЧТЕНИЯ. При записи Clean ДО ЗАПИСИ. Я честно говоря, не понимаю зачем нужно делать CleanInvalidate до чтения, но (читал обсуждение) и видел в исходниках https://github.com/micropython/micropython/blob/86f06d6a874d4eb3d6c50deec0240942344c01ea/ports/stm32/sdcard.c И тоже пробовал ставить очистку еще и до чтения, но результата это не дало... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
UniSoft 15 4 марта, 2019 Опубликовано 4 марта, 2019 · Жалоба 13 minutes ago, jcxz said: А почему нет? Так собственно и надо бы делать. Покурить атрибуты областей памяти в MPU. Да это как-то странно, распределять буферы... А если это локальные буферы? ну там прочитать заголовок файла... можно конечно двойную буферизацию, но пока ищу нормальное решение. А атрибуты памяти выкурил все в корень, все перепробовал и CACHEABLE и NOT_CACHEABLE, SHAREABLE и NOT_SHAREABLE, LL_MPU_REGION_NUMBER0 и LL_MPU_REGION_NUMBER1 (в разных примерах по разному) при некоторых валится в HardFault, при других ничего не меняется. Прежде чем сюда написать, перепробовал все, что только мог. Перерыл множество примеров. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GenaSPB 11 4 марта, 2019 Опубликовано 4 марта, 2019 (изменено) · Жалоба До чтения. До записи. Перебирать долго будете. не про атрибуты, а про доступность областей памяти для DMA, но если с выключенным data cache работает - с этим нормально. Если что - вот идеально работающий на F7 вариант. https://github.com/ua1arn/hftrx/blob/master/sdcard.c Смотреть SD_disk_read и SD_disk_write Изменено 4 марта, 2019 пользователем GenaSPB Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AVI-crak 0 4 марта, 2019 Опубликовано 4 марта, 2019 · Жалоба 1 hour ago, GenaSPB said: Если что - вот идеально работающий на F7 вариант // ?????? HF Dream Receiver (?? ??????? ?????) Там наверное что-то важное было... До автоматической смены кодировки. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GenaSPB 11 4 марта, 2019 Опубликовано 4 марта, 2019 · Жалоба Нет.... скачайте и смотритте в нужной кодировке. Обычнам cp1251 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
UniSoft 15 4 марта, 2019 Опубликовано 4 марта, 2019 · Жалоба 4 hours ago, GenaSPB said: Если что - вот идеально работающий на F7 вариант. https://github.com/ua1arn/hftrx/blob/master/sdcard.c Смотреть SD_disk_read и SD_disk_write Посмотрел, к сожалению, ничего нового не увидел. Единственное, что очистка кэша до чтения... хотя я это и не понимаю, но как уже сказал, такой вариант пробовал... не помогло. А на счет идеально работающий, это еще не факт... ради интереса, разместите буфер куда-нибудь за пределы DTCM... ну, например вот так: #define __AT(__ADDR) __attribute__((section(".ARM.__at_" #__ADDR))) #define AT_ADDR(__ADDR) __AT(__ADDR) AT_ADDR(0x20010200) static RAMNOINIT_D1 FATFS wave_Fatfs; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GenaSPB 11 4 марта, 2019 Опубликовано 4 марта, 2019 (изменено) · Жалоба Мы про F7 говорим? Все USB буферы у меня исключительно ВНЕ DTCM размещаются. В DTCM кладу то что требует скоростной работы... Сделано через LD скрипт, в DTCM попадает .data - инициализированные переменные. Скрипт там же. Могу посоветовать проверить выравнивание адресов для обмена - в структурах FatFS это не гарантируется. У меня превышен размер допустимых аттачментов на 17%, а так бы MAP файл заскриншотил бы... Там вот так: .bss 0x20025ae8 0x0 c:/program files (x86)/gnu tools arm embedded/7 2018-q2-update/bin/../lib/gcc/arm-none-eabi/7.3.1/../../../../arm-none-eabi/lib/thumb/v7e-m/fpv4-sp/hard\libc.a(lib_a-strlen.o) *(COMMON) 0x20025b00 . = ALIGN (0x20) *fill* 0x20025ae8 0x18 0x20025b00 __bss_end__ = . .noinit 0x20025b00 0x110c0 0x20025b00 . = ALIGN (0x20) *(.noinit) .noinit 0x20025b00 0x40 C:\Users\gena\AppData\Local\Temp\ccCriE8j.ltrans0.ltrans.o .noinit 0x20025b40 0x10e40 C:\Users\gena\AppData\Local\Temp\ccCriE8j.ltrans2.ltrans.o 0x20026540 wave_Fatfs.lto_priv.478 .noinit 0x20036980 0x240 C:\Users\gena\AppData\Local\Temp\ccCriE8j.ltrans4.ltrans.o 0x20036980 wav_file.lto_priv.480 0x20036bc0 . = ALIGN (0x20) .heap 0x20036bc0 0x0 0x20036bc0 __HeapBase = . 0x20036bc0 __end__ = . 0x20036bc0 end = __end__ *(.heap*) 0x20036bc0 __HeapLimit = . Изменено 4 марта, 2019 пользователем GenaSPB Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться