|
FATfs и SD-карта, не хочет записываться вновь созданный файл.. |
|
|
|
May 3 2011, 05:29
|
Участник

Группа: Свой
Сообщений: 72
Регистрация: 4-02-05
Пользователь №: 2 424

|
Доброго времени суток! Микроконтроллер STM32 работает с SD картой по SPI. Прицеплена FATfs. Необходимо открыть файл для записи, если файла нет, то создать его и в него записать строку. Но вот в чём проблема, если в файле уже есть хоть один символ, то запись проходит успешно, а если файл только что создали, т.е. его размер равен 0 , то запись не происходит, f_write возвращает FR_INT_ERR. Не могу понять в чём проблема... Помогите кто чем может.. Заранее спасибо. Вот код: CODE void proba () { volatile FRESULT res; // FatFs function common result code UINT br, bw; // File read/write count uint8_t str_cnt = 0;
// Register a work area for logical drive 0 f_mount(0, &fs);
// Открываем файл res = f_open(&fdst, "test_cpy.txt", FA_OPEN_ALWAYS | FA_READ | FA_WRITE); if(res) { res = res; }
buffer[0] = 'A'; buffer[1] = 'B'; buffer[2] = 'C'; buffer[3] = 'D'; buffer[4] = 'E';
for(str_cnt = 0; str_cnt < 10; str_cnt++) { res = f_lseek(&fdst, fdst.fsize); br = 5; res = f_write(&fdst, buffer, br, &bw); if(res) { res = res; } f_puts ("Proba \r\n", &fdst); f_sync (&fdst); }
f_close(&fdst);
// Unregister a work area before discard it f_mount(0, NULL); } Добавлю: Файл не пишется размером больше 4033 байт. Сделал вот так: CODE void proba () { volatile FRESULT res; // FatFs function common result code UINT br, bw; // File read/write count uint8_t str_cnt = 0;
// Register a work area for logical drive 0 f_mount(0, &fs);
// Открываем файл res = f_open(&fdst, "test_cpy.txt", FA_OPEN_ALWAYS | FA_READ | FA_WRITE); if(res) { res = res; }
buffer[0] = 'A'; buffer[1] = 'B'; buffer[2] = 'C'; buffer[3] = 'D'; buffer[4] = 'E';
for(str_cnt = 0; str_cnt < 10; str_cnt++) { res = f_lseek(&fdst, fdst.fsize); br = 5; res = f_write(&fdst, buffer, br, &bw); if(res) { res = res; } f_puts ("Proba \r\n", &fdst); f_sync (&fdst); }
//--------------------------------------------------------------------------------- // Вот этот блок добавил for(str_cnt = 0; str_cnt < 10; str_cnt++) { res = f_lseek(&data_file, ((&data_file)->fsize));
f_puts ("Proba\r\n", &fdst); f_sync (&data_file); } //---------------------------------------------------------------------------------
f_close(&fdst);
// Unregister a work area before discard it f_mount(0, NULL); } и стало писаться с в только что созданный файл, и размер файла не ограничен. Ничего не понимаю, в чём дело? Что за танцы с бубном?
Сообщение отредактировал IgorKossak - May 4 2011, 14:14
Причина редактирования: [codebox] !!!
|
|
|
|
|
 |
Ответов
(1 - 9)
|
May 4 2011, 09:07
|
Частый гость
 
Группа: Участник
Сообщений: 109
Регистрация: 19-01-11
Пользователь №: 62 335

