Перейти к содержанию
    

FATfs и SD-карта

Доброго времени суток! Микроконтроллер STM32 работает с SD картой по SPI. Прицеплена FATfs. Необходимо открыть файл для записи, если файла нет, то создать его и в него записать строку. Но вот в чём проблема, если в файле уже есть хоть один символ, то запись проходит успешно, а если файл только что создали, т.е. его размер равен 0 , то запись не происходит, f_write возвращает FR_INT_ERR. Не могу понять в чём проблема... Помогите кто чем может.. Заранее спасибо.

Вот код:

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 байт.

 

 

Сделал вот так:

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
[codebox] !!!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Файл не пишется размером больше 4033 байт.

 

Быть такого не может. Я использую ту же библиотеку что и Вы, все нормально

 

 

Вот пример использования FATfs от ATMEL надеюсь он Вам поможет.

#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
[codebox] !!!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Сделал вот так:


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) размер стека увеличивал, не помогает...

что такое может быть?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Учитывая, что сам FatFS пользуют, неверное, миллионы программистов и она работает, проблема, скорее всего, в той части, которую вы сами к этой библиотеке "прикрутили" - функции физического чтения/записи сектора. Ва бы их внимательно проверили и отладили до FatFS.

 

 

Во-вторых, может вы можете свой тест запустить не под FreeDOS? Тогда тоже многое может проясниться.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Так вот если файл не нулевого размера, эти функции работают же. Файл пишется. Поэтому на них вроде и не думаю. Понятно, что ошибка где то у меня, не понятно только где..

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

На мой взгляд, должно быть что-то типа:

 

 

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
[codebox] !!!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Спасибо, Ваш пример работает. Переработал свой код по образу и подобию, тоже заработало. Спасибо!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Спасибо, Ваш пример работает. Переработал свой код по образу и подобию, тоже заработало. Спасибо!

Artem, добрый день. У меня аналогичный набор (stm32+fatfs+freertos) и абсолютно та же проблема. При этом я ранее реализовывал эту связку на более старшем проце, только там был SDIO, а не SPI как здесь. Вроде делаю все как у вас заработало - у меня эффект ноль. Можете скинуть ваши исходники относительно Fatfs (ff.c diskio.c и т.п.) на мыло [email protected]?

 

Artem, добрый день. У меня аналогичный набор (stm32+fatfs+freertos) и абсолютно та же проблема. При этом я ранее реализовывал эту связку на более старшем проце, только там был SDIO, а не SPI как здесь. Вроде делаю все как у вас заработало - у меня эффект ноль. Можете скинуть ваши исходники относительно Fatfs (ff.c diskio.c и т.п.) на мыло [email protected]?

Блин, занятное дело...

 

Был код

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);

и стало все Ок и при нулевом размере файла. Откуда ноги растут так и не ясно

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Добрый день. У меня проблема была с файлом sdc_diskio.c (низкоуровневые функции работы с SD). А если ещё точнее, то проблема была с функцией Receive_DataBlock. Получалось, что я при чтении вылезал за область памяти прёмного буфера, и при этом портил структуру fs. После устранения, проблемы исчезли.

 

PS. Письмо отправил

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Добрый день. У меня проблема была с файлом 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 */
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...