Последняя версия библиотеки FATFS, взятая отсюда.
Keil uVision 4 в качестве среды.
JetLink8 программатор.
SD на 4Gb.
Собственно в документации к FATFS написано, что в diskio.c надо реализовать I/O уровень.
Реализовала.
На чтение FATFS работает прекрасно.
А вот на записи начинается абсолютно непонятный мне космос.
Если выполнить f_write без отладчика, кидает FR_DISK_ERR и отваливается.
Если с отладчиком если пошагово трасировать f_write, записывает все, f_eof говорит, что файл имеет метку окончания, f_size отдает правильный размер, но когда вставляю в компьютер, машина сообщает, что файл битый.
Бьюсь уже который час, святые макароны знают, в чем дело.
SD_DMA_MODE закоменчен, раскоменчен SD_POLLING_MODE.
Собственно, discio.c
CODE
/*-----------------------------------------------------------------------*/
/* Low level disk I/O module skeleton for FatFs ©ChaN, 2007 */
/*-----------------------------------------------------------------------*/
/* by grqd_xp */
/* This is a stub disk I/O module that acts as front end of the existing */
/* disk I/O modules and attach it to FatFs module with common interface. */
/*-----------------------------------------------------------------------*/
/* by nemui trinomius */
/* adopted to STM32F2xx_StdPeriph_Driver V1.0.0. */
/*-----------------------------------------------------------------------*/
#include <string.h>
#include <stdio.h>
#include "stm32_eval_sdio_sd.h"
#include "diskio.h"
/*-----------------------------------------------------------------------*/
/* Correspondence between physical drive number and physical drive. */
/* Note that Tiny-FatFs supports only single drive and always */
/* accesses drive number 0. */
#define SECTOR_SIZE 512
static SD_Error Status = SD_OK;
static SD_CardInfo SDCardInfo;
/*-----------------------------------------------------------------------*/
/* Correspondence between physical drive number and physical drive. */
#define SDIO_DRIVE 0
/*-----------------------------------------------------------------------*/
/* Initialize a Drive */
DSTATUS disk_initialize (
BYTE drv /* Physical drive nmuber (0..) */
)
{
switch (drv)
{
case SDIO_DRIVE:
{
/* Initialize SD Card */
Status = SD_Init();
if (Status != SD_OK)
return STA_NOINIT;
else
return 0x00;
}
}
return STA_NOINIT;
}
/*-----------------------------------------------------------------------*/
/* Return Disk Status */
DSTATUS disk_status (
BYTE drv /* Physical drive nmuber (0..) */
)
{
switch (drv)
{
case SDIO_DRIVE:
{
Status = SD_GetCardInfo(&SDCardInfo);
if (Status != SD_OK)
return STA_NOINIT;
else
return 0x00;
}
}
return STA_NOINIT;
}
/*-----------------------------------------------------------------------*/
/* Read Sector(s) */
DRESULT disk_read (
BYTE drv, /* Physical drive nmuber (0..) */
BYTE *buff, /* Data buffer to store read data */
DWORD sector, /* Sector address (LBA) */
BYTE count /* Number of sectors to read (1..255) */
)
{
switch (drv)
{
case SDIO_DRIVE:
{
Status = SD_OK;
#if defined(SD_DMA_MODE) /* DMA Transfer */
/* Read Multiple Blocks */
Status = SD_ReadMultiBlocks((uint8_t*)(buff),(sector)*SECTOR_SIZE,SECTOR_SIZE,count);
/* Check if the Transfer is finished */
Status = SD_WaitReadOperation();
/* Wait until end of DMA transfer */
while(SD_GetStatus() != SD_TRANSFER_OK);
#else /* Polling Transfer */
for (int secNum = 0; (secNum < count) && (Status == SD_OK); secNum++)
{
Status = SD_ReadBlock((buff+SECTOR_SIZE*secNum),
(sector+secNum)*SECTOR_SIZE,
SECTOR_SIZE);
}
#endif
if (Status == SD_OK) return RES_OK;
else return RES_ERROR;
}
}
return RES_PARERR;
}
/*-----------------------------------------------------------------------*/
/* Write Sector(s) */
#if _READONLY == 0
DRESULT disk_write (
BYTE drv, /* Physical drive nmuber (0..) */
const BYTE *buff, /* Data to be written */
DWORD sector, /* Sector address (LBA) */
BYTE count /* Number of sectors to write (1..255) */
)
{
switch (drv)
{
case SDIO_DRIVE:
{
Status = SD_OK;
#if defined(SD_DMA_MODE) /* DMA Transfer */
/* Write Multiple Blocks */
Status = SD_WriteMultiBlocks((uint8_t*)(buff),(sector)*SECTOR_SIZE,SECTOR_SIZE,count);
/* Check if the Transfer is finished */
Status = SD_WaitWriteOperation();
/* Wait until end of DMA transfer */
while(SD_GetStatus() != SD_TRANSFER_OK);
#else /* Polling Transfer */
for (int secNum = 0; (secNum < count) && (Status == SD_OK); secNum++)
{
Status = SD_WriteBlock((uint8_t *) buff+SECTOR_SIZE*secNum,
(sector+secNum)*SECTOR_SIZE,
SECTOR_SIZE);
}
#endif
if (Status == SD_OK) return RES_OK;
else return RES_ERROR;
}
}
return RES_PARERR;
}
#endif /* _READONLY */
/*-----------------------------------------------------------------------*/
/* Miscellaneous Functions */
DRESULT disk_ioctl (
BYTE drv, /* Physical drive nmuber (0..) */
BYTE ctrl, /* Control code */
void *buff /* Buffer to send/receive control data */
)
{
switch (drv)
{
case SDIO_DRIVE:
{
switch (ctrl)
{
case CTRL_SYNC:
/* no synchronization to do since not buffering in this module */
return RES_OK;
case GET_SECTOR_SIZE:
*(WORD*)buff = SECTOR_SIZE;
return RES_OK;
case GET_SECTOR_COUNT:
*(DWORD*)buff = SDCardInfo.CardCapacity / SECTOR_SIZE;
return RES_OK;
case GET_BLOCK_SIZE:
*(DWORD*)buff = SECTOR_SIZE;
return RES_OK;
}
}
}
return RES_PARERR;
}
DWORD get_fattime (void)
{
DWORD res;
RTC_TimeTypeDef RTC_TimeStructure;
RTC_DateTypeDef RTC_DateStructure;
RTC_GetTime(RTC_Format_BIN, &RTC_TimeStructure);
RTC_GetDate(RTC_Format_BIN, &RTC_DateStructure);
res = (((DWORD)RTC_DateStructure.RTC_Year + 20) << 25)
| ((DWORD)RTC_DateStructure.RTC_Month << 21)
| ((DWORD)RTC_DateStructure.RTC_Date << 16)
| (WORD)(RTC_TimeStructure.RTC_Hours << 11)
| (WORD)(RTC_TimeStructure.RTC_Minutes << 5)
| (WORD)(RTC_TimeStructure.RTC_Seconds >> 1);
return res;
}
/* Low level disk I/O module skeleton for FatFs ©ChaN, 2007 */
/*-----------------------------------------------------------------------*/
/* by grqd_xp */
/* This is a stub disk I/O module that acts as front end of the existing */
/* disk I/O modules and attach it to FatFs module with common interface. */
/*-----------------------------------------------------------------------*/
/* by nemui trinomius */
/* adopted to STM32F2xx_StdPeriph_Driver V1.0.0. */
/*-----------------------------------------------------------------------*/
#include <string.h>
#include <stdio.h>
#include "stm32_eval_sdio_sd.h"
#include "diskio.h"
/*-----------------------------------------------------------------------*/
/* Correspondence between physical drive number and physical drive. */
/* Note that Tiny-FatFs supports only single drive and always */
/* accesses drive number 0. */
#define SECTOR_SIZE 512
static SD_Error Status = SD_OK;
static SD_CardInfo SDCardInfo;
/*-----------------------------------------------------------------------*/
/* Correspondence between physical drive number and physical drive. */
#define SDIO_DRIVE 0
/*-----------------------------------------------------------------------*/
/* Initialize a Drive */
DSTATUS disk_initialize (
BYTE drv /* Physical drive nmuber (0..) */
)
{
switch (drv)
{
case SDIO_DRIVE:
{
/* Initialize SD Card */
Status = SD_Init();
if (Status != SD_OK)
return STA_NOINIT;
else
return 0x00;
}
}
return STA_NOINIT;
}
/*-----------------------------------------------------------------------*/
/* Return Disk Status */
DSTATUS disk_status (
BYTE drv /* Physical drive nmuber (0..) */
)
{
switch (drv)
{
case SDIO_DRIVE:
{
Status = SD_GetCardInfo(&SDCardInfo);
if (Status != SD_OK)
return STA_NOINIT;
else
return 0x00;
}
}
return STA_NOINIT;
}
/*-----------------------------------------------------------------------*/
/* Read Sector(s) */
DRESULT disk_read (
BYTE drv, /* Physical drive nmuber (0..) */
BYTE *buff, /* Data buffer to store read data */
DWORD sector, /* Sector address (LBA) */
BYTE count /* Number of sectors to read (1..255) */
)
{
switch (drv)
{
case SDIO_DRIVE:
{
Status = SD_OK;
#if defined(SD_DMA_MODE) /* DMA Transfer */
/* Read Multiple Blocks */
Status = SD_ReadMultiBlocks((uint8_t*)(buff),(sector)*SECTOR_SIZE,SECTOR_SIZE,count);
/* Check if the Transfer is finished */
Status = SD_WaitReadOperation();
/* Wait until end of DMA transfer */
while(SD_GetStatus() != SD_TRANSFER_OK);
#else /* Polling Transfer */
for (int secNum = 0; (secNum < count) && (Status == SD_OK); secNum++)
{
Status = SD_ReadBlock((buff+SECTOR_SIZE*secNum),
(sector+secNum)*SECTOR_SIZE,
SECTOR_SIZE);
}
#endif
if (Status == SD_OK) return RES_OK;
else return RES_ERROR;
}
}
return RES_PARERR;
}
/*-----------------------------------------------------------------------*/
/* Write Sector(s) */
#if _READONLY == 0
DRESULT disk_write (
BYTE drv, /* Physical drive nmuber (0..) */
const BYTE *buff, /* Data to be written */
DWORD sector, /* Sector address (LBA) */
BYTE count /* Number of sectors to write (1..255) */
)
{
switch (drv)
{
case SDIO_DRIVE:
{
Status = SD_OK;
#if defined(SD_DMA_MODE) /* DMA Transfer */
/* Write Multiple Blocks */
Status = SD_WriteMultiBlocks((uint8_t*)(buff),(sector)*SECTOR_SIZE,SECTOR_SIZE,count);
/* Check if the Transfer is finished */
Status = SD_WaitWriteOperation();
/* Wait until end of DMA transfer */
while(SD_GetStatus() != SD_TRANSFER_OK);
#else /* Polling Transfer */
for (int secNum = 0; (secNum < count) && (Status == SD_OK); secNum++)
{
Status = SD_WriteBlock((uint8_t *) buff+SECTOR_SIZE*secNum,
(sector+secNum)*SECTOR_SIZE,
SECTOR_SIZE);
}
#endif
if (Status == SD_OK) return RES_OK;
else return RES_ERROR;
}
}
return RES_PARERR;
}
#endif /* _READONLY */
/*-----------------------------------------------------------------------*/
/* Miscellaneous Functions */
DRESULT disk_ioctl (
BYTE drv, /* Physical drive nmuber (0..) */
BYTE ctrl, /* Control code */
void *buff /* Buffer to send/receive control data */
)
{
switch (drv)
{
case SDIO_DRIVE:
{
switch (ctrl)
{
case CTRL_SYNC:
/* no synchronization to do since not buffering in this module */
return RES_OK;
case GET_SECTOR_SIZE:
*(WORD*)buff = SECTOR_SIZE;
return RES_OK;
case GET_SECTOR_COUNT:
*(DWORD*)buff = SDCardInfo.CardCapacity / SECTOR_SIZE;
return RES_OK;
case GET_BLOCK_SIZE:
*(DWORD*)buff = SECTOR_SIZE;
return RES_OK;
}
}
}
return RES_PARERR;
}
DWORD get_fattime (void)
{
DWORD res;
RTC_TimeTypeDef RTC_TimeStructure;
RTC_DateTypeDef RTC_DateStructure;
RTC_GetTime(RTC_Format_BIN, &RTC_TimeStructure);
RTC_GetDate(RTC_Format_BIN, &RTC_DateStructure);
res = (((DWORD)RTC_DateStructure.RTC_Year + 20) << 25)
| ((DWORD)RTC_DateStructure.RTC_Month << 21)
| ((DWORD)RTC_DateStructure.RTC_Date << 16)
| (WORD)(RTC_TimeStructure.RTC_Hours << 11)
| (WORD)(RTC_TimeStructure.RTC_Minutes << 5)
| (WORD)(RTC_TimeStructure.RTC_Seconds >> 1);
return res;
}
И main.c:
CODE
int main(void)
{
USART_InitStructure.USART_BaudRate = 115200;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
STM_EVAL_COMInit(COM1, &USART_InitStructure);
Init_RTC();
/* Output a message on Hyperterminal using printf function */
printf("\n\rTest FATFS Lib for STM32F217\n\r");
fStatus = f_mount(DISC_LOGIC_NUMB, &fatfs);
printf("f_mount result: %i\r\n", fStatus);
if (fStatus == 0x00)
{
printf("Test read file.\r\n");
fStatus = f_open(&f, "test1.txt", FA_OPEN_EXISTING | FA_READ);
printf("f_open result: %i\r\n", fStatus);
if (fStatus == 0)
{
printf("f_size result: %i\r\n", f_size(&f));
char p[f_size(&f) + 1];
memset(p, 0, f_size(&f) + 1);
fStatus = f_read(&f, (void *) p, f_size(&f), &uiStatus);
printf("f_read result: fStatus: %i; uiStatus: %i;\r\n", fStatus, uiStatus);
fStatus = f_close(&f);
if (uiStatus > 0)
{
printf("Read data: %s\r\n", p);
printf("f_close result: %i\r\n", fStatus);
printf("Test write file.\r\n");
fStatus = f_open(&f, "0:test2.txt", FA_CREATE_ALWAYS | FA_WRITE);
printf("f_open result: %i\r\n", fStatus);
if (fStatus == 0)
{
printf("f_size result: %i\r\n", f_size(&f));
fStatus = f_write(&f, "Hello world!\r\n", strlen("Hello world!\r\n") + 1, &uiStatus);
printf("f_write result: fStatus: %i; uiStatus: %i;\r\n", fStatus, uiStatus);
printf("f_eof result: %i.\r\n", f_eof(&f));
if (fStatus > 0)
{
fStatus = f_unlink("test2.txt");
printf("f_ulink result: %i\r\n", fStatus);
}
printf("f_size result: %i\r\n", f_size(&f));
}
f_sync(&f);
fStatus = f_close(&f);
}
fStatus = f_mount(DISC_LOGIC_NUMB, NULL);
printf("f_unmount result: %i\r\n", fStatus);
}
SDIO_DeInit();
}
while (1)
{
}
}
{
USART_InitStructure.USART_BaudRate = 115200;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
STM_EVAL_COMInit(COM1, &USART_InitStructure);
Init_RTC();
/* Output a message on Hyperterminal using printf function */
printf("\n\rTest FATFS Lib for STM32F217\n\r");
fStatus = f_mount(DISC_LOGIC_NUMB, &fatfs);
printf("f_mount result: %i\r\n", fStatus);
if (fStatus == 0x00)
{
printf("Test read file.\r\n");
fStatus = f_open(&f, "test1.txt", FA_OPEN_EXISTING | FA_READ);
printf("f_open result: %i\r\n", fStatus);
if (fStatus == 0)
{
printf("f_size result: %i\r\n", f_size(&f));
char p[f_size(&f) + 1];
memset(p, 0, f_size(&f) + 1);
fStatus = f_read(&f, (void *) p, f_size(&f), &uiStatus);
printf("f_read result: fStatus: %i; uiStatus: %i;\r\n", fStatus, uiStatus);
fStatus = f_close(&f);
if (uiStatus > 0)
{
printf("Read data: %s\r\n", p);
printf("f_close result: %i\r\n", fStatus);
printf("Test write file.\r\n");
fStatus = f_open(&f, "0:test2.txt", FA_CREATE_ALWAYS | FA_WRITE);
printf("f_open result: %i\r\n", fStatus);
if (fStatus == 0)
{
printf("f_size result: %i\r\n", f_size(&f));
fStatus = f_write(&f, "Hello world!\r\n", strlen("Hello world!\r\n") + 1, &uiStatus);
printf("f_write result: fStatus: %i; uiStatus: %i;\r\n", fStatus, uiStatus);
printf("f_eof result: %i.\r\n", f_eof(&f));
if (fStatus > 0)
{
fStatus = f_unlink("test2.txt");
printf("f_ulink result: %i\r\n", fStatus);
}
printf("f_size result: %i\r\n", f_size(&f));
}
f_sync(&f);
fStatus = f_close(&f);
}
fStatus = f_mount(DISC_LOGIC_NUMB, NULL);
printf("f_unmount result: %i\r\n", fStatus);
}
SDIO_DeInit();
}
while (1)
{
}
}
Вывод платы без отладчика:
CODE
Test FATFS Lib for STM32F217
f_mount result: 0
Test read file.
f_open result: 0
f_size result: 14
f_read result: fStatus: 0; uiStatus: 14;
Read data: Hello world!
f_close result: 0
Test write file.
f_open result: 0
f_size result: 0
f_write result: fStatus: 1; uiStatus: 0;
f_eof result: 1.
f_ulink result: 1
f_size result: 0
f_unmount result: 0
f_mount result: 0
Test read file.
f_open result: 0
f_size result: 14
f_read result: fStatus: 0; uiStatus: 14;
Read data: Hello world!
f_close result: 0
Test write file.
f_open result: 0
f_size result: 0
f_write result: fStatus: 1; uiStatus: 0;
f_eof result: 1.
f_ulink result: 1
f_size result: 0
f_unmount result: 0
С отладчиком:
CODE
Test FATFS Lib for STM32F217
f_mount result: 0
Test read file.
f_open result: 0
f_size result: 14
f_read result: fStatus: 0; uiStatus: 14;
Read data: Hello world!
f_close result: 0
Test write file.
f_open result: 0
f_size result: 0
f_write result: fStatus: 0; uiStatus: 15;
f_eof result: 1.
f_size result: 15
f_unmount result: 0
f_mount result: 0
Test read file.
f_open result: 0
f_size result: 14
f_read result: fStatus: 0; uiStatus: 14;
Read data: Hello world!
f_close result: 0
Test write file.
f_open result: 0
f_size result: 0
f_write result: fStatus: 0; uiStatus: 15;
f_eof result: 1.
f_size result: 15
f_unmount result: 0
Пошерстив сей прекрасный форум и поняв, что дурак я, немного полазив отладчиком подправила disk_write и disk_read.
CODE
/*-----------------------------------------------------------------------*/
/* Read Sector(s) */
DRESULT disk_read (
BYTE drv, /* Physical drive nmuber (0..) */
BYTE *buff, /* Data buffer to store read data */
DWORD sector, /* Sector address (LBA) */
BYTE count /* Number of sectors to read (1..255) */
)
{
/* ................................................................................
...............................*/
for (int secNum = 0; (secNum < count) && (Status == SD_OK); secNum++)
{
Status = SD_ReadBlock((buff+SECTOR_SIZE*secNum),
(sector+secNum)*SECTOR_SIZE,
SECTOR_SIZE);
while(SD_GetStatus() != SD_TRANSFER_OK);
}
/* ................................................................................
...............................*/
}
/*-----------------------------------------------------------------------*/
/* Write Sector(s) */
#if _READONLY == 0
DRESULT disk_write (
BYTE drv, /* Physical drive nmuber (0..) */
const BYTE *buff, /* Data to be written */
DWORD sector, /* Sector address (LBA) */
BYTE count /* Number of sectors to write (1..255) */
)
{
/* ................................................................................
...............................*/
for (int secNum = 0; (secNum < count) && (Status == SD_OK); secNum++)
{
Status = SD_WriteBlock((uint8_t *) buff+SECTOR_SIZE*secNum,
(sector+secNum)*SECTOR_SIZE,
SECTOR_SIZE);
while(SD_GetStatus() != SD_TRANSFER_OK);
}
/* ................................................................................
...............................*/
}
/* Read Sector(s) */
DRESULT disk_read (
BYTE drv, /* Physical drive nmuber (0..) */
BYTE *buff, /* Data buffer to store read data */
DWORD sector, /* Sector address (LBA) */
BYTE count /* Number of sectors to read (1..255) */
)
{
/* ................................................................................
...............................*/
for (int secNum = 0; (secNum < count) && (Status == SD_OK); secNum++)
{
Status = SD_ReadBlock((buff+SECTOR_SIZE*secNum),
(sector+secNum)*SECTOR_SIZE,
SECTOR_SIZE);
while(SD_GetStatus() != SD_TRANSFER_OK);
}
/* ................................................................................
...............................*/
}
/*-----------------------------------------------------------------------*/
/* Write Sector(s) */
#if _READONLY == 0
DRESULT disk_write (
BYTE drv, /* Physical drive nmuber (0..) */
const BYTE *buff, /* Data to be written */
DWORD sector, /* Sector address (LBA) */
BYTE count /* Number of sectors to write (1..255) */
)
{
/* ................................................................................
...............................*/
for (int secNum = 0; (secNum < count) && (Status == SD_OK); secNum++)
{
Status = SD_WriteBlock((uint8_t *) buff+SECTOR_SIZE*secNum,
(sector+secNum)*SECTOR_SIZE,
SECTOR_SIZE);
while(SD_GetStatus() != SD_TRANSFER_OK);
}
/* ................................................................................
...............................*/
}