|
Цитата Файл не пишется размером больше 4033 байт. Быть такого не может. Я использую ту же библиотеку что и Вы, все нормально Вот пример использования FATfs от ATMEL надеюсь он Вам поможет. CODE #include <stdio.h> #include <string.h> #include <board.h> #include <utility/trace.h> #include <utility/assert.h> #include <utility/math.h> #include <memories/MEDSdcard.h>
#include "fatfs_config.h" #if _FATFS_TINY != 1 #include <fatfs/src/ff.h> #else #include <fatfs/src/tff.h> #endif #include <fatfs/src/ff_util.h>
//------------------------------------------------------------------------------ // Local constants //------------------------------------------------------------------------------
/// Maximum number of LUNs which can be defined. /// (Logical drive = physical drive = medium number) #define MAX_LUNS 1
/// Available medias. Media medias[MAX_LUNS];
//------------------------------------------------------------------------------ // Local variables //------------------------------------------------------------------------------
#define ID_DRV DRV_MMC
#if _FATFS_TINY == 0 #define STR_ROOT_DIRECTORY "0:" #else #define STR_ROOT_DIRECTORY "" #endif
#if defined(at91cap9stk) #define MCI_ID 1 //no connector for MCIO/SPI0 #else #define MCI_ID 0 #endif
const char* FileName = STR_ROOT_DIRECTORY "Basic.bin";
#if 0 //Bigger than this value will cause SD HC error now. //#define DATA_SIZE (7*1024 + 512) #define DATA_SIZE (9*1024) //unsigned char data[DATA_SIZE]; unsigned char * data = (unsigned char*)0x60000400; #else #define DATA_SIZE 2064 // size of the file to write/read // !!!minimum size 512 for erase operation !!!
unsigned char data[DATA_SIZE]; #endif
//------------------------------------------------------------------------------ // Local functions //------------------------------------------------------------------------------
//------------------------------------------------------------------------------ /// Do file system tests /// \return test result, 1: success. //------------------------------------------------------------------------------ static unsigned char RunFsTest(void) { unsigned int i; unsigned int ByteToRead; unsigned int ByteRead; #if _FATFS_TINY == 0 unsigned int ByteWritten; char key; #endif
FRESULT res; DIR dirs; FATFS fs; // File system object FIL FileObject;
// Init Disk printf("-I- Please connect a SD card ...\n\r"); while(!MEDSdcard_Detect(&medias[ID_DRV], MCI_ID)); printf("-I- SD card connection detected\n\r");
printf("-I- Init media Sdcard\n\r"); if (!MEDSdcard_Initialize(&medias[ID_DRV], MCI_ID)) { printf("-E- SD Init fail\n\r"); return 0; } numMedias = 1;
// Mount disk printf("-I- Mount disk %d\n\r", ID_DRV); memset(&fs, 0, sizeof(FATFS)); // Clear file system object res = f_mount(ID_DRV, &fs); if( res != FR_OK ) { printf("-E- f_mount pb: 0x%X (%s)\n\r", res, FF_GetStrResult(res)); return 0; }
// Test if the disk is formated res = f_opendir (&dirs,STR_ROOT_DIRECTORY); if(res == FR_OK ){
// erase sdcard to re-format it ? printf("-I- The disk is already formated.\n\r");
// Display the file tree printf("-I- Display files contained on the SDcard :\n\r"); FF_ScanDir(STR_ROOT_DIRECTORY);
#if _FATFS_TINY == 0 printf("-I- Do you want to erase the sdcard to re-format disk ? (y/n)!\n\r");
key = DBGU_GetChar(); if( (key == 'y') || (key == 'Y')) { for(i=0;i<100;i++) { MEDSdcard_EraseBlock(&medias[ID_DRV], i); } printf("-I- Erase the first 100 blocks complete !\n\r"); res = FR_NO_FILESYSTEM; } #endif }
if( res == FR_NO_FILESYSTEM ) {
#if _FATFS_TINY == 0 //printf("-I- Press 'y' to start format:\n\r"); //if (DBGU_GetChar() != 'y') return 0; // Format disk printf("-I- Format disk %d\n\r", ID_DRV); printf("-I- Please wait a moment during formating...\n\r"); res = f_mkfs(ID_DRV, // Drv 0, // FDISK partition 512); // AllocSize printf("-I- Format disk finished !\n\r"); if( res != FR_OK ) { printf("-E- f_mkfs pb: 0x%X (%s)\n\r", res, FF_GetStrResult(res)); return 0; } #else printf("-I- Please run Full version FAT FS test first\n\r"); return 0; #endif }
#if _FATFS_TINY == 0 // Create a new file printf("-I- Create a file : \"%s\"\n\r", FileName); res = f_open(&FileObject, FileName, FA_CREATE_ALWAYS|FA_WRITE); if( res != FR_OK ) { printf("-E- f_open create pb: 0x%X (%s)\n\r", res, FF_GetStrResult(res)); return 0; }
// Write a checkerboard pattern in the buffer for (i=0; i < sizeof(data); i++) { if ((i & 1) == 0) { data[i] = (i & 0x55); } else { data[i] = (i & 0xAA); } } printf("-I- Write file\n\r"); res = f_write(&FileObject, data, DATA_SIZE, &ByteWritten); printf("-I- ByteWritten=%d\n\r", (int)ByteWritten); if( res != FR_OK ) { printf("-E- f_write pb: 0x%X (%s)\n\r", res, FF_GetStrResult(res)); return 0; } else { printf("-I- f_write ok: ByteWritten=%d\n\r", (int)ByteWritten); }
// Close the file printf("-I- Close file\n\r"); res = f_close(&FileObject); if( res != FR_OK ) { printf("-E- f_close pb: 0x%X (%s)\n\r", res, FF_GetStrResult(res)); return 0; } #endif
// Open the file printf("-I- Open the same file : \"%s\"\n\r", FileName); res = f_open(&FileObject, FileName, FA_OPEN_EXISTING|FA_READ); if( res != FR_OK ) { printf("-E- f_open read pb: 0x%X (%s)\n\r", res, FF_GetStrResult(res)); return 0; } ASSERT( FileObject.fsize == DATA_SIZE, "File size value not expected!\n\r");
// Read file printf("-I- Read file\n\r"); memset(data, 0, DATA_SIZE); ByteToRead = FileObject.fsize; res = f_read(&FileObject, data, ByteToRead, &ByteRead); if(res != FR_OK) { printf("-E- f_read pb: 0x%X (%s)\n\r", res, FF_GetStrResult(res)); return 0; }
// Close the file printf("-I- Close file\n\r"); res = f_close(&FileObject); if( res != FR_OK ) { printf("-E- f_close pb: 0x%X (%s)\n\r", res, FF_GetStrResult(res)); return 0; }
// compare read data with the expected data for (i=0; i < sizeof(data); i++) { ASSERT((((i & 1) == 0) && (data[i] == (i & 0x55))) || (data[i] == (i & 0xAA)), "Invalid data at data[%u] (expected 0x%02X, read 0x%02X)\n\r", i, ((i & 1) == 0) ? (i & 0x55) : (i & 0xAA), data[i]); } printf("-I- File data Ok !\n\r");
return 1; }
//------------------------------------------------------------------------------ // Global functions //------------------------------------------------------------------------------
//------------------------------------------------------------------------------ /// main /// FatFs Full version //------------------------------------------------------------------------------ int main( void ) { TRACE_CONFIGURE(DBGU_STANDARD, 115200, BOARD_MCK); printf("-- Basic FatFS Full Version with SDCard Project %s --\n\r", SOFTPACK_VERSION); printf("-- %s\n\r", BOARD_NAME); printf("-- Compiled: %s %s --\n\r", __DATE__, __TIME__);
while(1) { if (RunFsTest()) { printf("-I- Test passed !\n\r"); } else { printf("-F- Test Failed !\n\r"); } SD_Stop(MEDSdcard_GetDriver(MCI_ID), MEDSdcard_GetDriver(MCI_ID)->pSdDriver);
printf("\n\r** any key to start test again **\n\r"); DBGU_GetChar(); }
return 0; }
Сообщение отредактировал IgorKossak - May 4 2011, 14:15
Причина редактирования: [codebox] !!!
|
|
|
|
|
May 5 2011, 03:59
|
Участник

Группа: Свой
Сообщений: 72
Регистрация: 4-02-05
Пользователь №: 2 424

|
Сделал вот так: CODE
static FATFS fs; // Work area (file system object) for logical drives static FIL fdst, data_file; // file objects
void proba () { volatile FRESULT res; // FatFs function common result code UINT br, bw; // File read/write count uint8_t str_cnt = 0;
// Register a work area for logical drive 0 f_mount(0, &fs);
// Открываем файл res = f_open(&data_file, "test_cpy.txt", FA_OPEN_ALWAYS | FA_READ | FA_WRITE); if(res) { res = res; }
buffer[0] = 'A'; buffer[1] = 'B'; buffer[2] = 'C'; buffer[3] = 'D'; buffer[4] = 'E';
for(str_cnt = 0; str_cnt < 10; str_cnt++) { res = f_lseek(&data_file, data_file.fsize); br = 5; res = f_write(&data_file, buffer, br, &bw); if(res) { res = res; } f_puts ("Proba \r\n", &data_file); f_sync (&data_file); }
//--------------------------------------------------------------------------------- // Вот этот блок добавил fdst = fdst; //---------------------------------------------------------------------------------
f_close(&data_file);
// Unregister a work area before discard it f_mount(0, NULL); }
Вот только не понятно, почему если оставить неиспользуемый fdst , то всё работает, если его закомментировать, то опять с начала файла не пишет, и размер файла не больше 4033 байт. (забыл сказать , компилятор IAR ARM, FreeRTOS) размер стека увеличивал, не помогает... что такое может быть?
|
|
|
|
|
May 5 2011, 07:31
|
Участник

Группа: Свой
Сообщений: 72
Регистрация: 4-02-05
Пользователь №: 2 424

|
Так вот если файл не нулевого размера, эти функции работают же. Файл пишется. Поэтому на них вроде и не думаю. Понятно, что ошибка где то у меня, не понятно только где..
|
|
|
|
|
May 5 2011, 10:56
|
Профессионал
    
Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007

|
На мой взгляд, должно быть что-то типа: CODE void proba () { volatile FRESULT res; // FatFs function common result code UINT br, bw; // File read/write count uint8_t str_cnt = 0; static FATFS fs; // Work area (file system object) for logical drives static FIL fdst, data_file; // file objects // Register a work area for logical drive 0 f_mount(0, &fs); res = f_open(&data_file, "test_cpy.txt", FA_OPEN_ALWAYS | FA_READ | FA_WRITE); if(res != FR_OK) { printf("ERR : %d\n", res); f_close(&data_file); return; } buffer[0] = 'A'; buffer[1] = 'B'; buffer[2] = 'C'; buffer[3] = 'D'; buffer[4] = 'E'; if(data_file.fsize) res = f_lseek(&data_file, data_file.fsize); // goto to the end of file only, // if file exist if(res != FR_OK) { printf("ERR : %d\n", res); f_close(&data_file); return; } for(str_cnt = 0; str_cnt < 10; str_cnt++) { res = f_write(&data_file, buffer, 5, &bw); if(res != FR_OK) { printf("ERR : %d\n", res); f_close(&data_file); return; } f_puts("Proba \r\n", &data_file); } f_close(&data_file); // Unregister a work area before discard it f_mount(0, NULL); }
Сообщение отредактировал IgorKossak - May 5 2011, 12:19
Причина редактирования: [codebox] !!!
|
|
|
|
|
May 6 2011, 06:38
|
Участник

Группа: Свой
Сообщений: 72
Регистрация: 4-02-05
Пользователь №: 2 424

|
Спасибо, Ваш пример работает. Переработал свой код по образу и подобию, тоже заработало. Спасибо!
|
|
|
|
|
Jun 23 2011, 13:26
|
Группа: Новичок
Сообщений: 4
Регистрация: 1-12-08
Пользователь №: 42 111

|
Цитата(Artem @ May 6 2011, 09:38)  Спасибо, Ваш пример работает. Переработал свой код по образу и подобию, тоже заработало. Спасибо! Artem, добрый день. У меня аналогичный набор (stm32+fatfs+freertos) и абсолютно та же проблема. При этом я ранее реализовывал эту связку на более старшем проце, только там был SDIO, а не SPI как здесь. Вроде делаю все как у вас заработало - у меня эффект ноль. Можете скинуть ваши исходники относительно Fatfs (ff.c diskio.c и т.п.) на мыло dimasusl@gmail.com? Цитата(dimasusl @ Jun 23 2011, 16:00)  Artem, добрый день. У меня аналогичный набор (stm32+fatfs+freertos) и абсолютно та же проблема. При этом я ранее реализовывал эту связку на более старшем проце, только там был SDIO, а не SPI как здесь. Вроде делаю все как у вас заработало - у меня эффект ноль. Можете скинуть ваши исходники относительно Fatfs (ff.c diskio.c и т.п.) на мыло dimasusl@gmail.com? Блин, занятное дело... Был код Код res = f_mount(0, &fs); res = f_open(&fsrc, "spi1.txt", FA_OPEN_ALWAYS | FA_READ | FA_WRITE ); if (fsrc.fsize) res = f_lseek(&fsrc, fsrc.fsize); res = f_write(&fsrc, usb_buffer, sizeof(usb_buffer), &br); res = f_close(&fsrc); res = f_mount(0, NULL); Файл создавался, но данные в него не писались (если сделать ненулевой размер файла то все Ок). Подсмотрел тут что еще юзаете для своих целей f_puts(...) Код res = f_mount(0, &fs); res = f_open(&fsrc, "spi1.txt", FA_OPEN_ALWAYS | FA_READ | FA_WRITE ); if (fsrc.fsize) res = f_lseek(&fsrc, fsrc.fsize); res = f_puts("",&fsrc); // Пустая строка, чтобы не "ломать" формат файла res = f_write(&fsrc, usb_buffer, sizeof(usb_buffer), &br); res = f_close(&fsrc); res = f_mount(0, NULL); и стало все Ок и при нулевом размере файла. Откуда ноги растут так и не ясно
|
|
|
|
|
Jun 24 2011, 06:02
|
Участник

Группа: Свой
Сообщений: 72
Регистрация: 4-02-05
Пользователь №: 2 424

|
Добрый день. У меня проблема была с файлом sdc_diskio.c (низкоуровневые функции работы с SD). А если ещё точнее, то проблема была с функцией Receive_DataBlock. Получалось, что я при чтении вылезал за область памяти прёмного буфера, и при этом портил структуру fs. После устранения, проблемы исчезли.
PS. Письмо отправил
|
|
|
|
|
Jun 24 2011, 06:35
|
Группа: Новичок
Сообщений: 4
Регистрация: 1-12-08
Пользователь №: 42 111

|
Цитата(Artem @ Jun 24 2011, 09:02)  Добрый день. У меня проблема была с файлом sdc_diskio.c (низкоуровневые функции работы с SD). А если ещё точнее, то проблема была с функцией Receive_DataBlock. Получалось, что я при чтении вылезал за область памяти прёмного буфера, и при этом портил структуру fs. После устранения, проблемы исчезли.
PS. Письмо отправил Ответил на мыло, но напишу и тут, вдруг кому будет полезно Код static BOOL Receive_DataBlock( BYTE *buff, /* Data buffer to store received data */ UINT btr /* Byte count (must be multiple of 4) */ ) { BYTE token; MMC_SELECT(); // !!!!!!!!!! ДОБАВИЛ ЭТО !!!!!!!!!!!!!!!! Timer1 = 10; do { /* Wait for data packet in timeout of 100ms */ token = SPI_ReadWrite_Byte(0xff); } while ((token == 0xFF) && Timer1); if(token != 0xFE) return FALSE; /* If not valid data token, retutn with error */
btr--; //!!!!!!!!!! И ДОБАВИЛ ЭТО !!!!!!!!!! do { /* Receive the data block into buffer */ *buff++ = SPI_ReadWrite_Byte(0xff); } while (btr--); SPI_ReadWrite_Byte(0xff); /* Discard CRC */ SPI_ReadWrite_Byte(0xff);
return TRUE; /* Return with success */ }
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|