interface functions between FATFS and SD card I/O functions More...
#include "config.h"
#include <stdio.h>
#include <avr/pgmspace.h>
#include <diskio.h>
#include <sdcmd.h>
Defines | |
#define | SDCARD_MINVOLTAGE (2800) |
minimum voltage for SD access | |
#define | CHK_POWER do {} while (0) |
#define | MAXMULTSECT (0 ? 8 : 1) |
maximum number of sectors to handle in one SD command (read or write) | |
Functions | |
DSTATUS | disk_initialize (BYTE drv) |
initialize disk | |
DSTATUS | disk_status (BYTE drv) |
check disk status | |
DRESULT | disk_read (BYTE drv, BYTE *buf, DWORD sect, BYTE count) |
read data from disk | |
DRESULT | disk_write (BYTE drv, const BYTE *buf, DWORD sect, BYTE count) |
write data to disk | |
DRESULT | disk_ioctl (BYTE drv, BYTE ctrl, void *buf) |
special operations with disk |
interface functions between FATFS and SD card I/O functions
#define MAXMULTSECT (0 ? 8 : 1) |
maximum number of sectors to handle in one SD command (read or write)
MAXMULTSECT currently is set to 1, because more does not seem to work for me and I don't have documentation at hand.
#define SDCARD_MINVOLTAGE (2800) |
minimum voltage for SD access
The minimum safe voltage for SD card operation is 2.7 Volt according to specification. Require somewhat more to account for measuring error
DSTATUS disk_initialize | ( | BYTE | drv | ) |
initialize disk
disk_initialize() initializes the SD card if necessary (power-on or after battery low level indication).
drv | which drive to initialize (0=SD card) |
{ uint16_t result; if (drv == 0) { CHK_POWER; if (!sd_is_initialized) { result = sd_init_card (1); if (result != 0) { /* failure on init */ return STA_NOINIT; } sd_is_initialized = 1; } return 0; } return STA_NOINIT; }
DRESULT disk_read | ( | BYTE | drv, | |
BYTE * | buf, | |||
DWORD | sect, | |||
BYTE | count | |||
) |
read data from disk
disk_read() reads the specified number of sectors from disk into RAM.
drv | which drive to read the data from | |
buf | pointer to RAM buffer to put read data into | |
sect | starting sector number | |
count | number of sectors to read |
For reading a single sector just do a sd_read_block().
When there is more than one sector left to read, use sd_read_block_multi(), but read at most MAXMULTSECT sectors per iteration.
{ uint8_t result; uint32_t addr; if (drv != 0) return RES_NOTRDY; CHK_POWER; if (count == 0) return RES_PARERR; while (count) { uint8_t n; if (count == 1) { addr = sd_block2addr (sect); result = sd_read_block (buf, addr); if (result) { printf_P (PSTR("sd_read_block(%p,%lx)"), buf, addr); printf_P (PSTR("=%02x\r\n"), result); } return result ? RES_ERROR : RES_OK; } /* count > 1 => use multiple access if enabled */ n = MAXMULTSECT; if (count < n) n = count; if (MAXMULTSECT > 1) { sd_rd_mult_block_data_t desc; /* fill data pointers */ desc.buffer = buf; desc.num_blocks = n; buf += SECTOR_SIZE * n; /* prepare for next iteration */ addr = sd_block2addr(sect); printf_P (PSTR("sd_read_block_mult2(%p,%lx,%hu)"), buf, addr, n); result = sd_read_multiple_block2 (&desc, n, addr); } else { addr = sd_block2addr (sect); #if 0 printf_P (PSTR("sd_read_block(%p,%lx)"), buf, addr); #endif result = sd_read_block (buf, addr); buf += SECTOR_SIZE; } sect += n; count -= n; if (result) return RES_ERROR; } return RES_OK; }
DSTATUS disk_status | ( | BYTE | drv | ) |
check disk status
drv | drive to check |
{ if (drv == 0) { CHK_POWER; return 0; return STA_NODISK; } return STA_NOINIT; }
DRESULT disk_write | ( | BYTE | drv, | |
const BYTE * | buf, | |||
DWORD | sect, | |||
BYTE | count | |||
) |
write data to disk
disk_write() writes the specified number of sectors from RAM to the disk.
drv | which drive to write the data to | |
buf | pointer to RAM buffer to read data from | |
sect | starting sector number | |
count | number of sectors to write |
For writing a single sector just do a sd_write_block().
When there is more than one sector left to write, use sd_write_block_multi(), but write at most MAXMULTSECT sectors per iteration.
{ uint32_t result; uint32_t addr; if (drv != 0) return RES_NOTRDY; CHK_POWER; if (count == 0) return RES_PARERR; while (count) { uint8_t n; if (count == 1) { uint8_t retries = 4; uint8_t reset_retries = 5; uint8_t reset_done = 0; addr = sd_block2addr (sect); do { result = sd_write_block (buf, addr); if (result || reset_done) { printf_P (PSTR("sd_write_block(%p,%lx)"), buf, addr); printf_P (PSTR("=%06lx\r\n"), result); } if (result) { if (--retries == 0) { /* give up */ if (--reset_retries == 0) { /* really give up */ return RES_ERROR; } /* - reset card and try again */ printf_P (PSTR("resetting SD card\r\n")); sd_init_card (0); reset_done = 1; } } } while (result); return RES_OK; } /* count > 1 => use multiple access if enabled */ n = MAXMULTSECT; if (count < n) n = count; if (MAXMULTSECT > 1) { sd_wr_mult_block_data_t desc; /* fill data pointers */ desc.buffer = buf; desc.num_blocks = n; buf += SECTOR_SIZE * n; /* prepare for next iteration */ result = sd_write_multiple_block2 (&desc, n, sd_block2addr(sect)); } else { addr = sd_block2addr (sect); printf_P (PSTR("sd_write_block(%p,%lx)"), buf, addr); result = sd_write_block (buf, addr); buf += SECTOR_SIZE; } sect += n; count -= n; if (result) return RES_ERROR; } return RES_OK; }