Donker 0 23 февраля, 2019 Опубликовано 23 февраля, 2019 (изменено) · Жалоба Пытаюсь подключить FatFs (http://elm-chan.org/fsw/ff/00index_e.html) к STM32F105RBT6 + карта SDHC (поддержка старых SD не требуется), проект в Keil 5.26, отладка в оперативной памяти (из 64кб - 40кб под прошивку 24кб оставшаяся оперативная память) Создал проект с тремя основными функциями - инициализация SDHC (предполагается работа только с одной картой), чтение N секторов в буфер начиная со стартового адреса, запись N секторов из буфера начиная со стартового адреса, проверял на буферах размером до 8 секторов, всё надежно работает. Пытаюсь подключить библиотеку, нужно написать функцию disk_read: Спойлер DRESULT disk_read ( BYTE pdrv, /* Physical drive nmuber to identify the drive */ BYTE *buff, /* Data buffer to store read data */ DWORD sector, /* Start sector in LBA */ UINT count /* Number of sectors to read */ ) { ////////////////////////////////////////////////////////////////////////// if(0 == spi_SD_Read_Block(buff, sector, uint8_t (count))) {return RES_OK;} else {return RES_ERROR;} ////////////////////////////////////////////////////////////////////////// } получаю ошибку: Цитата fatfs/diskio.cpp(159): error: no matching function for call to 'spi_SD_Read_Block' моя функция: Спойлер unsigned char spi_SD_Read_Block (char* bf, uint32_t SD_adr, uint8_t adr_count) //чтение секторов из SD карты { ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// unsigned char result; long int cnt = 0; //******************************************************************************************************************* for(uint8_t i=0; i < adr_count; i++) { SD_adr = SD_adr+i; unsigned char SD_adr_0 = SD_adr; //разбивка адреса uint32_t на 4 байта unsigned char SD_adr_1 = SD_adr >> 8; unsigned char SD_adr_2 = SD_adr >> 16; unsigned char SD_adr_3 = SD_adr >> 24; //----------------------------------------------------------------------------------------------------------------- first_ACMD17 = spi_WaitReady(); if(first_ACMD17 == waiting) {return 1;} //превышено время ожидания spi_SD_cmd (0x51, SD_adr_3, SD_adr_2, SD_adr_1, SD_adr_0, 0x95); //CMD17 даташит стр 50 и 96 cnt=0; do { result=spi_SendRecvByte(0xFF); cnt++; } while ((result!=0x00) && (cnt < waiting)); after_ACMD17 = cnt; if (cnt == waiting) return 2; //превышено время ожидания spi_SendRecvByte(0xFF); cnt=0; do //Ждем начала блока { result=spi_SendRecvByte(0xFF); cnt++; } while ((result!=0xFE) && (cnt < waiting)); first_read = cnt; if (cnt == waiting) return 3; for (cnt=0;cnt<512;cnt++) bf[cnt+(512*i)]=spi_SendRecvByte(0xFF); //получаем байты блока из шины в буфер spi_SendRecvByte(0xFF); //Получаем контрольную сумму spi_SendRecvByte(0xFF); } return 0; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// } Что не так? Второй вопрос: я саму библиотеку правильно скачал http://elm-chan.org/fsw/ff/arc/ff13c.zip ? Третий вопрос: мой проект написан на C++ а библиотека FatFs на C, как правильно, в этом случае, её подключать? Изменено 24 февраля, 2019 пользователем Donker добавил вопрос Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Donker 0 24 февраля, 2019 Опубликовано 24 февраля, 2019 · Жалоба Уточнение, если поставить такую заглушку: Цитата char buffer[10]; if(0 == spi_SD_Read_Block(buffer, sector, uint8_t (count))) {return RES_OK;} else {return RES_ERROR;} код компилируется, т.е. компилятору не нравиться передача указателя на буфер, но почему?! BYTE это обычный unsigned char, после подключения FatFs я могу в своём коде поменять unsigned char или uint8_t на BYTE и ничего не изменится. Цитата typedef unsigned char BYTE; /* char must be 8-bit */ Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 184 24 февраля, 2019 Опубликовано 24 февраля, 2019 · Жалоба 2 часа назад, Donker сказал: BYTE это обычный unsigned char, после подключения FatFs я могу в своём коде поменять unsigned char или uint8_t на BYTE и ничего не изменится. Разница в том, что функцию объявили с char *, а вызываете с BYTE *. Соответственно - компилятор не может найти функцию с подходящей вашему вызову декларацией. И что мешает применить явное приведение типа при вызове: spi_SD_Read_Block((char *)buff,... ? Ведь count Вы зачем-то приводите, хотя как раз там это делать бессмысленно и вредно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Donker 0 24 февраля, 2019 Опубликовано 24 февраля, 2019 (изменено) · Жалоба jcxz спасибо, я что то думал что unsigned char и просто char в данном случае одно и тоже. Остальные вопросы в силе, (скоро новые возникнут). Изменено 24 февраля, 2019 пользователем Donker Остальные вопросы в силе... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Donker 0 24 февраля, 2019 Опубликовано 24 февраля, 2019 (изменено) · Жалоба Новые вопросы: Есть некоторые успехи, в этой тестовой функции: Спойлер void ff_test(void) { ////////////////////////////////////////////////////////////////////////////////////////////// FATFS fs; FRESULT res; sprintf(lines[0],"Ready!"); //UART_Printf("Ready!\r\n"); // mount the default drive res = f_mount(&fs, "", 0); sprintf(lines[0],"f_mount, res: %d", res); lcd_refr(); if(res != FR_OK) { //UART_Printf("f_mount() failed, res = %d\r\n", res); return; } //UART_Printf("f_mount() done!\r\n"); //--------------------------------------------------------------------------------------------- uint32_t freeClust; FATFS* fs_ptr = &fs; // Warning! This fills fs.n_fatent and fs.csize! res = f_getfree("", &freeClust, &fs_ptr); sprintf(lines[1],"f_getfree, res: %d", res); lcd_refr(); if(res != FR_OK) { ///UART_Printf("f_getfree() failed, res = %d\r\n", res); return; } ///UART_Printf("f_getfree() done!\r\n"); uint32_t totalBlocks = (fs.n_fatent - 2) * fs.csize; uint32_t freeBlocks = freeClust * fs.csize; //UART_Printf("Total blocks: %lu (%lu Mb)\r\n", totalBlocks, totalBlocks / 2000); //UART_Printf("Free blocks: %lu (%lu Mb)\r\n", freeBlocks, freeBlocks / 2000); sprintf(lines[2],"Total blocks: %d Mb", (totalBlocks / 2048)); sprintf(lines[3],"Free blocks: %d Mb", (freeBlocks / 2048)); lcd_refr(); //--------------------------------------------------------------------------------------------- DIR dir; res = f_opendir(&dir, "/"); sprintf(lines[4],"f_opendir, res: %d", res); lcd_refr(); if(res != FR_OK) { ///UART_Printf("f_opendir() failed, res = %d\r\n", res); return; } FILINFO fileInfo; uint32_t totalFiles = 0; uint32_t totalDirs = 0; //UART_Printf("--------\r\nRoot directory:\r\n"); uint8_t st=0; for(;;) { res = f_readdir(&dir, &fileInfo); if((res != FR_OK) || (fileInfo.fname[0] == '\0')) {break;} if(fileInfo.fattrib & AM_DIR) { //UART_Printf(" DIR %s\r\n", fileInfo.fname); sprintf(lines[5+st],"DIR %s", fileInfo.fname); st++; totalDirs++; } else { //UART_Printf(" FILE %s\r\n", fileInfo.fname); sprintf(lines[5+st],"FILE %s", fileInfo.fname); st++; totalFiles++; } } //UART_Printf("(total: %lu dirs, %lu files)\r\n--------\r\n",totalDirs, totalFiles); sprintf(lines[15],"total: %d dr, %d fl",totalDirs, totalFiles); lcd_refr(); //--------------------------------------------------------------------------------------------- res = f_closedir(&dir); sprintf(lines[16],"f_closedir, res: %d", res); lcd_refr(); if(res != FR_OK) { //UART_Printf("f_closedir() failed, res = %d\r\n", res); return; } //--------------------------------------------------------------------------------------------- //UART_Printf("Writing to log.txt...\r\n"); char writeBuff[128]; snprintf(writeBuff, sizeof(writeBuff), "Total blocks: %d (%d Mb); Free blocks: %d (%d Mb)\r\n", totalBlocks, totalBlocks / 2048, freeBlocks, freeBlocks / 2048); FIL logFile; res = f_open(&logFile, "log.txt", FA_OPEN_APPEND | FA_WRITE); sprintf(lines[17],"f_open, res: %d", res); lcd_refr(); if(res != FR_OK) { //UART_Printf("f_open() failed, res = %d\r\n", res); return; } unsigned int bytesToWrite = strlen(writeBuff); unsigned int bytesWritten; res = f_write(&logFile, writeBuff, bytesToWrite, &bytesWritten); sprintf(lines[18],"f_write, res: %d", res); lcd_refr(); if(res != FR_OK) { //UART_Printf("f_write() failed, res = %d\r\n", res); return; } if(bytesWritten < bytesToWrite) { //UART_Printf("WARNING! Disk is full.\r\n"); } //_delay_ms(1); res = f_close(&logFile); sprintf(lines[18],"f_close, res: %d", res); lcd_refr(); if(res != FR_OK) { //UART_Printf("f_close() failed, res = %d\r\n", res); return; } //--------------------------------------------------------------------------------------------- //UART_Printf("Reading file...\r\n"); FIL msgFile; res = f_open(&msgFile, "log.txt", FA_READ); if(res != FR_OK) { //UART_Printf("f_open() failed, res = %d\r\n", res); return; } char readBuff[128]; unsigned int bytesRead; res = f_read(&msgFile, readBuff, sizeof(readBuff)-1, &bytesRead); if(res != FR_OK) { //UART_Printf("f_read() failed, res = %d\r\n", res); return; } readBuff[bytesRead] = '\0'; //UART_Printf("```\r\n%s\r\n```\r\n", readBuff); res = f_close(&msgFile); if(res != FR_OK) { //UART_Printf("f_close() failed, res = %d\r\n", res); return; } // Unmount res = f_mount(NULL, "", 0); if(res != FR_OK) { //UART_Printf("Unmount failed, res = %d\r\n", res); return; } //UART_Printf("Done!\r\n"); } все функции до f_close нормально работают (как минимум возвращают 0, а не код ошибки, и делают ожидаемые вещи), а вот f_close возвращает 1, почему такое может быть? Нужно ли настраивать таймер на 10ms и вызывать в нём disk_timerproc (я вообще не нашёл такой функции в FatFs)? Каким образом и где FatFs создаёт буферы для чтения и записи сектров, указатели которых передаются в функции disk_write и disk_read, если они создаются динамически, можно ли их заставить создаваться в стеке без потери функциональности библиотеки? Изменено 24 февраля, 2019 пользователем Donker Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Donker 0 25 февраля, 2019 Опубликовано 25 февраля, 2019 · Жалоба Вот весь проект:https://yadi.sk/d/w98_y4E7kJN6Eg Уточнение, перераспределение памяти для отладки в RAM - 44кб под прошивку 20кб оставшаяся оперативная память память. Сейчас появилась такая проблема, в fileWork.cpp в функции ff_test есть строка: res = f_open(&logFile, "log.txt", FA_OPEN_APPEND | FA_WRITE); если выходить из функции до неё, то всо нормально, выполнение этой строки, в какой то момент(не пойму что я сделал), начало приводить к зависанию МК, до этого проблема была только с f_close (код ошибки 1), и ведь строки в log.txt успешно добавлялись! Карта подключена к J10 (схема в проекте), к J2 подключен экран 20x4, lines[NumLines][20] массив для хранения строк отладочного экрана строки крутятся энкодером, пробовал подавать питание на J1 убирая перемычку J4, на проблему это не повлияло. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Donker 0 25 февраля, 2019 Опубликовано 25 февраля, 2019 · Жалоба Нашёл ошибку, в функции чтения и записи секторов (spi_SD_Write_Block и spi_SD_Read_Block) они корректно работали только при чтении одного сектора, иначе адрес котцался, так правильно: uint32_t SD_adr_tmp = SD_adr+i; unsigned char SD_adr_0 = SD_adr_tmp; //разбивка адреса uint32_t на 4 байта unsigned char SD_adr_1 = SD_adr_tmp >> 8; unsigned char SD_adr_2 = SD_adr_tmp >> 16; unsigned char SD_adr_3 = SD_adr_tmp >> 24; но исправление на вышеописанную проблему никак не повлияло. Кстати, я беру некоторый код отсюда: https://eax.me/stm32-fatfs/ вам тут ничего не кажется подозрительным? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Donker 0 25 февраля, 2019 Опубликовано 25 февраля, 2019 · Жалоба Новый вопрос, при каком минимальном количестве оперативной памяти в микроконтроллере у вас нормально работал FatFs не урезанный (с поддержкой длинных имён и юникодом c русской кодовой страницей)? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 184 26 февраля, 2019 Опубликовано 26 февраля, 2019 · Жалоба 7 часов назад, Donker сказал: Новый вопрос, при каком минимальном количестве оперативной памяти в микроконтроллере у вас нормально работал FatFs не урезанный (с поддержкой длинных имён и юникодом c русской кодовой страницей)? Вы это сами можете посмотреть, в своём .map-файле. Не задавая вопросов. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Donker 0 26 февраля, 2019 Опубликовано 26 февраля, 2019 · Жалоба Было переполнение стэка, он был задан 1кб (размер по умолчанию), поставил 4кб, глюк исчез. Это только у меня такая проблема, всем остальным хватает 1кб для FatFs на STM32 ?! При каких обстоятельствах мне ждать от FatFs переполнения уже 4кб? Я нашёл где прячется этот самый массив на 512 байт минимум (см. win BYTE win[FF_MAX_SS];): typedef struct { BYTE fs_type; /* Filesystem type (0:not mounted) */ BYTE pdrv; /* Associated physical drive */ BYTE n_fats; /* Number of FATs (1 or 2) */ BYTE wflag; /* win[] flag (b0:dirty) */ BYTE fsi_flag; /* FSINFO flags (b7:disabled, b0:dirty) */ WORD id; /* Volume mount ID */ WORD n_rootdir; /* Number of root directory entries (FAT12/16) */ WORD csize; /* Cluster size [sectors] */ #if FF_MAX_SS != FF_MIN_SS WORD ssize; /* Sector size (512, 1024, 2048 or 4096) */ #endif #if FF_USE_LFN WCHAR* lfnbuf; /* LFN working buffer */ #endif #if FF_FS_EXFAT BYTE* dirbuf; /* Directory entry block scratchpad buffer for exFAT */ #endif #if FF_FS_REENTRANT FF_SYNC_t sobj; /* Identifier of sync object */ #endif #if !FF_FS_READONLY DWORD last_clst; /* Last allocated cluster */ DWORD free_clst; /* Number of free clusters */ #endif #if FF_FS_RPATH DWORD cdir; /* Current directory start cluster (0:root) */ #if FF_FS_EXFAT DWORD cdc_scl; /* Containing directory start cluster (invalid when cdir is 0) */ DWORD cdc_size; /* b31-b8:Size of containing directory, b7-b0: Chain status */ DWORD cdc_ofs; /* Offset in the containing directory (invalid when cdir is 0) */ #endif #endif DWORD n_fatent; /* Number of FAT entries (number of clusters + 2) */ DWORD fsize; /* Size of an FAT [sectors] */ DWORD volbase; /* Volume base sector */ DWORD fatbase; /* FAT base sector */ DWORD dirbase; /* Root directory base sector/cluster */ DWORD database; /* Data base sector */ #if FF_FS_EXFAT DWORD bitbase; /* Allocation bitmap base sector */ #endif DWORD winsect; /* Current sector appearing in the win[] */ BYTE win[FF_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */ } FATFS; причём структурных переменных "FATFS" может быть много, они что при прерываниях тоже в стек лезут? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 184 26 февраля, 2019 Опубликовано 26 февраля, 2019 · Жалоба 46 минут назад, Donker сказал: причём структурных переменных "FATFS" может быть много, они что при прерываниях тоже в стек лезут? FatFS ничего не знает про прерывания. Не его это дело. Так как он - middleware. И вообще - использование стека зависит от компилятора, ключей его компиляции, архитектуры МК, использования инструкций FPU, .... и много от чего ещё. Создатели middleware не обязаны знать особенности архитектуры всех целевых платформ на которых будет запускаться их ПО. Их должны знать Вы - тот кто портирует FatFS к себе на своё железо/компилятор. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться