SD card for ARM board (first part)
This commit is contained in:
+6
-8
@@ -296,6 +296,10 @@ ifeq ($(EEPROM_PROGRESS_BAR), YES)
|
||||
CPPDEFS += -DEEPROM_PROGRESS_BAR
|
||||
endif
|
||||
|
||||
ifeq ($(SDCARD), YES)
|
||||
CPPDEFS += -DSDCARD
|
||||
endif
|
||||
|
||||
RUN_FROM_FLASH = 1
|
||||
|
||||
ifeq ($(PCB), ARM)
|
||||
@@ -305,8 +309,7 @@ ifeq ($(PCB), ARM)
|
||||
EXTRAINCDIRS += ersky9x
|
||||
BOARDSRC = board_ersky9x.cpp
|
||||
EXTRABOARDSRC = ersky9x/core_cm3.c ersky9x/board_lowlevel.c ersky9x/crt.c ersky9x/vectors_sam3s.c
|
||||
# ersky9x/ff.c ersky9x/diskio_sam3s.c ersky9x/Media.c ersky9x/ccsbcs.c ersky9x/sdcard.c ersky9x/MEDSdcard.c
|
||||
# CPPSRC += ersky9x/sdmmc_spi.c ersky9x/sdspi.c
|
||||
CPPSRC += ersky9x/ff.cpp ersky9x/diskio.cpp ersky9x/gtime.cpp
|
||||
EEPROMSRC = eeprom_arm.cpp
|
||||
PULSESSRC = pulses_arm.cpp
|
||||
CPPSRC += ersky9x/audio.cpp haptic.cpp
|
||||
@@ -322,14 +325,9 @@ ifeq ($(PCB), V4)
|
||||
EEPROMSRC = eeprom_avr.cpp
|
||||
PULSESSRC = pulses_avr.cpp
|
||||
CPPSRC += stock/audio.cpp haptic.cpp
|
||||
CPPSRC += gruvin9x/gtime.cpp
|
||||
CPPSRC += gruvin9x/rtc.cpp
|
||||
CPPSRC += gruvin9x/ff.cpp
|
||||
CPPSRC += gruvin9x/diskio.cpp
|
||||
|
||||
ifeq ($(SDCARD), YES)
|
||||
CPPDEFS += -DSDCARD
|
||||
CPPSRC += gruvin9x/logs.cpp
|
||||
CPPSRC += gruvin9x/logs.cpp gruvin9x/gtime.cpp gruvin9x/rtc.cpp gruvin9x/ff.cpp gruvin9x/diskio.cpp
|
||||
MODS:=${MODS}S
|
||||
endif
|
||||
|
||||
|
||||
@@ -71,6 +71,7 @@ inline void board_init()
|
||||
TCCR0B = (1<<WGM02) | (0b011 << CS00);
|
||||
TCCR0A = (0b01<<WGM00);
|
||||
|
||||
#if defined(SDCARD)
|
||||
// Initialise global unix timestamp with current time from RTC chip on SD card interface
|
||||
RTC rtc = {0,0,0,0,0,0,0};
|
||||
struct gtm utm;
|
||||
@@ -83,6 +84,7 @@ inline void board_init()
|
||||
utm.tm_sec = rtc.sec;
|
||||
utm.tm_wday = rtc.wday - 1;
|
||||
g_unixTime = mktime(&utm);
|
||||
#endif
|
||||
|
||||
/***************************************************/
|
||||
/* Rotary encoder interrupt set-up (V4 board only) */
|
||||
|
||||
+2
-7
@@ -137,10 +137,6 @@ void killEvents(uint8_t event)
|
||||
volatile uint16_t g_tmr10ms;
|
||||
volatile uint8_t g_blinkTmr10ms;
|
||||
|
||||
|
||||
#if defined (PCBV4)
|
||||
uint8_t g_ms100 = 0; // global to allow time set function to reset to zero
|
||||
#endif
|
||||
void per10ms()
|
||||
{
|
||||
g_tmr10ms++;
|
||||
@@ -150,10 +146,9 @@ void per10ms()
|
||||
Tenms |= 1 ; // 10 mS has passed
|
||||
#endif
|
||||
|
||||
#if defined (PCBV4)
|
||||
#if defined (PCBV4) && defined(SDCARD)
|
||||
/* Update gloabal Date/Time every 100 per10ms cycles */
|
||||
if (++g_ms100 == 100)
|
||||
{
|
||||
if (++g_ms100 == 100) {
|
||||
g_unixTime++; // inc global unix timestamp one second
|
||||
g_ms100 = 0;
|
||||
}
|
||||
|
||||
@@ -932,6 +932,12 @@ typedef struct {
|
||||
/* -------- HSMCI_SDCR : (HSMCI Offset: 0x0C) SD/SDIO Card Register -------- */
|
||||
#define HSMCI_SDCR_SDCSEL (0x3 << 0) /**< \brief (HSMCI_SDCR) SDCard/SDIO Slot */
|
||||
#define HSMCI_SDCR_SDCBUS (0x3 << 6) /**< \brief (HSMCI_SDCR) SDCard/SDIO Bus Width */
|
||||
#define HSMCI_SDCR_SDCSEL_SLOTA (0x0u << 0) /**< \brief (HSMCI_SDCR) Slot A is selected. */
|
||||
#define HSMCI_SDCR_SDCSEL_SLOTB (0x1u << 0) /**< \brief (HSMCI_SDCR) - */
|
||||
#define HSMCI_SDCR_SDCSEL_SLOTC (0x2u << 0) /**< \brief (HSMCI_SDCR) - */
|
||||
#define HSMCI_SDCR_SDCSEL_SLOTD (0x3u << 0) /**< \brief (HSMCI_SDCR) - */
|
||||
#define HSMCI_SDCR_SDCBUS_1 (0x0u << 6) /**< \brief (HSMCI_SDCR) 1 bit */
|
||||
#define HSMCI_SDCR_SDCBUS_4 (0x2u << 6) /**< \brief (HSMCI_SDCR) 4 bit */
|
||||
/* -------- HSMCI_ARGR : (HSMCI Offset: 0x10) Argument Register -------- */
|
||||
#define HSMCI_ARGR_ARG (0xffffffff << 0) /**< \brief (HSMCI_ARGR) Command Argument */
|
||||
/* -------- HSMCI_CMDR : (HSMCI Offset: 0x14) Command Register -------- */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* Authors (alphabetical order)
|
||||
* - Bertrand Songis <bsongis@gmail.com>
|
||||
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
|
||||
* - Cameron Weeks <th9xer@gmail.com>
|
||||
* - Erez Raviv
|
||||
* - Jean-Pierre Parisy
|
||||
* - Karl Szmutny <shadow@privy.de>
|
||||
* - Michael Blandford
|
||||
* - Michal Hlavinka
|
||||
* - Pat Mackenzie
|
||||
* - Philip Moss
|
||||
* - Rob Thomson
|
||||
* - Romolo Manfredini <romolo.manfredini@gmail.com>
|
||||
* - Thomas Husterer
|
||||
*
|
||||
* open9x is based on code named
|
||||
* gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/,
|
||||
* er9x by Erez Raviv: http://code.google.com/p/er9x/,
|
||||
* and the original (and ongoing) project by
|
||||
* Thomas Husterer, th9x: http://code.google.com/p/th9x/
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
/ Low level disk interface modlue include file (C)ChaN, 2010
|
||||
/-----------------------------------------------------------------------*/
|
||||
|
||||
#ifndef DEF_DISKIO
|
||||
#define DEF_DISKIO
|
||||
|
||||
#include "integer.h"
|
||||
|
||||
#define DN_MCI 0 /* Physical drive number for MCI */
|
||||
#define DN_NAND 1 /* Physical drive number for NAND flash */
|
||||
|
||||
|
||||
/* These functions are defined in asmfunc.S */
|
||||
void Copy_al2un (BYTE *dst, const DWORD *src, int count); /* Copy aligned to unaligned. */
|
||||
void Copy_un2al (DWORD *dst, const BYTE *src, int count); /* Copy unaligned to aligned. */
|
||||
|
||||
|
||||
/* Status of Disk Functions */
|
||||
typedef BYTE DSTATUS;
|
||||
|
||||
/* Results of Disk Functions */
|
||||
typedef enum {
|
||||
RES_OK = 0, /* 0: Successful */
|
||||
RES_ERROR, /* 1: R/W Error */
|
||||
RES_WRPRT, /* 2: Write Protected */
|
||||
RES_NOTRDY, /* 3: Not Ready */
|
||||
RES_PARERR /* 4: Invalid Parameter */
|
||||
} DRESULT;
|
||||
|
||||
|
||||
/*---------------------------------------*/
|
||||
/* Prototypes for disk control functions */
|
||||
|
||||
DSTATUS disk_initialize (BYTE);
|
||||
DSTATUS disk_status (BYTE);
|
||||
DRESULT disk_read (BYTE, BYTE*, DWORD, BYTE);
|
||||
DRESULT disk_write (BYTE, const BYTE*, DWORD, BYTE);
|
||||
DRESULT disk_ioctl (BYTE, BYTE, BYTE*);
|
||||
void disk_timerproc (void);
|
||||
|
||||
|
||||
/* Disk Status Bits (DSTATUS) */
|
||||
|
||||
#define STA_NOINIT 0x01 /* Drive not initialized */
|
||||
#define STA_NODISK 0x02 /* No medium in the drive */
|
||||
#define STA_PROTECT 0x04 /* Write protected */
|
||||
|
||||
|
||||
/* Command code for disk_ioctrl fucntion */
|
||||
|
||||
/* Generic ioctl command (defined for FatFs) */
|
||||
#define CTRL_SYNC 0 /* Flush disk cache (for write functions) */
|
||||
#define GET_SECTOR_COUNT 1 /* Get media size (for only f_mkfs()) */
|
||||
#define GET_SECTOR_SIZE 2 /* Get sector size (for multiple sector size (_MAX_SS >= 1024)) */
|
||||
#define GET_BLOCK_SIZE 3 /* Get erase block size (for only f_mkfs()) */
|
||||
#define CTRL_ERASE_SECTOR 4 /* Force erased a block of sectors (for only _USE_ERASE) */
|
||||
|
||||
/* Generic ioctl command */
|
||||
#define CTRL_POWER 5 /* Get/Set power status */
|
||||
#define CTRL_LOCK 6 /* Lock/Unlock media removal */
|
||||
#define CTRL_EJECT 7 /* Eject media */
|
||||
|
||||
/* MMC/SDC specific ioctl command */
|
||||
#define MMC_GET_TYPE 10 /* Get card type */
|
||||
#define MMC_GET_CSD 11 /* Get CSD */
|
||||
#define MMC_GET_CID 12 /* Get CID */
|
||||
#define MMC_GET_OCR 13 /* Get OCR */
|
||||
#define MMC_GET_SDSTAT 14 /* Get SD status */
|
||||
|
||||
/* ATA/CF specific ioctl command */
|
||||
#define ATA_GET_REV 20 /* Get F/W revision */
|
||||
#define ATA_GET_MODEL 21 /* Get model name */
|
||||
#define ATA_GET_SN 22 /* Get serial number */
|
||||
|
||||
/* NAND specific ioctl command */
|
||||
#define NAND_FORMAT 30 /* Create physical format */
|
||||
|
||||
|
||||
volatile extern BYTE Timer1, Timer2; /* 100Hz decrement timer */
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// Detect if SD card is connected
|
||||
//------------------------------------------------------------------------------
|
||||
#define CardIsConnected() ( (PIOB->PIO_PDSR & PIO_PB7) == 0 )
|
||||
|
||||
extern uint32_t Card_ID[4] ;
|
||||
extern uint32_t Card_SCR[2] ;
|
||||
extern uint32_t Card_CSD[4] ;
|
||||
extern uint32_t Sd_128_resp[4] ;
|
||||
extern uint32_t Sd_rca ;
|
||||
//extern uint32_t Cmd_55_resp ;
|
||||
|
||||
extern uint32_t SD_SetBusWidth( uint32_t busWidth) ;
|
||||
extern void SD_EnableHsMode( uint8_t hsEnable) ;
|
||||
extern uint32_t SD_SetSpeed( uint32_t mciSpeed ) ;
|
||||
extern void SD_Reset( uint8_t keepSettings) ;
|
||||
extern void sd_cmd55( void ) ;
|
||||
extern uint32_t sd_acmd41( void ) ;
|
||||
extern uint32_t sd_cmd2( void ) ;
|
||||
extern uint32_t sd_cmd3( void ) ;
|
||||
extern uint32_t sd_cmd7( void ) ;
|
||||
extern uint32_t sd_cmd9( void ) ;
|
||||
extern uint32_t sd_cmd17( uint32_t address, uint32_t *presult ) ;
|
||||
extern uint32_t sd_acmd6( void ) ;
|
||||
extern uint32_t sd_acmd51( uint32_t *presult ) ;
|
||||
extern void sd_poll_10mS( void ) ;
|
||||
extern uint32_t sd_card_ready( void ) ;
|
||||
extern uint32_t sd_read_block( uint32_t block_no, uint32_t *data ) ;
|
||||
|
||||
|
||||
#endif
|
||||
+3819
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,575 @@
|
||||
/*
|
||||
* Authors (alphabetical order)
|
||||
* - Bertrand Songis <bsongis@gmail.com>
|
||||
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
|
||||
* - Cameron Weeks <th9xer@gmail.com>
|
||||
* - Erez Raviv
|
||||
* - Jean-Pierre Parisy
|
||||
* - Karl Szmutny <shadow@privy.de>
|
||||
* - Michael Blandford
|
||||
* - Michal Hlavinka
|
||||
* - Pat Mackenzie
|
||||
* - Philip Moss
|
||||
* - Rob Thomson
|
||||
* - Romolo Manfredini <romolo.manfredini@gmail.com>
|
||||
* - Thomas Husterer
|
||||
*
|
||||
* open9x is based on code named
|
||||
* gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/,
|
||||
* er9x by Erez Raviv: http://code.google.com/p/er9x/,
|
||||
* and the original (and ongoing) project by
|
||||
* Thomas Husterer, th9x: http://code.google.com/p/th9x/
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
/*---------------------------------------------------------------------------/
|
||||
/ FatFs - FAT file system module include file R0.08a (C)ChaN, 2010
|
||||
/----------------------------------------------------------------------------/
|
||||
/ FatFs module is a generic FAT file system module for small embedded systems.
|
||||
/ This is a free software that opened for education, research and commercial
|
||||
/ developments under license policy of following trems.
|
||||
/
|
||||
/ Copyright (C) 2010, ChaN, all right reserved.
|
||||
/
|
||||
/ * The FatFs module is a free software and there is NO WARRANTY.
|
||||
/ * No restriction on use. You can use, modify and redistribute it for
|
||||
/ personal, non-profit or commercial product UNDER YOUR RESPONSIBILITY.
|
||||
/ * Redistributions of source code must retain the above copyright notice.
|
||||
/
|
||||
/----------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _FATFS
|
||||
#define _FATFS 8255 /* Revision ID */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "inttypes.h"
|
||||
#include "integer.h" /* Basic integer types */
|
||||
#include "ffconf.h" /* FatFs configuration options */
|
||||
|
||||
#if _FATFS != _FFCONF
|
||||
#error Wrong configuration file (ffconf.h).
|
||||
#endif
|
||||
|
||||
|
||||
/* DBCS code ranges and SBCS extend char conversion table */
|
||||
|
||||
#if _CODE_PAGE == 932 /* Japanese Shift-JIS */
|
||||
#define _DF1S 0x81 /* DBC 1st byte range 1 start */
|
||||
#define _DF1E 0x9F /* DBC 1st byte range 1 end */
|
||||
#define _DF2S 0xE0 /* DBC 1st byte range 2 start */
|
||||
#define _DF2E 0xFC /* DBC 1st byte range 2 end */
|
||||
#define _DS1S 0x40 /* DBC 2nd byte range 1 start */
|
||||
#define _DS1E 0x7E /* DBC 2nd byte range 1 end */
|
||||
#define _DS2S 0x80 /* DBC 2nd byte range 2 start */
|
||||
#define _DS2E 0xFC /* DBC 2nd byte range 2 end */
|
||||
|
||||
#elif _CODE_PAGE == 936 /* Simplified Chinese GBK */
|
||||
#define _DF1S 0x81
|
||||
#define _DF1E 0xFE
|
||||
#define _DS1S 0x40
|
||||
#define _DS1E 0x7E
|
||||
#define _DS2S 0x80
|
||||
#define _DS2E 0xFE
|
||||
|
||||
#elif _CODE_PAGE == 949 /* Korean */
|
||||
#define _DF1S 0x81
|
||||
#define _DF1E 0xFE
|
||||
#define _DS1S 0x41
|
||||
#define _DS1E 0x5A
|
||||
#define _DS2S 0x61
|
||||
#define _DS2E 0x7A
|
||||
#define _DS3S 0x81
|
||||
#define _DS3E 0xFE
|
||||
|
||||
#elif _CODE_PAGE == 950 /* Traditional Chinese Big5 */
|
||||
#define _DF1S 0x81
|
||||
#define _DF1E 0xFE
|
||||
#define _DS1S 0x40
|
||||
#define _DS1E 0x7E
|
||||
#define _DS2S 0xA1
|
||||
#define _DS2E 0xFE
|
||||
|
||||
#elif _CODE_PAGE == 437 /* U.S. (OEM) */
|
||||
#define _DF1S 0
|
||||
#define _EXCVT {0x80,0x9A,0x90,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x49,0x49,0x49,0x8E,0x8F,0x90,0x92,0x92,0x4F,0x99,0x4F,0x55,0x55,0x59,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
|
||||
0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
|
||||
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
|
||||
0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
|
||||
|
||||
#elif _CODE_PAGE == 720 /* Arabic (OEM) */
|
||||
#define _DF1S 0
|
||||
#define _EXCVT {0x80,0x81,0x45,0x41,0x84,0x41,0x86,0x43,0x45,0x45,0x45,0x49,0x49,0x8D,0x8E,0x8F,0x90,0x92,0x92,0x93,0x94,0x95,0x49,0x49,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
|
||||
0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
|
||||
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
|
||||
0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
|
||||
|
||||
#elif _CODE_PAGE == 737 /* Greek (OEM) */
|
||||
#define _DF1S 0
|
||||
#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x92,0x92,0x93,0x94,0x95,0x96,0x97,0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87, \
|
||||
0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0xAA,0x92,0x93,0x94,0x95,0x96,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
|
||||
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
|
||||
0x97,0xEA,0xEB,0xEC,0xE4,0xED,0xEE,0xE7,0xE8,0xF1,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
|
||||
|
||||
#elif _CODE_PAGE == 775 /* Baltic (OEM) */
|
||||
#define _DF1S 0
|
||||
#define _EXCVT {0x80,0x9A,0x91,0xA0,0x8E,0x95,0x8F,0x80,0xAD,0xED,0x8A,0x8A,0xA1,0x8D,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0x95,0x96,0x97,0x97,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \
|
||||
0xA0,0xA1,0xE0,0xA3,0xA3,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
|
||||
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xB5,0xB6,0xB7,0xB8,0xBD,0xBE,0xC6,0xC7,0xA5,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
|
||||
0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE3,0xE8,0xE8,0xEA,0xEA,0xEE,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
|
||||
|
||||
#elif _CODE_PAGE == 850 /* Multilingual Latin 1 (OEM) */
|
||||
#define _DF1S 0
|
||||
#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0xDE,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x59,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \
|
||||
0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
|
||||
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
|
||||
0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE7,0xE9,0xEA,0xEB,0xED,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
|
||||
|
||||
#elif _CODE_PAGE == 852 /* Latin 2 (OEM) */
|
||||
#define _DF1S 0
|
||||
#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xDE,0x8F,0x80,0x9D,0xD3,0x8A,0x8A,0xD7,0x8D,0x8E,0x8F,0x90,0x91,0x91,0xE2,0x99,0x95,0x95,0x97,0x97,0x99,0x9A,0x9B,0x9B,0x9D,0x9E,0x9F, \
|
||||
0xB5,0xD6,0xE0,0xE9,0xA4,0xA4,0xA6,0xA6,0xA8,0xA8,0xAA,0x8D,0xAC,0xB8,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBD,0xBF, \
|
||||
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC6,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD2,0xD3,0xD2,0xD5,0xD6,0xD7,0xB7,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
|
||||
0xE0,0xE1,0xE2,0xE3,0xE3,0xD5,0xE6,0xE6,0xE8,0xE9,0xE8,0xEB,0xED,0xED,0xDD,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xEB,0xFC,0xFC,0xFE,0xFF}
|
||||
|
||||
#elif _CODE_PAGE == 855 /* Cyrillic (OEM) */
|
||||
#define _DF1S 0
|
||||
#define _EXCVT {0x81,0x81,0x83,0x83,0x85,0x85,0x87,0x87,0x89,0x89,0x8B,0x8B,0x8D,0x8D,0x8F,0x8F,0x91,0x91,0x93,0x93,0x95,0x95,0x97,0x97,0x99,0x99,0x9B,0x9B,0x9D,0x9D,0x9F,0x9F, \
|
||||
0xA1,0xA1,0xA3,0xA3,0xA5,0xA5,0xA7,0xA7,0xA9,0xA9,0xAB,0xAB,0xAD,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB6,0xB6,0xB8,0xB8,0xB9,0xBA,0xBB,0xBC,0xBE,0xBE,0xBF, \
|
||||
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD3,0xD3,0xD5,0xD5,0xD7,0xD7,0xDD,0xD9,0xDA,0xDB,0xDC,0xDD,0xE0,0xDF, \
|
||||
0xE0,0xE2,0xE2,0xE4,0xE4,0xE6,0xE6,0xE8,0xE8,0xEA,0xEA,0xEC,0xEC,0xEE,0xEE,0xEF,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF8,0xFA,0xFA,0xFC,0xFC,0xFD,0xFE,0xFF}
|
||||
|
||||
#elif _CODE_PAGE == 857 /* Turkish (OEM) */
|
||||
#define _DF1S 0
|
||||
#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0x98,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x98,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9E, \
|
||||
0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA6,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
|
||||
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
|
||||
0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xDE,0x59,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
|
||||
|
||||
#elif _CODE_PAGE == 858 /* Multilingual Latin 1 + Euro (OEM) */
|
||||
#define _DF1S 0
|
||||
#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0xDE,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x59,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \
|
||||
0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
|
||||
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
|
||||
0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE7,0xE9,0xEA,0xEB,0xED,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
|
||||
|
||||
#elif _CODE_PAGE == 862 /* Hebrew (OEM) */
|
||||
#define _DF1S 0
|
||||
#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
|
||||
0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
|
||||
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
|
||||
0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
|
||||
|
||||
#elif _CODE_PAGE == 866 /* Russian (OEM) */
|
||||
#define _DF1S 0
|
||||
#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
|
||||
0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
|
||||
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
|
||||
0x90,0x91,0x92,0x93,0x9d,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,0xF0,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
|
||||
|
||||
#elif _CODE_PAGE == 874 /* Thai (OEM, Windows) */
|
||||
#define _DF1S 0
|
||||
#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
|
||||
0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
|
||||
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
|
||||
0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
|
||||
|
||||
#elif _CODE_PAGE == 1250 /* Central Europe (Windows) */
|
||||
#define _DF1S 0
|
||||
#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x8A,0x9B,0x8C,0x8D,0x8E,0x8F, \
|
||||
0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xA3,0xB4,0xB5,0xB6,0xB7,0xB8,0xA5,0xAA,0xBB,0xBC,0xBD,0xBC,0xAF, \
|
||||
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
|
||||
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF}
|
||||
|
||||
#elif _CODE_PAGE == 1251 /* Cyrillic (Windows) */
|
||||
#define _DF1S 0
|
||||
#define _EXCVT {0x80,0x81,0x82,0x82,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x80,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x8A,0x9B,0x8C,0x8D,0x8E,0x8F, \
|
||||
0xA0,0xA2,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB2,0xA5,0xB5,0xB6,0xB7,0xA8,0xB9,0xAA,0xBB,0xA3,0xBD,0xBD,0xAF, \
|
||||
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
|
||||
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF}
|
||||
|
||||
#elif _CODE_PAGE == 1252 /* Latin 1 (Windows) */
|
||||
#define _DF1S 0
|
||||
#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0xAd,0x9B,0x8C,0x9D,0xAE,0x9F, \
|
||||
0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
|
||||
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
|
||||
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0x9F}
|
||||
|
||||
#elif _CODE_PAGE == 1253 /* Greek (Windows) */
|
||||
#define _DF1S 0
|
||||
#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
|
||||
0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
|
||||
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xA2,0xB8,0xB9,0xBA, \
|
||||
0xE0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xF2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xFB,0xBC,0xFD,0xBF,0xFF}
|
||||
|
||||
#elif _CODE_PAGE == 1254 /* Turkish (Windows) */
|
||||
#define _DF1S 0
|
||||
#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x8A,0x9B,0x8C,0x9D,0x9E,0x9F, \
|
||||
0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
|
||||
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
|
||||
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0x9F}
|
||||
|
||||
#elif _CODE_PAGE == 1255 /* Hebrew (Windows) */
|
||||
#define _DF1S 0
|
||||
#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
|
||||
0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
|
||||
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
|
||||
0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
|
||||
|
||||
#elif _CODE_PAGE == 1256 /* Arabic (Windows) */
|
||||
#define _DF1S 0
|
||||
#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x8C,0x9D,0x9E,0x9F, \
|
||||
0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
|
||||
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
|
||||
0x41,0xE1,0x41,0xE3,0xE4,0xE5,0xE6,0x43,0x45,0x45,0x45,0x45,0xEC,0xED,0x49,0x49,0xF0,0xF1,0xF2,0xF3,0x4F,0xF5,0xF6,0xF7,0xF8,0x55,0xFA,0x55,0x55,0xFD,0xFE,0xFF}
|
||||
|
||||
#elif _CODE_PAGE == 1257 /* Baltic (Windows) */
|
||||
#define _DF1S 0
|
||||
#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
|
||||
0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xA8,0xB9,0xAA,0xBB,0xBC,0xBD,0xBE,0xAF, \
|
||||
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
|
||||
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF}
|
||||
|
||||
#elif _CODE_PAGE == 1258 /* Vietnam (OEM, Windows) */
|
||||
#define _DF1S 0
|
||||
#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0xAC,0x9D,0x9E,0x9F, \
|
||||
0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
|
||||
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
|
||||
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xEC,0xCD,0xCE,0xCF,0xD0,0xD1,0xF2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xFE,0x9F}
|
||||
|
||||
#elif _CODE_PAGE == 1 /* ASCII (for only non-LFN cfg) */
|
||||
#define _DF1S 0
|
||||
|
||||
#else
|
||||
#error Unknown code page
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* Definitions of volume management */
|
||||
|
||||
#if _MULTI_PARTITION /* Multiple partition configuration */
|
||||
#define LD2PD(vol) (VolToPart[vol].pd) /* Get physical drive# */
|
||||
#define LD2PT(vol) (VolToPart[vol].pt) /* Get partition# */
|
||||
typedef struct {
|
||||
BYTE pd; /* Physical drive# */
|
||||
BYTE pt; /* Partition # (0-3) */
|
||||
} PARTITION;
|
||||
extern const PARTITION VolToPart[]; /* Volume - Physical location resolution table */
|
||||
|
||||
#else /* Single partition configuration */
|
||||
#define LD2PD(vol) (vol) /* Logical drive# is bound to the same physical drive# */
|
||||
#define LD2PT(vol) 0 /* Always mounts the 1st partition */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* Type of path name strings on FatFs API */
|
||||
|
||||
#if _LFN_UNICODE /* Unicode string */
|
||||
#if !_USE_LFN
|
||||
#error _LFN_UNICODE must be 0 in non-LFN cfg.
|
||||
#endif
|
||||
#ifndef _INC_TCHAR
|
||||
typedef WCHAR TCHAR;
|
||||
#define _T(x) L ## x
|
||||
#define _TEXT(x) L ## x
|
||||
#endif
|
||||
|
||||
#else /* ANSI/OEM string */
|
||||
#ifndef _INC_TCHAR
|
||||
typedef char TCHAR;
|
||||
#define _T(x) x
|
||||
#define _TEXT(x) x
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* File system object structure (FATFS) */
|
||||
|
||||
typedef struct {
|
||||
BYTE fs_type; /* FAT sub-type (0:Not mounted) */
|
||||
BYTE drv; /* Physical drive number */
|
||||
BYTE csize; /* Sectors per cluster (1,2,4...128) */
|
||||
BYTE n_fats; /* Number of FAT copies (1,2) */
|
||||
BYTE wflag; /* win[] dirty flag (1:must be written back) */
|
||||
BYTE fsi_flag; /* fsinfo dirty flag (1:must be written back) */
|
||||
WORD id; /* File system mount ID */
|
||||
WORD n_rootdir; /* Number of root directory entries (FAT12/16) */
|
||||
#if _MAX_SS != 512
|
||||
WORD ssize; /* Bytes per sector (512,1024,2048,4096) */
|
||||
#endif
|
||||
#if _FS_REENTRANT
|
||||
_SYNC_t sobj; /* Identifier of sync object */
|
||||
#endif
|
||||
#if !_FS_READONLY
|
||||
DWORD last_clust; /* Last allocated cluster */
|
||||
DWORD free_clust; /* Number of free clusters */
|
||||
DWORD fsi_sector; /* fsinfo sector (FAT32) */
|
||||
#endif
|
||||
#if _FS_RPATH
|
||||
DWORD cdir; /* Current directory start cluster (0:root) */
|
||||
#endif
|
||||
DWORD n_fatent; /* Number of FAT entries (= number of clusters + 2) */
|
||||
DWORD fsize; /* Sectors per FAT */
|
||||
DWORD fatbase; /* FAT start sector */
|
||||
DWORD dirbase; /* Root directory start sector (FAT32:Cluster#) */
|
||||
DWORD database; /* Data start sector */
|
||||
DWORD winsect; /* Current sector appearing in the win[] */
|
||||
BYTE win[_MAX_SS]; /* Disk access window for Directory, FAT (and Data on tiny cfg) */
|
||||
} FATFS;
|
||||
|
||||
|
||||
|
||||
/* File object structure (FIL) */
|
||||
|
||||
typedef struct {
|
||||
FATFS* fs; /* Pointer to the owner file system object */
|
||||
WORD id; /* Owner file system mount ID */
|
||||
BYTE flag; /* File status flags */
|
||||
BYTE pad1;
|
||||
DWORD fptr; /* File read/write pointer (0 on file open) */
|
||||
DWORD fsize; /* File size */
|
||||
DWORD org_clust; /* File start cluster (0 when fsize==0) */
|
||||
DWORD curr_clust; /* Current cluster */
|
||||
DWORD dsect; /* Current data sector */
|
||||
#if !_FS_READONLY
|
||||
DWORD dir_sect; /* Sector containing the directory entry */
|
||||
BYTE* dir_ptr; /* Ponter to the directory entry in the window */
|
||||
#endif
|
||||
#if _USE_FASTSEEK
|
||||
DWORD* cltbl; /* Pointer to the cluster link map table (null on file open) */
|
||||
#endif
|
||||
#if _FS_SHARE
|
||||
UINT lockid; /* File lock ID (index of file semaphore table) */
|
||||
#endif
|
||||
#if !_FS_TINY
|
||||
BYTE buf[_MAX_SS]; /* File data read/write buffer */
|
||||
#endif
|
||||
} FIL;
|
||||
|
||||
|
||||
|
||||
/* Directory object structure (DIR) */
|
||||
|
||||
typedef struct {
|
||||
FATFS* fs; /* Pointer to the owner file system object */
|
||||
WORD id; /* Owner file system mount ID */
|
||||
WORD index; /* Current read/write index number */
|
||||
DWORD sclust; /* Table start cluster (0:Root dir) */
|
||||
DWORD clust; /* Current cluster */
|
||||
DWORD sect; /* Current sector */
|
||||
BYTE* dir; /* Pointer to the current SFN entry in the win[] */
|
||||
BYTE* fn; /* Pointer to the SFN (in/out) {file[8],ext[3],status[1]} */
|
||||
#if _USE_LFN
|
||||
WCHAR* lfn; /* Pointer to the LFN working buffer */
|
||||
WORD lfn_idx; /* Last matched LFN index number (0xFFFF:No LFN) */
|
||||
#endif
|
||||
} DIR;
|
||||
|
||||
|
||||
|
||||
/* File status structure (FILINFO) */
|
||||
|
||||
typedef struct {
|
||||
DWORD fsize; /* File size */
|
||||
WORD fdate; /* Last modified date */
|
||||
WORD ftime; /* Last modified time */
|
||||
BYTE fattrib; /* Attribute */
|
||||
TCHAR fname[13]; /* Short file name (8.3 format) */
|
||||
#if _USE_LFN
|
||||
TCHAR* lfname; /* Pointer to the LFN buffer */
|
||||
UINT lfsize; /* Size of LFN buffer in TCHAR */
|
||||
#endif
|
||||
} FILINFO;
|
||||
|
||||
|
||||
|
||||
/* File function return code (FRESULT) */
|
||||
|
||||
typedef enum {
|
||||
FR_OK = 0, // (0) Succeeded
|
||||
FR_DISK_ERR, // (1) A hard error occured in the low level disk I/O layer
|
||||
FR_INT_ERR, // (2) Assertion failed
|
||||
FR_NOT_READY, // (3) The physical drive cannot work
|
||||
FR_NO_FILE, // (4) Could not find the file
|
||||
FR_NO_PATH, // (5) Could not find the path
|
||||
FR_INVALID_NAME, // (6) The path name format is invalid
|
||||
FR_DENIED, // (7) Acces denied due to prohibited access or directory full
|
||||
FR_EXIST, // (8) Acces denied due to prohibited access
|
||||
FR_INVALID_OBJECT, // (9) The file/directory object is invalid
|
||||
FR_WRITE_PROTECTED, // (10) The physical drive is write protected
|
||||
FR_INVALID_DRIVE, // (11) The logical drive number is invalid
|
||||
FR_NOT_ENABLED, // (12) The volume has no work area
|
||||
FR_NO_FILESYSTEM, // (13) There is no valid FAT volume on the physical drive
|
||||
FR_MKFS_ABORTED, // (14) The f_mkfs() aborted due to any parameter error
|
||||
FR_TIMEOUT, // (15) Could not get a grant to access the volume within defined period
|
||||
FR_LOCKED, // (16) The operation is rejected according to the file shareing policy
|
||||
FR_NOT_ENOUGH_CORE, // (17) LFN working buffer could not be allocated
|
||||
FR_TOO_MANY_OPEN_FILES // (18) Number of open files > _FS_SHARE
|
||||
} FRESULT;
|
||||
|
||||
|
||||
|
||||
/*--------------------------------------------------------------*/
|
||||
/* FatFs module application interface */
|
||||
|
||||
FRESULT f_mount (BYTE, FATFS*); /* Mount/Unmount a logical drive */
|
||||
FRESULT f_open (FIL*, const TCHAR*, BYTE); /* Open or create a file */
|
||||
FRESULT f_read (FIL*, BYTE*, UINT, UINT*); /* Read data from a file */
|
||||
FRESULT f_lseek (FIL*, DWORD); /* Move file pointer of a file object */
|
||||
FRESULT f_close (FIL*); /* Close an open file object */
|
||||
FRESULT f_opendir (DIR*, const TCHAR*); /* Open an existing directory */
|
||||
FRESULT f_readdir (DIR*, FILINFO*); /* Read a directory item */
|
||||
FRESULT f_stat (const TCHAR*, FILINFO*); /* Get file status */
|
||||
|
||||
#if !_FS_READONLY
|
||||
FRESULT f_write (FIL*, const BYTE *, UINT, UINT*); /* Write data to a file */
|
||||
FRESULT f_getfree (const TCHAR*, DWORD*, FATFS**); /* Get number of free clusters on the drive */
|
||||
FRESULT f_truncate (FIL*); /* Truncate file */
|
||||
FRESULT f_sync (FIL*); /* Flush cached data of a writing file */
|
||||
FRESULT f_unlink (const TCHAR*); /* Delete an existing file or directory */
|
||||
FRESULT f_mkdir (const TCHAR*); /* Create a new directory */
|
||||
FRESULT f_chmod (const TCHAR*, BYTE, BYTE); /* Change attriburte of the file/dir */
|
||||
FRESULT f_utime (const TCHAR*, const FILINFO*); /* Change timestamp of the file/dir */
|
||||
FRESULT f_rename (const TCHAR*, const TCHAR*); /* Rename/Move a file or directory */
|
||||
#endif
|
||||
|
||||
#if _USE_FORWARD
|
||||
FRESULT f_forward (FIL*, UINT(*)(const BYTE*,UINT), UINT, UINT*); /* Forward data to the stream */
|
||||
#endif
|
||||
|
||||
#if _USE_MKFS
|
||||
FRESULT f_mkfs (BYTE, BYTE, UINT); /* Create a file system on the drive */
|
||||
#endif
|
||||
|
||||
#if _FS_RPATH
|
||||
FRESULT f_chdrive (BYTE); /* Change current drive */
|
||||
FRESULT f_chdir (const TCHAR*); /* Change current directory */
|
||||
FRESULT f_getcwd (TCHAR*, UINT); /* Get current directory */
|
||||
#endif
|
||||
|
||||
#if _USE_STRFUNC
|
||||
int f_putc (TCHAR, FIL*); /* Put a character to the file */
|
||||
int f_puts (const TCHAR*, FIL*); /* Put a string to the file */
|
||||
int f_printf (FIL*, const TCHAR*, ...); /* Put a formatted string to the file */
|
||||
TCHAR* f_gets (TCHAR*, int, FIL*); /* Get a string from the file */
|
||||
#ifndef EOF
|
||||
#define EOF (-1)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define f_eof(fp) (((fp)->fptr == (fp)->fsize) ? 1 : 0)
|
||||
#define f_error(fp) (((fp)->flag & FA__ERROR) ? 1 : 0)
|
||||
#define f_tell(fp) ((fp)->fptr)
|
||||
#define f_size(fp) ((fp)->fsize)
|
||||
|
||||
|
||||
|
||||
/*--------------------------------------------------------------*/
|
||||
/* Additional user defined functions */
|
||||
|
||||
/* RTC function */
|
||||
#if !_FS_READONLY
|
||||
extern uint32_t o9x_get_fattime (void); /* Returns 32-bit packed date and time */
|
||||
#endif
|
||||
|
||||
/* Unicode support functions */
|
||||
#if _USE_LFN /* Unicode - OEM code conversion */
|
||||
WCHAR ff_convert (WCHAR, UINT); /* OEM-Unicode bidirectional conversion */
|
||||
WCHAR ff_wtoupper (WCHAR); /* Unicode upper-case conversion */
|
||||
#if _USE_LFN == 3 /* Memory functions */
|
||||
void* ff_memalloc (UINT); /* Allocate memory block */
|
||||
void ff_memfree (void*); /* Free memory block */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Sync functions */
|
||||
#if _FS_REENTRANT
|
||||
int ff_cre_syncobj (BYTE, _SYNC_t*);/* Create a sync object */
|
||||
int ff_del_syncobj (_SYNC_t); /* Delete a sync object */
|
||||
int ff_req_grant (_SYNC_t); /* Lock sync object */
|
||||
void ff_rel_grant (_SYNC_t); /* Unlock sync object */
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
/*--------------------------------------------------------------*/
|
||||
/* Flags and offset address */
|
||||
|
||||
|
||||
/* File access control and file status flags (FIL.flag) */
|
||||
|
||||
#define FA_READ 0x01
|
||||
#define FA_OPEN_EXISTING 0x00
|
||||
#define FA__ERROR 0x80
|
||||
|
||||
#if !_FS_READONLY
|
||||
#define FA_WRITE 0x02
|
||||
#define FA_CREATE_NEW 0x04
|
||||
#define FA_CREATE_ALWAYS 0x08
|
||||
#define FA_OPEN_ALWAYS 0x10
|
||||
#define FA__WRITTEN 0x20
|
||||
#define FA__DIRTY 0x40
|
||||
#endif
|
||||
|
||||
|
||||
/* FAT sub type (FATFS.fs_type) */
|
||||
|
||||
#define FS_FAT12 1
|
||||
#define FS_FAT16 2
|
||||
#define FS_FAT32 3
|
||||
|
||||
|
||||
/* File attribute bits for directory entry */
|
||||
|
||||
#define AM_RDO 0x01 /* Read only */
|
||||
#define AM_HID 0x02 /* Hidden */
|
||||
#define AM_SYS 0x04 /* System */
|
||||
#define AM_VOL 0x08 /* Volume label */
|
||||
#define AM_LFN 0x0F /* LFN entry */
|
||||
#define AM_DIR 0x10 /* Directory */
|
||||
#define AM_ARC 0x20 /* Archive */
|
||||
#define AM_MASK 0x3F /* Mask of defined bits */
|
||||
|
||||
|
||||
/* Fast seek function */
|
||||
#define CREATE_LINKMAP 0xFFFFFFFF
|
||||
|
||||
|
||||
/*--------------------------------*/
|
||||
/* Multi-byte word access macros */
|
||||
|
||||
#if _WORD_ACCESS == 1 /* Enable word access to the FAT structure */
|
||||
#define LD_WORD(ptr) (WORD)(*(WORD*)(BYTE*)(ptr))
|
||||
#define LD_DWORD(ptr) (DWORD)(*(DWORD*)(BYTE*)(ptr))
|
||||
#define ST_WORD(ptr,val) *(WORD*)(BYTE*)(ptr)=(WORD)(val)
|
||||
#define ST_DWORD(ptr,val) *(DWORD*)(BYTE*)(ptr)=(DWORD)(val)
|
||||
#else /* Use byte-by-byte access to the FAT structure */
|
||||
#define LD_WORD(ptr) (WORD)(((WORD)*(BYTE*)((ptr)+1)<<8)|(WORD)*(BYTE*)(ptr))
|
||||
#define LD_DWORD(ptr) (DWORD)(((DWORD)*(BYTE*)((ptr)+3)<<24)|((DWORD)*(BYTE*)((ptr)+2)<<16)|((WORD)*(BYTE*)((ptr)+1)<<8)|*(BYTE*)(ptr))
|
||||
#define ST_WORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *(BYTE*)((ptr)+1)=(BYTE)((WORD)(val)>>8)
|
||||
#define ST_DWORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *(BYTE*)((ptr)+1)=(BYTE)((WORD)(val)>>8); *(BYTE*)((ptr)+2)=(BYTE)((DWORD)(val)>>16); *(BYTE*)((ptr)+3)=(BYTE)((DWORD)(val)>>24)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _FATFS */
|
||||
@@ -0,0 +1,221 @@
|
||||
/*
|
||||
* Authors (alphabetical order)
|
||||
* - Bertrand Songis <bsongis@gmail.com>
|
||||
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
|
||||
* - Cameron Weeks <th9xer@gmail.com>
|
||||
* - Erez Raviv
|
||||
* - Jean-Pierre Parisy
|
||||
* - Karl Szmutny <shadow@privy.de>
|
||||
* - Michael Blandford
|
||||
* - Michal Hlavinka
|
||||
* - Pat Mackenzie
|
||||
* - Philip Moss
|
||||
* - Rob Thomson
|
||||
* - Romolo Manfredini <romolo.manfredini@gmail.com>
|
||||
* - Thomas Husterer
|
||||
*
|
||||
* open9x is based on code named
|
||||
* gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/,
|
||||
* er9x by Erez Raviv: http://code.google.com/p/er9x/,
|
||||
* and the original (and ongoing) project by
|
||||
* Thomas Husterer, th9x: http://code.google.com/p/th9x/
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
/*---------------------------------------------------------------------------/
|
||||
/ FatFs - FAT file system module configuration file R0.08a (C)ChaN, 2010
|
||||
/----------------------------------------------------------------------------/
|
||||
/
|
||||
/ CAUTION! Do not forget to make clean the project after any changes to
|
||||
/ the configuration options.
|
||||
/
|
||||
/----------------------------------------------------------------------------*/
|
||||
#ifndef _FFCONF
|
||||
#define _FFCONF 8255 /* Revision ID */
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------/
|
||||
/ Function and Buffer Configurations
|
||||
/----------------------------------------------------------------------------*/
|
||||
|
||||
#define _FS_TINY 1 /* 0:Normal or 1:Tiny */
|
||||
/* When _FS_TINY is set to 1, FatFs uses the sector buffer in the file system
|
||||
/ object instead of the sector buffer in the individual file object for file
|
||||
/ data transfer. This reduces memory consumption 512 bytes each file object. */
|
||||
|
||||
|
||||
#define _FS_READONLY 0 /* 0:Read/Write or 1:Read only */
|
||||
/* Setting _FS_READONLY to 1 defines read only configuration. This removes
|
||||
/ writing functions, f_write, f_sync, f_unlink, f_mkdir, f_chmod, f_rename,
|
||||
/ f_truncate and useless f_getfree. */
|
||||
|
||||
|
||||
#define _FS_MINIMIZE 0 /* 0 to 3 */
|
||||
/* The _FS_MINIMIZE option defines minimization level to remove some functions.
|
||||
/
|
||||
/ 0: Full function.
|
||||
/ 1: f_stat, f_getfree, f_unlink, f_mkdir, f_chmod, f_truncate and f_rename
|
||||
/ are removed.
|
||||
/ 2: f_opendir and f_readdir are removed in addition to 1.
|
||||
/ 3: f_lseek is removed in addition to 2. */
|
||||
|
||||
|
||||
#define _USE_STRFUNC 1 /* 0:Disable or 1/2:Enable */
|
||||
/* To enable string functions, set _USE_STRFUNC to 1 or 2. */
|
||||
|
||||
|
||||
#define _USE_MKFS 1 /* 0:Disable or 1:Enable */
|
||||
/* To enable f_mkfs function, set _USE_MKFS to 1 and set _FS_READONLY to 0 */
|
||||
|
||||
|
||||
#define _USE_FORWARD 0 /* 0:Disable or 1:Enable */
|
||||
/* To enable f_forward function, set _USE_FORWARD to 1 and set _FS_TINY to 1. */
|
||||
|
||||
|
||||
#define _USE_FASTSEEK 0 /* 0:Disable or 1:Enable */
|
||||
/* To enable fast seek feature, set _USE_FASTSEEK to 1. */
|
||||
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------/
|
||||
/ Locale and Namespace Configurations
|
||||
/----------------------------------------------------------------------------*/
|
||||
|
||||
#define _CODE_PAGE 932
|
||||
/* The _CODE_PAGE specifies the OEM code page to be used on the target system.
|
||||
/ Incorrect setting of the code page can cause a file open failure.
|
||||
/
|
||||
/ 932 - Japanese Shift-JIS (DBCS, OEM, Windows)
|
||||
/ 936 - Simplified Chinese GBK (DBCS, OEM, Windows)
|
||||
/ 949 - Korean (DBCS, OEM, Windows)
|
||||
/ 950 - Traditional Chinese Big5 (DBCS, OEM, Windows)
|
||||
/ 1250 - Central Europe (Windows)
|
||||
/ 1251 - Cyrillic (Windows)
|
||||
/ 1252 - Latin 1 (Windows)
|
||||
/ 1253 - Greek (Windows)
|
||||
/ 1254 - Turkish (Windows)
|
||||
/ 1255 - Hebrew (Windows)
|
||||
/ 1256 - Arabic (Windows)
|
||||
/ 1257 - Baltic (Windows)
|
||||
/ 1258 - Vietnam (OEM, Windows)
|
||||
/ 437 - U.S. (OEM)
|
||||
/ 720 - Arabic (OEM)
|
||||
/ 737 - Greek (OEM)
|
||||
/ 775 - Baltic (OEM)
|
||||
/ 850 - Multilingual Latin 1 (OEM)
|
||||
/ 858 - Multilingual Latin 1 + Euro (OEM)
|
||||
/ 852 - Latin 2 (OEM)
|
||||
/ 855 - Cyrillic (OEM)
|
||||
/ 866 - Russian (OEM)
|
||||
/ 857 - Turkish (OEM)
|
||||
/ 862 - Hebrew (OEM)
|
||||
/ 874 - Thai (OEM, Windows)
|
||||
/ 1 - ASCII only (Valid for non LFN cfg.)
|
||||
*/
|
||||
|
||||
|
||||
#define _USE_LFN 0 /* 0 to 3 */
|
||||
#define _MAX_LFN 255 /* Maximum LFN length to handle (12 to 255) */
|
||||
/* The _USE_LFN option switches the LFN support.
|
||||
/
|
||||
/ 0: Disable LFN feature. _MAX_LFN and _LFN_UNICODE have no effect.
|
||||
/ 1: Enable LFN with static working buffer on the BSS. Always NOT reentrant.
|
||||
/ 2: Enable LFN with dynamic working buffer on the STACK.
|
||||
/ 3: Enable LFN with dynamic working buffer on the HEAP.
|
||||
/
|
||||
/ The LFN working buffer occupies (_MAX_LFN + 1) * 2 bytes. To enable LFN,
|
||||
/ Unicode handling functions ff_convert() and ff_wtoupper() must be added
|
||||
/ to the project. When enable to use heap, memory control functions
|
||||
/ ff_memalloc() and ff_memfree() must be added to the project. */
|
||||
|
||||
|
||||
#define _LFN_UNICODE 0 /* 0:ANSI/OEM or 1:Unicode */
|
||||
/* To switch the character code set on FatFs API to Unicode,
|
||||
/ enable LFN feature and set _LFN_UNICODE to 1. */
|
||||
|
||||
|
||||
#define _FS_RPATH 2 /* 0 to 2 */
|
||||
/* The _FS_RPATH option configures relative path feature.
|
||||
/
|
||||
/ 0: Disable relative path feature and remove related functions.
|
||||
/ 1: Enable relative path. f_chdrive() and f_chdir() are available.
|
||||
/ 2: f_getcwd() is available in addition to 1.
|
||||
/
|
||||
/ Note that output of the f_readdir fnction is affected by this option. */
|
||||
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------/
|
||||
/ Physical Drive Configurations
|
||||
/----------------------------------------------------------------------------*/
|
||||
|
||||
#define _VOLUMES 1
|
||||
/* Number of volumes (logical drives) to be used. */
|
||||
|
||||
|
||||
#define _MAX_SS 512 /* 512, 1024, 2048 or 4096 */
|
||||
/* Maximum sector size to be handled.
|
||||
/ Always set 512 for memory card and hard disk but a larger value may be
|
||||
/ required for floppy disk (512/1024) and optical disk (512/2048).
|
||||
/ When _MAX_SS is larger than 512, GET_SECTOR_SIZE command must be implememted
|
||||
/ to the disk_ioctl function. */
|
||||
|
||||
|
||||
#define _MULTI_PARTITION 0 /* 0:Single partition or 1:Multiple partition */
|
||||
/* When set to 0, each volume is bound to the same physical drive number and
|
||||
/ it can mount only first primaly partition. When it is set to 1, each volume
|
||||
/ is tied to the partitions listed in VolToPart[]. */
|
||||
|
||||
|
||||
#define _USE_ERASE 0 /* 0:Disable or 1:Enable */
|
||||
/* To enable sector erase feature, set _USE_ERASE to 1. */
|
||||
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------/
|
||||
/ System Configurations
|
||||
/----------------------------------------------------------------------------*/
|
||||
|
||||
#define _WORD_ACCESS 0 /* 0 or 1 */
|
||||
/* Set 0 first and it is always compatible with all platforms. The _WORD_ACCESS
|
||||
/ option defines which access method is used to the word data on the FAT volume.
|
||||
/
|
||||
/ 0: Byte-by-byte access.
|
||||
/ 1: Word access. Do not choose this unless following condition is met.
|
||||
/
|
||||
/ When the byte order on the memory is big-endian or address miss-aligned word
|
||||
/ access results incorrect behavior, the _WORD_ACCESS must be set to 0.
|
||||
/ If it is not the case, the value can also be set to 1 to improve the
|
||||
/ performance and code size. */
|
||||
|
||||
|
||||
/* Include a header file here to define sync object types on the O/S */
|
||||
/* #include <windows.h>, <ucos_ii.h.h>, <semphr.h> or ohters. */
|
||||
|
||||
#define _FS_REENTRANT 0 /* 0:Disable or 1:Enable */
|
||||
#define _FS_TIMEOUT 1000 /* Timeout period in unit of time ticks */
|
||||
#define _SYNC_t HANDLE /* O/S dependent type of sync object. e.g. HANDLE, OS_EVENT*, ID and etc.. */
|
||||
|
||||
/* The _FS_REENTRANT option switches the reentrancy of the FatFs module.
|
||||
/
|
||||
/ 0: Disable reentrancy. _SYNC_t and _FS_TIMEOUT have no effect.
|
||||
/ 1: Enable reentrancy. Also user provided synchronization handlers,
|
||||
/ ff_req_grant, ff_rel_grant, ff_del_syncobj and ff_cre_syncobj
|
||||
/ function must be added to the project. */
|
||||
|
||||
|
||||
#define _FS_SHARE 0 /* 0:Disable or >=1:Enable */
|
||||
/* To enable file shareing feature, set _FS_SHARE to 1 or greater. The value
|
||||
defines how many files can be opened simultaneously. */
|
||||
|
||||
|
||||
#endif /* _FFCONFIG */
|
||||
@@ -0,0 +1,495 @@
|
||||
/*
|
||||
* Authors (alphabetical order)
|
||||
* - Bertrand Songis <bsongis@gmail.com>
|
||||
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
|
||||
* - Cameron Weeks <th9xer@gmail.com>
|
||||
* - Erez Raviv
|
||||
* - Jean-Pierre Parisy
|
||||
* - Karl Szmutny <shadow@privy.de>
|
||||
* - Michael Blandford
|
||||
* - Michal Hlavinka
|
||||
* - Pat Mackenzie
|
||||
* - Philip Moss
|
||||
* - Rob Thomson
|
||||
* - Romolo Manfredini <romolo.manfredini@gmail.com>
|
||||
* - Thomas Husterer
|
||||
*
|
||||
* open9x is based on code named
|
||||
* gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/,
|
||||
* er9x by Erez Raviv: http://code.google.com/p/er9x/,
|
||||
* and the original (and ongoing) project by
|
||||
* Thomas Husterer, th9x: http://code.google.com/p/th9x/
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "gtime.h"
|
||||
|
||||
#define LEAP_SECONDS_POSSIBLE 0
|
||||
|
||||
/* Shift A right by B bits portably, by dividing A by 2**B and
|
||||
truncating towards minus infinity. A and B should be free of side
|
||||
effects, and B should be in the range 0 <= B <= INT_BITS - 2, where
|
||||
INT_BITS is the number of useful bits in an int. GNU code can
|
||||
assume that INT_BITS is at least 32.
|
||||
|
||||
ISO C99 says that A >> B is implementation-defined if A < 0. Some
|
||||
implementations (e.g., UNICOS 9.0 on a Cray Y-MP EL) don't shift
|
||||
right in the usual way when A < 0, so SHR falls back on division if
|
||||
ordinary A >> B doesn't seem to be the usual signed shift. */
|
||||
#define SHR(a, b) \
|
||||
(-1 >> 1 == -1 \
|
||||
? (a) >> (b) \
|
||||
: (a) / (1 << (b)) - ((a) % (1 << (b)) < 0))
|
||||
|
||||
/* The extra casts in the following macros work around compiler bugs,
|
||||
e.g., in Cray C 5.0.3.0. */
|
||||
|
||||
/* True if the arithmetic type T is an integer type. bool counts as
|
||||
an integer. */
|
||||
#define TYPE_IS_INTEGER(t) ((t) 1.5 == 1)
|
||||
|
||||
/* True if negative values of the signed integer type T use two's
|
||||
complement, ones' complement, or signed magnitude representation,
|
||||
respectively. Much GNU code assumes two's complement, but some
|
||||
people like to be portable to all possible C hosts. */
|
||||
#define TYPE_TWOS_COMPLEMENT(t) ((t) ~ (t) 0 == (t) -1)
|
||||
#define TYPE_ONES_COMPLEMENT(t) ((t) ~ (t) 0 == 0)
|
||||
#define TYPE_SIGNED_MAGNITUDE(t) ((t) ~ (t) 0 < (t) -1)
|
||||
|
||||
/* True if the arithmetic type T is signed. */
|
||||
#define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
|
||||
|
||||
/* The maximum and minimum values for the integer type T. These
|
||||
macros have undefined behavior if T is signed and has padding bits.
|
||||
If this is a problem for you, please let us know how to fix it for
|
||||
your host. */
|
||||
#define TYPE_MINIMUM(t) \
|
||||
((t) (! TYPE_SIGNED (t) \
|
||||
? (t) 0 \
|
||||
: TYPE_SIGNED_MAGNITUDE (t) \
|
||||
? ~ (t) 0 \
|
||||
: ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1)))
|
||||
#define TYPE_MAXIMUM(t) \
|
||||
((t) (! TYPE_SIGNED (t) \
|
||||
? (t) -1 \
|
||||
: ~ (~ (t) 0 << (sizeof (t) * CHAR_BIT - 1))))
|
||||
|
||||
#ifndef TIME_T_MIN
|
||||
# define TIME_T_MIN TYPE_MINIMUM (gtime_t)
|
||||
#endif
|
||||
#ifndef TIME_T_MAX
|
||||
# define TIME_T_MAX TYPE_MAXIMUM (gtime_t)
|
||||
#endif
|
||||
#define TIME_T_MIDPOINT (SHR (TIME_T_MIN + TIME_T_MAX, 1) + 1)
|
||||
|
||||
/* Verify a requirement at compile-time (unlike assert, which is runtime). */
|
||||
#define verify(name, assertion) struct name { char a[(assertion) ? 1 : -1]; }
|
||||
|
||||
verify (gtime_t_is_integer, TYPE_IS_INTEGER (gtime_t));
|
||||
verify (twos_complement_arithmetic, TYPE_TWOS_COMPLEMENT (int));
|
||||
/* The code also assumes that signed integer overflow silently wraps
|
||||
around, but this assumption can't be stated without causing a
|
||||
diagnostic on some hosts. */
|
||||
|
||||
#define EPOCH_YEAR 1970
|
||||
#define TM_YEAR_BASE 1900
|
||||
verify (base_year_is_a_multiple_of_100, TM_YEAR_BASE % 100 == 0);
|
||||
|
||||
#define SECS_PER_HOUR 3600ul
|
||||
#define SECS_PER_DAY 86400ul
|
||||
|
||||
/* Return 1 if YEAR + TM_YEAR_BASE is a leap year. */
|
||||
static inline int
|
||||
leapyear (long int year)
|
||||
{
|
||||
/* Don't add YEAR to TM_YEAR_BASE, as that might overflow.
|
||||
Also, work even if YEAR is negative. */
|
||||
return
|
||||
((year & 3) == 0
|
||||
&& (year % 100 != 0
|
||||
|| ((year / 100) & 3) == (- (TM_YEAR_BASE / 100) & 3)));
|
||||
}
|
||||
|
||||
const unsigned short int __mon_yday[2][13] =
|
||||
{
|
||||
/* Normal years. */
|
||||
{ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
|
||||
/* Leap years. */
|
||||
{ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
|
||||
};
|
||||
|
||||
/* Compute the `struct tm' representation of *T,
|
||||
offset OFFSET seconds east of UTC,
|
||||
and store year, yday, mon, mday, wday, hour, min, sec into *TP.
|
||||
Return nonzero if successful. */
|
||||
int
|
||||
__offtime (
|
||||
gtime_t *t,
|
||||
long int offset,
|
||||
struct gtm *tp)
|
||||
{
|
||||
long int days, rem, y;
|
||||
const unsigned short int *ip;
|
||||
|
||||
days = *t / SECS_PER_DAY;
|
||||
rem = *t % SECS_PER_DAY;
|
||||
rem += offset;
|
||||
while (rem < 0)
|
||||
{
|
||||
rem += SECS_PER_DAY;
|
||||
--days;
|
||||
}
|
||||
while (rem >= (long int)SECS_PER_DAY)
|
||||
{
|
||||
rem -= SECS_PER_DAY;
|
||||
++days;
|
||||
}
|
||||
tp->tm_hour = rem / SECS_PER_HOUR;
|
||||
rem %= SECS_PER_HOUR;
|
||||
tp->tm_min = rem / 60;
|
||||
tp->tm_sec = rem % 60;
|
||||
/* January 1, 1970 was a Thursday. */
|
||||
tp->tm_wday = (4 + days) % 7;
|
||||
if (tp->tm_wday < 0)
|
||||
tp->tm_wday += 7;
|
||||
y = 1970;
|
||||
|
||||
#define DIV(a, b) ((a) / (b) - ((a) % (b) < 0))
|
||||
#define LEAPS_THRU_END_OF(y) (DIV (y, 4) - DIV (y, 100) + DIV (y, 400))
|
||||
|
||||
while (days < 0 || days >= (leapyear (y) ? 366 : 365))
|
||||
{
|
||||
/* Guess a corrected year, assuming 365 days per year. */
|
||||
long int yg = y + days / 365 - (days % 365 < 0);
|
||||
|
||||
/* Adjust DAYS and Y to match the guessed year. */
|
||||
days -= ((yg - y) * 365
|
||||
+ LEAPS_THRU_END_OF (yg - 1)
|
||||
- LEAPS_THRU_END_OF (y - 1));
|
||||
y = yg;
|
||||
}
|
||||
tp->tm_year = y - 1900;
|
||||
if (tp->tm_year != y - 1900)
|
||||
{
|
||||
/* The year cannot be represented due to overflow. */
|
||||
// __set_errno (EOVERFLOW);
|
||||
return 0;
|
||||
}
|
||||
tp->tm_yday = days;
|
||||
ip = __mon_yday[leapyear(y)];
|
||||
for (y = 11; days < (long int) ip[y]; --y)
|
||||
continue;
|
||||
days -= ip[y];
|
||||
tp->tm_mon = y;
|
||||
tp->tm_mday = days + 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* time_r function implementations */
|
||||
// G: No time zones in our implementation so just do the converion from gtime_t to struct tm
|
||||
struct gtm *
|
||||
__localtime_r (gtime_t * t, struct gtm * tp)
|
||||
{
|
||||
__offtime(t, 0, tp);
|
||||
return tp;
|
||||
}
|
||||
|
||||
|
||||
/* Return an integer value measuring (YEAR1-YDAY1 HOUR1:MIN1:SEC1) -
|
||||
(YEAR0-YDAY0 HOUR0:MIN0:SEC0) in seconds, assuming that the clocks
|
||||
were not adjusted between the time stamps.
|
||||
|
||||
The YEAR values uses the same numbering as TP->tm_year. Values
|
||||
need not be in the usual range. However, YEAR1 must not be less
|
||||
than 2 * INT_MIN or greater than 2 * INT_MAX.
|
||||
|
||||
The result may overflow. It is the caller's responsibility to
|
||||
detect overflow. */
|
||||
|
||||
static inline gtime_t
|
||||
ydhms_diff (long int year1, long int yday1, int hour1, int min1, int sec1,
|
||||
int year0, int yday0, int hour0, int min0, int sec0)
|
||||
{
|
||||
verify (C99_integer_division, -1 / 2 == 0);
|
||||
verify (long_int_year_and_yday_are_wide_enough,
|
||||
INT_MAX <= LONG_MAX / 2 || TIME_T_MAX <= UINT_MAX);
|
||||
|
||||
/* Compute intervening leap days correctly even if year is negative.
|
||||
Take care to avoid integer overflow here. */
|
||||
int a4 = SHR (year1, 2) + SHR (TM_YEAR_BASE, 2) - ! (year1 & 3);
|
||||
int b4 = SHR (year0, 2) + SHR (TM_YEAR_BASE, 2) - ! (year0 & 3);
|
||||
int a100 = a4 / 25 - (a4 % 25 < 0);
|
||||
int b100 = b4 / 25 - (b4 % 25 < 0);
|
||||
int a400 = SHR (a100, 2);
|
||||
int b400 = SHR (b100, 2);
|
||||
int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
|
||||
|
||||
/* Compute the desired time in gtime_t precision. Overflow might
|
||||
occur here. */
|
||||
gtime_t tyear1 = year1;
|
||||
gtime_t years = tyear1 - year0;
|
||||
gtime_t days = 365 * years + yday1 - yday0 + intervening_leap_days;
|
||||
gtime_t hours = 24 * days + hour1 - hour0;
|
||||
gtime_t minutes = 60 * hours + min1 - min0;
|
||||
gtime_t seconds = 60 * minutes + sec1 - sec0;
|
||||
return seconds;
|
||||
}
|
||||
|
||||
/* Return a gtime_t value corresponding to (YEAR-YDAY HOUR:MIN:SEC),
|
||||
assuming that *T corresponds to *TP and that no clock adjustments
|
||||
occurred between *TP and the desired time.
|
||||
If TP is null, return a value not equal to *T; this avoids false matches.
|
||||
If overflow occurs, yield the minimal or maximal value, except do not
|
||||
yield a value equal to *T. */
|
||||
static gtime_t
|
||||
guess_time_tm (long int year, long int yday, int hour, int min, int sec,
|
||||
gtime_t *t, struct gtm *tp)
|
||||
{
|
||||
if (tp)
|
||||
{
|
||||
gtime_t d = ydhms_diff (year, yday, hour, min, sec,
|
||||
tp->tm_year, tp->tm_yday,
|
||||
tp->tm_hour, tp->tm_min, tp->tm_sec);
|
||||
gtime_t t1 = *t + d;
|
||||
if ((t1 < *t) == (TYPE_SIGNED (gtime_t) ? d < 0 : TIME_T_MAX / 2 < d))
|
||||
return t1;
|
||||
}
|
||||
|
||||
/* Overflow occurred one way or another. Return the nearest result
|
||||
that is actually in range, except don't report a zero difference
|
||||
if the actual difference is nonzero, as that would cause a false
|
||||
match; and don't oscillate between two values, as that would
|
||||
confuse the spring-forward gap detector. */
|
||||
return (*t < TIME_T_MIDPOINT
|
||||
? (*t <= TIME_T_MIN + 1 ? *t + 1 : TIME_T_MIN)
|
||||
: (TIME_T_MAX - 1 <= *t ? *t - 1 : TIME_T_MAX));
|
||||
}
|
||||
|
||||
/* Use CONVERT to convert *T to a broken down time in *TP.
|
||||
If *T is out of range for conversion, adjust it so that
|
||||
it is the nearest in-range value and then convert that. */
|
||||
static struct gtm *
|
||||
ranged_convert (struct gtm *(*convert) (gtime_t *, struct gtm *),
|
||||
gtime_t *t, struct gtm *tp)
|
||||
{
|
||||
struct gtm *r = convert (t, tp);
|
||||
|
||||
if (!r && *t)
|
||||
{
|
||||
gtime_t bad = *t;
|
||||
gtime_t ok = 0;
|
||||
|
||||
/* BAD is a known unconvertible gtime_t, and OK is a known good one.
|
||||
Use binary search to narrow the range between BAD and OK until
|
||||
they differ by 1. */
|
||||
while (bad != ok + (bad < 0 ? -1 : 1))
|
||||
{
|
||||
gtime_t mid = *t = (bad < 0
|
||||
? bad + ((ok - bad) >> 1)
|
||||
: ok + ((bad - ok) >> 1));
|
||||
r = convert (t, tp);
|
||||
if (r)
|
||||
ok = mid;
|
||||
else
|
||||
bad = mid;
|
||||
}
|
||||
|
||||
if (!r && ok)
|
||||
{
|
||||
/* The last conversion attempt failed;
|
||||
revert to the most recent successful attempt. */
|
||||
*t = ok;
|
||||
r = convert (t, tp);
|
||||
}
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Convert *TP to a gtime_t value, inverting
|
||||
the monotonic and mostly-unit-linear conversion function CONVERT.
|
||||
Use *OFFSET to keep track of a guess at the offset of the result,
|
||||
compared to what the result would be for UTC without leap seconds.
|
||||
If *OFFSET's guess is correct, only one CONVERT call is needed.
|
||||
This function is external because it is used also by timegm.c. */
|
||||
gtime_t
|
||||
__mktime_internal (struct gtm *tp,
|
||||
struct gtm *(*convert) (gtime_t *, struct gtm *),
|
||||
gtime_t *offset)
|
||||
{
|
||||
gtime_t t, gt, t0, t1, t2;
|
||||
struct gtm tm;
|
||||
|
||||
/* The maximum number of probes (calls to CONVERT) should be enough
|
||||
to handle any combinations of time zone rule changes, solar time,
|
||||
leap seconds, and oscillations around a spring-forward gap.
|
||||
POSIX.1 prohibits leap seconds, but some hosts have them anyway. */
|
||||
int remaining_probes = 6;
|
||||
|
||||
/* Time requested. Copy it in case CONVERT modifies *TP; this can
|
||||
occur if TP is localtime's returned value and CONVERT is localtime. */
|
||||
int sec = tp->tm_sec;
|
||||
int min = tp->tm_min;
|
||||
int hour = tp->tm_hour;
|
||||
int mday = tp->tm_mday;
|
||||
int mon = tp->tm_mon;
|
||||
int year_requested = tp->tm_year;
|
||||
|
||||
/* Ensure that mon is in range, and set year accordingly. */
|
||||
int mon_remainder = mon % 12;
|
||||
int negative_mon_remainder = mon_remainder < 0;
|
||||
int mon_years = mon / 12 - negative_mon_remainder;
|
||||
long int lyear_requested = year_requested;
|
||||
long int year = lyear_requested + mon_years;
|
||||
|
||||
/* The other values need not be in range:
|
||||
the remaining code handles minor overflows correctly,
|
||||
assuming int and gtime_t arithmetic wraps around.
|
||||
Major overflows are caught at the end. */
|
||||
|
||||
/* Calculate day of year from year, month, and day of month.
|
||||
The result need not be in range. */
|
||||
int mon_yday = ((__mon_yday[leapyear (year)]
|
||||
[mon_remainder + 12 * negative_mon_remainder])
|
||||
- 1);
|
||||
long int lmday = mday;
|
||||
long int yday = mon_yday + lmday;
|
||||
|
||||
gtime_t guessed_offset = *offset;
|
||||
|
||||
int sec_requested = sec;
|
||||
|
||||
/*
|
||||
if (LEAP_SECONDS_POSSIBLE)
|
||||
{
|
||||
// Handle out-of-range seconds specially,
|
||||
// since ydhms_tm_diff assumes every minute has 60 seconds.
|
||||
if (sec < 0)
|
||||
sec = 0;
|
||||
if (59 < sec)
|
||||
sec = 59;
|
||||
}
|
||||
*/
|
||||
|
||||
/* Invert CONVERT by probing. First assume the same offset as last
|
||||
time. */
|
||||
|
||||
t0 = ydhms_diff (year, yday, hour, min, sec,
|
||||
EPOCH_YEAR - TM_YEAR_BASE, 0, 0, 0, - guessed_offset);
|
||||
|
||||
if (TIME_T_MAX / INT_MAX / 366 / 24 / 60 / 60 < 3)
|
||||
{
|
||||
/* gtime_t isn't large enough to rule out overflows, so check
|
||||
for major overflows. A gross check suffices, since if t0
|
||||
has overflowed, it is off by a multiple of TIME_T_MAX -
|
||||
TIME_T_MIN + 1. So ignore any component of the difference
|
||||
that is bounded by a small value. */
|
||||
|
||||
/* Approximate log base 2 of the number of time units per
|
||||
biennium. A biennium is 2 years; use this unit instead of
|
||||
years to avoid integer overflow. For example, 2 average
|
||||
Gregorian years are 2 * 365.2425 * 24 * 60 * 60 seconds,
|
||||
which is 63113904 seconds, and rint (log2 (63113904)) is
|
||||
26. */
|
||||
int ALOG2_SECONDS_PER_BIENNIUM = 26;
|
||||
int ALOG2_MINUTES_PER_BIENNIUM = 20;
|
||||
int ALOG2_HOURS_PER_BIENNIUM = 14;
|
||||
int ALOG2_DAYS_PER_BIENNIUM = 10;
|
||||
int LOG2_YEARS_PER_BIENNIUM = 1;
|
||||
|
||||
int approx_requested_biennia =
|
||||
(SHR (year_requested, LOG2_YEARS_PER_BIENNIUM)
|
||||
- SHR (EPOCH_YEAR - TM_YEAR_BASE, LOG2_YEARS_PER_BIENNIUM)
|
||||
+ SHR (mday, ALOG2_DAYS_PER_BIENNIUM)
|
||||
+ SHR (hour, ALOG2_HOURS_PER_BIENNIUM)
|
||||
+ SHR (min, ALOG2_MINUTES_PER_BIENNIUM)
|
||||
+ (LEAP_SECONDS_POSSIBLE
|
||||
? 0
|
||||
: SHR (sec, ALOG2_SECONDS_PER_BIENNIUM)));
|
||||
|
||||
int approx_biennia = SHR (t0, ALOG2_SECONDS_PER_BIENNIUM);
|
||||
int diff = approx_biennia - approx_requested_biennia;
|
||||
int abs_diff = diff < 0 ? - diff : diff;
|
||||
|
||||
/* IRIX 4.0.5 cc miscalculates TIME_T_MIN / 3: it erroneously
|
||||
gives a positive value of 715827882. Setting a variable
|
||||
first then doing math on it seems to work.
|
||||
(ghazi@caip.rutgers.edu) */
|
||||
gtime_t time_t_max = TIME_T_MAX;
|
||||
gtime_t time_t_min = TIME_T_MIN;
|
||||
gtime_t overflow_threshold =
|
||||
(time_t_max / 3 - time_t_min / 3) >> ALOG2_SECONDS_PER_BIENNIUM;
|
||||
|
||||
if (overflow_threshold < abs_diff)
|
||||
{
|
||||
/* Overflow occurred. Try repairing it; this might work if
|
||||
the time zone offset is enough to undo the overflow. */
|
||||
gtime_t repaired_t0 = -1 - t0;
|
||||
approx_biennia = SHR (repaired_t0, ALOG2_SECONDS_PER_BIENNIUM);
|
||||
diff = approx_biennia - approx_requested_biennia;
|
||||
abs_diff = diff < 0 ? - diff : diff;
|
||||
if (overflow_threshold < abs_diff)
|
||||
return -1;
|
||||
guessed_offset += repaired_t0 - t0;
|
||||
t0 = repaired_t0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Repeatedly use the error to improve the guess. */
|
||||
|
||||
for (t = t1 = t2 = t0;
|
||||
(gt = guess_time_tm (year, yday, hour, min, sec, &t,
|
||||
ranged_convert (convert, &t, &tm)),
|
||||
t != gt);
|
||||
t1 = t2, t2 = t, t = gt)
|
||||
if (t == t1 && t != t2)
|
||||
goto offset_found;
|
||||
else if (--remaining_probes == 0)
|
||||
return -1;
|
||||
|
||||
offset_found:
|
||||
*offset = guessed_offset + t - t0;
|
||||
|
||||
if (LEAP_SECONDS_POSSIBLE && sec_requested != tm.tm_sec)
|
||||
{
|
||||
/* Adjust time to reflect the tm_sec requested, not the normalized value.
|
||||
Also, repair any damage from a false match due to a leap second. */
|
||||
int sec_adjustment = (sec == 0 && tm.tm_sec == 60) - sec;
|
||||
t1 = t + sec_requested;
|
||||
t2 = t1 + sec_adjustment;
|
||||
if (((t1 < t) != (sec_requested < 0))
|
||||
| ((t2 < t1) != (sec_adjustment < 0))
|
||||
| ! convert (&t2, &tm))
|
||||
return -1;
|
||||
t = t2;
|
||||
}
|
||||
|
||||
*tp = tm;
|
||||
return t;
|
||||
}
|
||||
|
||||
/* Convert *TP to a gtime_t value. */
|
||||
gtime_t
|
||||
mktime (struct gtm *tp)
|
||||
{
|
||||
// no time zone stuff. Just do the math ;)
|
||||
static gtime_t localtime_offset;
|
||||
return __mktime_internal (tp, __localtime_r, &localtime_offset);
|
||||
}
|
||||
|
||||
/* Fill a (struct tm) TP* from a given gtime_t time stamp */
|
||||
gtime_t
|
||||
filltm(gtime_t *t, struct gtm *tp)
|
||||
{
|
||||
return __offtime(t, 0, tp);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Authors (alphabetical order)
|
||||
* - Bertrand Songis <bsongis@gmail.com>
|
||||
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
|
||||
* - Cameron Weeks <th9xer@gmail.com>
|
||||
* - Erez Raviv
|
||||
* - Jean-Pierre Parisy
|
||||
* - Karl Szmutny <shadow@privy.de>
|
||||
* - Michael Blandford
|
||||
* - Michal Hlavinka
|
||||
* - Pat Mackenzie
|
||||
* - Philip Moss
|
||||
* - Rob Thomson
|
||||
* - Romolo Manfredini <romolo.manfredini@gmail.com>
|
||||
* - Thomas Husterer
|
||||
*
|
||||
* open9x is based on code named
|
||||
* gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/,
|
||||
* er9x by Erez Raviv: http://code.google.com/p/er9x/,
|
||||
* and the original (and ongoing) project by
|
||||
* Thomas Husterer, th9x: http://code.google.com/p/th9x/
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef g9x_time_h
|
||||
#define g9x_time_h
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <limits.h>
|
||||
|
||||
#undef CHAR_BIT
|
||||
#define CHAR_BIT 8
|
||||
|
||||
typedef long int gtime_t;
|
||||
|
||||
struct gtm
|
||||
{
|
||||
int8_t tm_sec; /* Seconds. [0-60] (1 leap second) */
|
||||
int8_t tm_min; /* Minutes. [0-59] */
|
||||
int8_t tm_hour; /* Hours. [0-23] */
|
||||
int8_t tm_mday; /* Day. [1-31] */
|
||||
int8_t tm_mon; /* Month. [0-11] */
|
||||
int8_t tm_year; /* Year - 1900. Limited to the year 2115. Oh no! :P */
|
||||
int8_t tm_wday; /* Day of week. [0-6] */
|
||||
int16_t tm_yday; /* Day of year. [0-365] Needed internally for calculations */
|
||||
};
|
||||
|
||||
extern const unsigned short int __mon_yday[2][13];
|
||||
|
||||
extern gtime_t mktime(struct gtm *tp);
|
||||
extern gtime_t filltm(gtime_t *t, struct gtm *tp);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Authors (alphabetical order)
|
||||
* - Bertrand Songis <bsongis@gmail.com>
|
||||
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
|
||||
* - Cameron Weeks <th9xer@gmail.com>
|
||||
* - Erez Raviv
|
||||
* - Jean-Pierre Parisy
|
||||
* - Karl Szmutny <shadow@privy.de>
|
||||
* - Michael Blandford
|
||||
* - Michal Hlavinka
|
||||
* - Pat Mackenzie
|
||||
* - Philip Moss
|
||||
* - Rob Thomson
|
||||
* - Romolo Manfredini <romolo.manfredini@gmail.com>
|
||||
* - Thomas Husterer
|
||||
*
|
||||
* open9x is based on code named
|
||||
* gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/,
|
||||
* er9x by Erez Raviv: http://code.google.com/p/er9x/,
|
||||
* and the original (and ongoing) project by
|
||||
* Thomas Husterer, th9x: http://code.google.com/p/th9x/
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
/*-------------------------------------------*/
|
||||
/* Integer type definitions for FatFs module */
|
||||
/*-------------------------------------------*/
|
||||
|
||||
#ifndef _INTEGER
|
||||
#define _INTEGER
|
||||
|
||||
#ifdef _WIN32 /* FatFs development platform */
|
||||
|
||||
#include <windows.h>
|
||||
#include <tchar.h>
|
||||
|
||||
#else /* Embedded platform */
|
||||
|
||||
/* These types must be 16-bit, 32-bit or larger integer */
|
||||
typedef int INT;
|
||||
typedef unsigned int UINT;
|
||||
|
||||
/* These types must be 8-bit integer */
|
||||
typedef char CHAR;
|
||||
typedef unsigned char UCHAR;
|
||||
typedef unsigned char BYTE;
|
||||
|
||||
/* These types must be 16-bit integer */
|
||||
typedef short SHORT;
|
||||
typedef unsigned short USHORT;
|
||||
typedef unsigned short WORD;
|
||||
typedef unsigned short WCHAR;
|
||||
|
||||
/* These types must be 32-bit integer */
|
||||
typedef long LONG;
|
||||
typedef unsigned long ULONG;
|
||||
typedef unsigned long DWORD;
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -36,6 +36,7 @@ void init_SDcard()
|
||||
#ifndef SIMU
|
||||
configure_pins( 0xFC000000, PIN_PERIPHERAL | PIN_INPUT | PIN_PER_C | PIN_PORTA | PIN_NO_PULLUP ) ;
|
||||
configure_pins( PIO_PB7, PIN_INPUT | PIN_PORTB | PIN_NO_PULLUP | PIN_NO_PULLDOWN ) ;
|
||||
SD_Init() ;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -31,5 +31,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "diskio.h"
|
||||
#include "ff.h"
|
||||
|
||||
extern void init_SDcard( void ) ;
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,443 +0,0 @@
|
||||
/* ----------------------------------------------------------------------------
|
||||
* ATMEL Microcontroller Software Support
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2008, Atmel Corporation
|
||||
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// \page "sdmmc_spi"
|
||||
///
|
||||
/// !Purpose
|
||||
///
|
||||
/// Implementation for sdcard spi mode physical layer driver. Supply a set of sdcard spi mode's
|
||||
/// interface.
|
||||
///
|
||||
/// !Usage
|
||||
///
|
||||
/// -# SD_Init: Run the SDcard initialization sequence
|
||||
/// -# SD_SPI_Init : Run the SDcard SPI Mode initialization sequence
|
||||
/// -# SD_Stop: Stop the SDcard by sending Cmd12
|
||||
/// -# SD_ReadBlock : Read blocks of data
|
||||
/// -# SD_WriteBlock : Write blocks of data
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// \page "sdcard spi mode initialization and identification"
|
||||
///
|
||||
/// !Purpose
|
||||
///
|
||||
/// sdcard spi mode initialization and identification sequence
|
||||
///
|
||||
/// !Description
|
||||
/// - Host sends Cmd0 to do card reset, card is in "idle state".
|
||||
/// - Host sends Cmd8 and checks the response of the card, only sdcard supports physical
|
||||
/// layer version 2.00 will response correctly to Cmd8, and this command is mandatory to be
|
||||
/// sent before ACmd41 for sdcard which support physical layer version 2.00, to enable new
|
||||
/// functions or to validate a dual-voltage card.
|
||||
/// - refer to "If Cmd8 response ok" branch for the initialize of sdcard 2.0.
|
||||
/// - refer to "If Cmd8 response fail" branch for the initialize of sdcard 1.x, mmc card, sdcard2.0
|
||||
/// with invalid voltage.
|
||||
/// - If Cmd8 response ok
|
||||
/// - Host sends Cmd58 to read OCR register to validate the voltage.
|
||||
/// - If the response to Cmd58 is fail, initialize ends, the card is put into inactive state.
|
||||
/// - If the response to Cmd58 is ok, continue to the next step.
|
||||
/// - Host sends ACmd41* with argument "HCS" equal to "1".
|
||||
/// - If the response to ACmd41 failed, it means the card does not match the voltage
|
||||
/// desired by the host, the card will be put into inactive state, initialize ends.
|
||||
/// - If the response with "CCS" equal to "1", the card is a version 2.0 high capacity sdcard,
|
||||
/// refer to "Card Initialize" for the succeeding initialize sequence.
|
||||
/// - If the response with "CCS" equal to "0", the card is a version 2.0 standard capacity sdcard.
|
||||
/// refer to "Card Initialize" for the succeeding initialize sequence.
|
||||
/// - If Cmd8 response fail
|
||||
/// - Host sends Cmd58 to read OCR register to validate the voltage.
|
||||
/// - If the response to Cmd58 is fail, initialize ends, the card is put into inactive state.
|
||||
/// - If the response to Cmd58 is ok, continue to the next step.
|
||||
/// - Host sends ACmd41* argument "HCS" equal to "0".
|
||||
/// - If the response to ACmd41 ok, the card is a version 1.x sdcard, refer to "Card Initialize" for
|
||||
/// the succeeding initialize sequence.
|
||||
/// - If the response to ACmd41 fails
|
||||
/// - Host sends Cmd0 to reset card.
|
||||
/// - Host sends Cmd1 to card.
|
||||
/// - If card has response to Cmd1, the card is a MMC card, refer to "Card Initialize" for the
|
||||
/// succeeding initialize sequence.
|
||||
/// - If card has no response to Cmd1, the card is either an unknown card or a card does
|
||||
/// not match host's voltage, the initialize ends.
|
||||
/// - Card Initialize
|
||||
/// - At this stage, the initialization and identification process is over, the following steps are done
|
||||
/// for the sdcard's succeeding operation.
|
||||
/// - Host sends Cmd59 to turn sdcard's CRC option off.
|
||||
/// - Host sends Cmd9 to get the Card Specific Data (CSD).
|
||||
///
|
||||
/// \note Send Cmd55 before send ACmd41. \endnote
|
||||
/// \note sdcard include ver 1.x sdcard, ver2.0 standard capacity sdcard, ver2.0 high capacity sdcard \endnote
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// \page "sdcard spi mode write"
|
||||
///
|
||||
/// !Purpose
|
||||
///
|
||||
/// sdcard spi mode write process
|
||||
///
|
||||
/// !Description
|
||||
/// - Make sure sdcard is under "transfer state", if the sdcard is under other state, host will send
|
||||
/// Cmd12 or use stop transmission token to stop multiple block write, and to transit sdcard to
|
||||
/// "stand-by state".
|
||||
/// - Host sends Cmd13 to check sdcard's status, to make sure sdcard is "ready-for-data".
|
||||
/// - Host sends Cmd25 to do multiple blocks write, the address here is different between high capacity
|
||||
/// sdcard and normal sdcard, the address of SDHC is equal to the block number, while normal sdcard's
|
||||
/// address is equal to block number times 512.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// \page "sdcard spi mode read"
|
||||
///
|
||||
/// !Purpose
|
||||
///
|
||||
/// sdcard spi mode read process
|
||||
///
|
||||
/// !Description
|
||||
/// - Make sure sdcard is under "transfer state", if the sdcard is under other state, host will send
|
||||
/// Cmd12 or use stop transmission token to stop multiple block read and to transit sdcard to
|
||||
/// "stand-by state".
|
||||
/// - Host sends Cmd13 to check sdcard's status, to make sure sdcard is "ready-for-data".
|
||||
/// - Host sends Cmd18 to do multiple blocks read, the address here is different between high capacity
|
||||
/// sdcard and normal sdcard, the address of SDHC is equal to the block number, while normal sdcard's
|
||||
/// address is equal to block number times 512.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// \page "sdhc"
|
||||
///
|
||||
/// !Purpose
|
||||
///
|
||||
/// highlight of sdhc
|
||||
///
|
||||
/// !Sdhc initialization and identification
|
||||
///
|
||||
/// - Refer to page "sdcard spi mode initialization and identification" for the initialization and identification
|
||||
/// sequence of a sdhc.
|
||||
///
|
||||
/// !Functional difference between sdhc and standard capacity sdcard
|
||||
///
|
||||
/// - Command argument is different:
|
||||
/// - Sdhc uses block address format in memory access commands*, block length is fixed to 512 bytes.
|
||||
/// - Standard capacity sdcard uses byte address format in memory access commands, block length
|
||||
/// is defined in Cmd16.
|
||||
/// - Partial access and misalign access are disabled in sdhc as the block address is used.
|
||||
/// - Sdhc does not support write-protected commands (Cmd28, Cmd29, Cmd30).
|
||||
///
|
||||
/// \note Memory access commands means block read commands (CMD17, CMD18), block write commands
|
||||
/// (CMD24, CMD25), and block erase commands (CMD32, CMD33).
|
||||
///
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
#ifndef SDCARD_H
|
||||
#define SDCARD_H
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Constants
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
/// There was an error with the SD driver.
|
||||
#define SD_ERROR_DRIVER 1
|
||||
/// The SD card did not answer the command.
|
||||
#define SD_ERROR_NORESPONSE 2
|
||||
/// The SD card did not answer the command.
|
||||
#define SD_ERROR_NOT_INITIALIZED 3
|
||||
/// The SD card is busy
|
||||
#define SD_ERROR_BUSY 4
|
||||
/// The operation is not supported
|
||||
#define SD_ERROR_NOT_SUPPORT 5
|
||||
|
||||
/// SD card block size in bytes.
|
||||
#define SD_BLOCK_SIZE 512
|
||||
/// SD card block size binary shift value
|
||||
#define SD_BLOCK_SIZE_BIT 9
|
||||
|
||||
//- MMC Card Command Types
|
||||
/// Broadcast commands (bc), no response
|
||||
#define MMC_CCT_BC 0
|
||||
/// Broadcase commands with response (bcr)
|
||||
#define MMC_CCT_BCR 1
|
||||
/// Addressed commands (ac), no data transfer on DAT lines
|
||||
#define MMC_CCT_AC 2
|
||||
/// Addressed data transfer commands (adtc), data transfer on DAT lines
|
||||
#define MMC_CCT_ADTC 3
|
||||
|
||||
//- MMC Card Command Classes (CCC)
|
||||
/// Class 0: basic
|
||||
#define MMC_CCC_BASIC 0
|
||||
/// Class 1: stream read
|
||||
#define MMC_CCC_STREAM_READ 1
|
||||
/// Class 2: block read
|
||||
#define MMC_CCC_BLOCK_READ 2
|
||||
/// Class 3: stream write
|
||||
#define MMC_CCC_STREAM_WRITE 3
|
||||
/// Class 4: block write
|
||||
#define MMC_CCC_BLOCK_WRITE 4
|
||||
/// Class 5: erase
|
||||
#define MMC_CCC_ERASE 5
|
||||
/// Class 6: write protection
|
||||
#define MMC_CCC_WRITE_PROTECTION 6
|
||||
/// Class 7: lock card
|
||||
#define MMC_CCC_LOCK_CARD 7
|
||||
/// Class 8: application specific
|
||||
#define MMC_CCC_APP_SPEC 8
|
||||
/// Class 9: I/O mode
|
||||
#define MMC_CCC_IO_MODE 9
|
||||
|
||||
//- MMC/SD Card Command Response Type
|
||||
/// R1 (normal response command), 48bits
|
||||
#define MMC_RESP_R1 1
|
||||
#define SD_RESP_R1 MMC_RESP_R1
|
||||
/// R1b: busy signal transmitted on the data line DAT0
|
||||
#define MMC_RESP_R1b 1
|
||||
#define SD_RESP_R1b MMC_RESP_R1b
|
||||
/// R2: 136bits, CID, CSD register
|
||||
#define MMC_RESP_R2 2
|
||||
#define SD_RESP_R2 MMC_RESP_R2
|
||||
/// R3: 48bits, OCR
|
||||
#define MMC_RESP_R3 3
|
||||
#define SD_RESP_R3 MMC_RESP_R3
|
||||
/// R4 (Fast I/O), 48bits
|
||||
#define MMC_RESP_R4 4
|
||||
/// R5 (Interrupt request), 48bits
|
||||
#define MMC_RESP_R5 5
|
||||
/// R6 (Published RCA response), 48bits
|
||||
#define SD_RESP_R6 6
|
||||
/// R7 (Card interface condition), 48bits
|
||||
#define SD_RESP_R7 7
|
||||
|
||||
//- MMC Card CMD6 access mode
|
||||
#define MMC_SWITCH_CMDSET 0
|
||||
#define MMC_SWITCH_SETBITS 1
|
||||
#define MMC_SWITCH_CLRBITS 2
|
||||
#define MMC_SWITCH_WRITE 3
|
||||
|
||||
//-MMC Boot partition enable
|
||||
/// Boot partition 1 enabled for boot
|
||||
#define MMC_BOOT_PART_1 1
|
||||
/// Boot partition 2 enabled for boot
|
||||
#define MMC_BOOT_PART_2 2
|
||||
/// User area enabled for boot
|
||||
#define MMC_BOOT_PART_USER 7
|
||||
|
||||
//-MMC Boot partition access
|
||||
/// R/W boot partition 1
|
||||
#define MMC_BOOT_ACC_PART1 1
|
||||
/// R/W boot partition 2
|
||||
#define MMC_BOOT_ACC_PART2 2
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Macros
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// CID register access macros.
|
||||
#define SD_CID(pSd, bitfield, bits) ( (pSd->cid[3-(bitfield)/32] >> ((bitfield)%32)) & ((1 << (bits)) - 1))
|
||||
#define SD_CID_MID(pSd) SD_CID(pSd, 120, 8) ///< Manufacturer ID
|
||||
#define SD_CID_BGA(pSd) SD_CID(pSd, 112, 2) ///< Card/BGA(eMMC)
|
||||
#define SD_CID_CBS(pSd) SD_CID(pSd, 112, 2) ///< Card/BGA(eMMC)
|
||||
#define SD_CID_OID_BYTE_1(pSd) SD_CID(pSd, 112, 8) ///< OEM/Application ID byte 1
|
||||
#define SD_CID_OID_BYTE_0(pSd) SD_CID(pSd, 104, 8) ///< OEM/Application ID byte 0
|
||||
#define SD_CID_PNM_BYTE_4(pSd) SD_CID(pSd, 96, 8) ///< Product revision byte 4
|
||||
#define SD_CID_PNM_BYTE_3(pSd) SD_CID(pSd, 88, 8) ///< Product revision byte 3
|
||||
#define SD_CID_PNM_BYTE_2(pSd) SD_CID(pSd, 80, 8) ///< Product revision byte 2
|
||||
#define SD_CID_PNM_BYTE_1(pSd) SD_CID(pSd, 72, 8) ///< Product revision byte 1
|
||||
#define SD_CID_PNM_BYTE_0(pSd) SD_CID(pSd, 64, 8) ///< Product revision byte 0
|
||||
#define SD_CID_PRV_1(pSd) SD_CID(pSd, 24, 8) ///< Product serial number 1
|
||||
#define SD_CID_PRV_2(pSd) SD_CID(pSd, 32,24) ///< Product serial number 2
|
||||
#define SD_CID_MDT_YEAR(pSd) (SD_CID(pSd, 12, 8))+2000///< Manufacturing date year
|
||||
#define SD_CID_MDT_MONTH(pSd) SD_CID(pSd, 8, 4) ///< Manufacturing date month
|
||||
#define SD_CID_CRC(pSd) SD_CID(pSd, 1, 7) ///< CRC7 checksum
|
||||
|
||||
// CSD register access macros.
|
||||
#define SD_CSD(pSd, bitfield, bits) ((((pSd)->csd)[3-(bitfield)/32] >> ((bitfield)%32)) & ((1 << (bits)) - 1))
|
||||
#define SD_CSD_STRUCTURE(pSd) SD_CSD(pSd, 126, 2) ///< CSD structure 00b Version 1.0 01b version 2.0 High Cap
|
||||
#define SD_CSD_SPEC_VERS(pSd) SD_CSD(pSd, 122, 4) ///< System Specification Version Number
|
||||
#define SD_CSD_TAAC(pSd) SD_CSD(pSd, 112, 8) ///< Data read-access-time-1
|
||||
#define SD_CSD_NSAC(pSd) SD_CSD(pSd, 104, 8) ///< Data read access-time-2 in CLK cycles
|
||||
#define SD_CSD_TRAN_SPEED(pSd) SD_CSD(pSd, 96, 8) ///< Max. data transfer rate
|
||||
#define SD_CSD_CCC(pSd) SD_CSD(pSd, 84, 12) ///< Card command class
|
||||
#define SD_CSD_READ_BL_LEN(pSd) SD_CSD(pSd, 80, 4) ///< Max. read data block length
|
||||
#define SD_CSD_READ_BL_PARTIAL(pSd) SD_CSD(pSd, 79, 1) ///< Bartial blocks for read allowed
|
||||
#define SD_CSD_WRITE_BLK_MISALIGN(pSd) SD_CSD(pSd, 78, 1) ///< Write block misalignment
|
||||
#define SD_CSD_READ_BLK_MISALIGN(pSd) SD_CSD(pSd, 77, 1) ///< Read block misalignment
|
||||
#define SD_CSD_DSR_IMP(pSd) SD_CSD(pSd, 76, 1) ///< DSP implemented
|
||||
#define SD_CSD_C_SIZE(pSd) ((SD_CSD(pSd, 72, 2) << 10) + \
|
||||
(SD_CSD(pSd, 64, 8) << 2) + \
|
||||
SD_CSD(pSd, 62, 2)) ///< Device size
|
||||
#define SD_CSD_C_SIZE_HC(pSd) ((SD_CSD(pSd, 64, 6) << 16) + \
|
||||
(SD_CSD(pSd, 56, 8) << 8) + \
|
||||
SD_CSD(pSd, 48, 8)) ///< Device size v2.0 High Capacity
|
||||
#define SD_CSD_VDD_R_CURR_MIN(pSd) SD_CSD(pSd, 59, 3) ///< Max. read current @VDD min
|
||||
#define SD_CSD_VDD_R_CURR_MAX(pSd) SD_CSD(pSd, 56, 3) ///< Max. read current @VDD max
|
||||
#define SD_CSD_VDD_W_CURR_MIN(pSd) SD_CSD(pSd, 53, 3) ///< Max. write current @VDD min
|
||||
#define SD_CSD_VDD_W_CURR_MAX(pSd) SD_CSD(pSd, 50, 3) ///< Max. write current @VDD max
|
||||
#define SD_CSD_C_SIZE_MULT(pSd) SD_CSD(pSd, 47, 3) ///< Device size multiplier
|
||||
#define SD_CSD_ERASE_BLK_EN(pSd) SD_CSD(pSd, 46, 1) ///< Erase single block enable
|
||||
#define SD_CSD_SECTOR_SIZE(pSd) ((SD_CSD(pSd, 40, 6) << 1) + SD_CSD(pSd, 39, 1)) ///< Erase sector size
|
||||
#define SD_CSD_WP_GRP_SIZE(pSd) SD_CSD(pSd, 32, 7) ///< Write protect group size
|
||||
#define SD_CSD_WP_GRP_ENABLE(pSd) SD_CSD(pSd, 31, 1) ///< write protect group enable
|
||||
#define SD_CSD_R2W_FACTOR(pSd) SD_CSD(pSd, 26, 3) ///< Write speed factor
|
||||
#define SD_CSD_WRITE_BL_LEN(pSd) ((SD_CSD(pSd, 24, 2) << 2) + SD_CSD(pSd, 22, 2)) ///< Max write block length
|
||||
#define SD_CSD_WRITE_BL_PARTIAL(pSd) SD_CSD(pSd, 21, 1) ///< Partial blocks for write allowed
|
||||
#define SD_CSD_CONTENT_PROT_APP(pSd) SD_CSD(pSd, 16, 1) ///< File format group
|
||||
#define SD_CSD_FILE_FORMAT_GRP(pSd) SD_CSD(pSd, 15, 1) ///< File format group
|
||||
#define SD_CSD_COPY(pSd) SD_CSD(pSd, 14, 1) ///< Copy flag (OTP)
|
||||
#define SD_CSD_PERM_WRITE_PROTECT(pSd) SD_CSD(pSd, 13, 1) ///< Permanent write protect
|
||||
#define SD_CSD_TMP_WRITE_PROTECT(pSd) SD_CSD(pSd, 12, 1) ///< Temporary write protection
|
||||
#define SD_CSD_FILE_FORMAT(pSd) SD_CSD(pSd, 11, 2) ///< File format
|
||||
#define SD_CSD_ECC(pSd) SD_CSD(pSd, 8, 2) ///< CRC
|
||||
#define SD_CSD_CRC(pSd) SD_CSD(pSd, 1, 7) ///< CRC
|
||||
#define SD_CSD_MULT(pSd) (1 << (SD_CSD_C_SIZE_MULT(pSd) + 2))
|
||||
#define SD_CSD_BLOCKNR(pSd) ((SD_CSD_C_SIZE(pSd) + 1) * SD_CSD_MULT(pSd))
|
||||
#define SD_CSD_BLOCKNR_HC(pSd) ((SD_CSD_C_SIZE_HC(pSd) + 1) * 1024)
|
||||
#define SD_CSD_BLOCK_LEN(pSd) (1 << SD_CSD_READ_BL_LEN(pSd))
|
||||
#define SD_CSD_TOTAL_SIZE(pSd) (SD_CSD_BLOCKNR(pSd) * SD_CSD_BLOCK_LEN(pSd))
|
||||
#define SD_CSD_TOTAL_SIZE_HC(pSd) ((SD_CSD_C_SIZE_HC(pSd) + 1) * 512* 1024)
|
||||
#define SD_TOTAL_SIZE(pSd) ((pSd)->totalSize)
|
||||
#define SD_TOTAL_BLOCK(pSd) ((pSd)->blockNr)
|
||||
|
||||
// SCR register access macros.
|
||||
#define SD_SCR_BUS_WIDTHS(pScr) ((pScr[1] >> 16) & 0xF) ///< Describes all the DAT bus that are supported by this card
|
||||
#define SD_SCR_BUS_WIDTH_4BITS (1 << 1) ///< 4bit Bus Width is supported
|
||||
#define SD_SCR_BUS_WIDTH_1BIT (1 << 0) ///< 1bit Bus Width is supported
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Types
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/// SD end-of-transfer callback function.
|
||||
typedef void (*SdCallback)(unsigned char status, void *pCommand);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// SD Transfer Request prepared by the application upper layer. This structure
|
||||
/// is sent to the SD_SendCommand function to start the transfer. At the end of
|
||||
/// the transfer, the callback is invoked by the interrupt handler.
|
||||
//------------------------------------------------------------------------------
|
||||
typedef struct _SdCmd {
|
||||
|
||||
/// Command status.
|
||||
volatile char status;
|
||||
/// Command code.
|
||||
unsigned int cmd;
|
||||
/// Command argument.
|
||||
unsigned int arg;
|
||||
/// Data buffer.
|
||||
unsigned char *pData;
|
||||
/// Size of data buffer in bytes.
|
||||
unsigned short blockSize;
|
||||
/// Number of blocks to be transfered
|
||||
unsigned short nbBlock;
|
||||
/// Indicate if continue to transfer data
|
||||
unsigned char conTrans;
|
||||
/// Indicates if the command is a read operation.
|
||||
unsigned char isRead;
|
||||
/// Response buffer.
|
||||
unsigned int *pResp;
|
||||
/// SD card response type.
|
||||
unsigned char resType;
|
||||
/// Optional user-provided callback function.
|
||||
SdCallback callback;
|
||||
/// Optional argument to the callback function.
|
||||
void *pArg;
|
||||
|
||||
} SdCmd;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// SD driver structure. Holds the internal state of the SD driver and
|
||||
/// prevents parallel access to a SPI peripheral.
|
||||
//------------------------------------------------------------------------------
|
||||
typedef struct {
|
||||
|
||||
/// Pointer to a SPI peripheral.
|
||||
//AT91S_MCI *pSdHw;
|
||||
/// SPI peripheral identifier.
|
||||
unsigned char spiId;
|
||||
/// MCI HW mode
|
||||
unsigned char mciMode;
|
||||
/// Pointer to currently executing command.
|
||||
SdCmd *pCommand;
|
||||
/// Mutex.
|
||||
volatile char semaphore;
|
||||
|
||||
} SdDriver;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// Sdcard driver structure. It holds the current command being processed and
|
||||
/// the SD card address.
|
||||
//------------------------------------------------------------------------------
|
||||
typedef struct _SdCard {
|
||||
|
||||
/// Pointer to the underlying MCI driver.
|
||||
SdDriver *pSdDriver;
|
||||
/// Current MCI command being processed.
|
||||
SdCmd command;
|
||||
/// SD card current address.
|
||||
unsigned short cardAddress;
|
||||
/// Card-specific data.
|
||||
unsigned int csd[4];
|
||||
/// Previous access block number.
|
||||
unsigned int preBlock;
|
||||
/// State after sd command complete
|
||||
unsigned char state;
|
||||
/// Card type
|
||||
unsigned char cardType;
|
||||
/// Card total size
|
||||
unsigned int totalSize;
|
||||
/// Card block number
|
||||
unsigned int blockNr;
|
||||
/// Card access mode
|
||||
unsigned char mode;
|
||||
|
||||
} SdCard;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Global functions
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
extern unsigned char SD_Init(SdCard *pSd,
|
||||
SdDriver *pSdDriver);
|
||||
|
||||
extern unsigned char SD_ReadBlock(
|
||||
SdCard *pSd,
|
||||
unsigned int address,
|
||||
unsigned short nbBlocks,
|
||||
unsigned char *pData);
|
||||
|
||||
extern unsigned char SD_WriteBlock(
|
||||
SdCard *pSd,
|
||||
unsigned int address,
|
||||
unsigned short nbBlocks,
|
||||
const unsigned char *pData);
|
||||
|
||||
extern unsigned char SD_Stop(SdCard *pSd, SdDriver *pSdDriver);
|
||||
|
||||
#endif //#ifndef SDCARD_H
|
||||
|
||||
@@ -1,781 +0,0 @@
|
||||
/* ----------------------------------------------------------------------------
|
||||
* ATMEL Microcontroller Software Support
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2008, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Headers
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#include "sdspi.h"
|
||||
//#include <utility/assert.h>
|
||||
//#include <utility/trace.h>
|
||||
//#include <board.h>
|
||||
//#include <crc7.h>
|
||||
//#include <crc-itu-t.h>
|
||||
//#include <crc16.h>
|
||||
//#include <crc-ccitt.h>
|
||||
#include <string.h>
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Macros
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/// Transfer is pending.
|
||||
#define SDSPI_STATUS_PENDING 1
|
||||
/// Transfer has been aborted because an error occured.
|
||||
#define SDSPI_STATUS_ERROR 2
|
||||
|
||||
/// SPI driver is currently in use.
|
||||
#define SDSPI_ERROR_LOCK 1
|
||||
|
||||
// Data Tokens
|
||||
#define SDSPI_START_BLOCK_1 0xFE // Single/Multiple read, single write
|
||||
#define SDSPI_START_BLOCK_2 0xFC // Multiple block write
|
||||
#define SDSPI_STOP_TRAN 0xFD // Cmd12
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Exported functions
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// Initializes the SD Spi structure and the corresponding SPI hardware.
|
||||
/// \param pSpid Pointer to a Spid instance.
|
||||
/// \param pSpiHw Associated SPI peripheral.
|
||||
/// \param spiId SPI peripheral identifier.
|
||||
//------------------------------------------------------------------------------
|
||||
void SDSPI_Configure(SdSpi *pSdSpi,
|
||||
AT91PS_SPI pSpiHw,
|
||||
unsigned char spiId)
|
||||
{
|
||||
// Initialize the SPI structure
|
||||
pSdSpi->pSpiHw = pSpiHw;
|
||||
pSdSpi->spiId = spiId;
|
||||
pSdSpi->semaphore = 1;
|
||||
|
||||
// Enable the SPI clock
|
||||
// BSS replaced by below AT91C_BASE_PMC->PMC_PCER = (1 << pSdSpi->spiId);
|
||||
PMC->PMC_PCER0 = (1 << pSdSpi->spiId);
|
||||
|
||||
// Execute a software reset of the SPI twice
|
||||
pSpiHw->SPI_CR = SPI_CR_SWRST; // BSS AT91C_SPI_SWRST;
|
||||
pSpiHw->SPI_CR = SPI_CR_SWRST; // BSS AT91C_SPI_SWRST;
|
||||
|
||||
// Configure SPI in Master Mode with No CS selected !!!
|
||||
pSpiHw->SPI_MR = SPI_MR_MSTR | SPI_MR_MODFDIS | SPI_MR_PCS; // BSS AT91C_SPI_MSTR | AT91C_SPI_MODFDIS | AT91C_SPI_PCS;
|
||||
|
||||
// Disables the receiver PDC transfer requests
|
||||
// Disables the transmitter PDC transfer requests.
|
||||
pSpiHw->SPI_PTCR = SPI_PTCR_RXTDIS | SPI_PTCR_TXTDIS; // BSS AT91C_PDC_RXTDIS | AT91C_PDC_TXTDIS;
|
||||
|
||||
// Enable the SPI
|
||||
pSpiHw->SPI_CR = SPI_CR_SPIEN; // BSS AT91C_SPI_SPIEN;
|
||||
|
||||
// Disable the SPI clock
|
||||
// BSS replaced by below AT91C_BASE_PMC->PMC_PCDR = (1 << pSdSpi->spiId);
|
||||
PMC->PMC_PCDR0 = (1 << pSdSpi->spiId);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// Configures the parameters for the device corresponding to the cs.
|
||||
/// \param pSdSpi Pointer to a SdSpi instance.
|
||||
/// \param cs number corresponding to the SPI chip select.
|
||||
/// \param csr SPI_CSR value to setup.
|
||||
//------------------------------------------------------------------------------
|
||||
void SDSPI_ConfigureCS(SdSpi *pSdSpi, unsigned char cs, unsigned int csr)
|
||||
{
|
||||
unsigned int spiMr;
|
||||
AT91S_SPI *pSpiHw = pSdSpi->pSpiHw;
|
||||
|
||||
// Enable the SPI clock
|
||||
// BSS below AT91C_BASE_PMC->PMC_PCER = (1 << pSdSpi->spiId);
|
||||
PMC->PMC_PCER0 = (1 << pSdSpi->spiId);
|
||||
|
||||
//TRACE_DEBUG("CSR[%d]=0x%8X\n\r", cs, csr);
|
||||
pSpiHw->SPI_CSR[cs] = csr;
|
||||
|
||||
//jcb to put in sendcommand
|
||||
// Write to the MR register
|
||||
spiMr = pSpiHw->SPI_MR;
|
||||
spiMr |= SPI_MR_PCS; // TODO AT91C_SPI_PCS;
|
||||
spiMr &= ~((1 << cs) << 16);
|
||||
pSpiHw->SPI_MR = spiMr;
|
||||
|
||||
// Disable the SPI clock
|
||||
// BSS below AT91C_BASE_PMC->PMC_PCDR = (1 << pSdSpi->spiId);
|
||||
PMC->PMC_PCDR0 = (1 << pSdSpi->spiId);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// Use PDC for SPI data transfer.
|
||||
/// Return 0 if no error, otherwise return error status.
|
||||
/// \param pSdSpi Pointer to a SdSpi instance.
|
||||
/// \param pData Data pointer.
|
||||
/// \param size Data transfer byte count.
|
||||
//------------------------------------------------------------------------------
|
||||
unsigned char SDSPI_PDC(SdSpi *pSdSpi, unsigned char *pData, unsigned int size)
|
||||
{
|
||||
AT91PS_SPI pSpiHw = pSdSpi->pSpiHw;
|
||||
unsigned int spiIer;
|
||||
|
||||
if (pSdSpi->semaphore == 0) {
|
||||
TRACE_DEBUG("No semaphore\n\r");
|
||||
return SDSPI_ERROR_LOCK;
|
||||
}
|
||||
pSdSpi->semaphore--;
|
||||
|
||||
// Enable the SPI clock
|
||||
// BSS below AT91C_BASE_PMC->PMC_PCER = (1 << pSdSpi->spiId);
|
||||
PMC->PMC_PCER0 = (1 << pSdSpi->spiId);
|
||||
|
||||
// Disable transmitter and receiver
|
||||
pSpiHw->SPI_PTCR = SPI_PTCR_RXTDIS | SPI_PTCR_TXTDIS; // BSS AT91C_PDC_RXTDIS | AT91C_PDC_TXTDIS;
|
||||
|
||||
// Receive Pointer Register
|
||||
pSpiHw->SPI_RPR = (int)pData;
|
||||
// Receive Counter Register
|
||||
pSpiHw->SPI_RCR = size;
|
||||
// Transmit Pointer Register
|
||||
pSpiHw->SPI_TPR = (int) pData;
|
||||
// Transmit Counter Register
|
||||
pSpiHw->SPI_TCR = size;
|
||||
|
||||
spiIer = SPI_IER_RXBUFF; // TODO AT91C_SPI_RXBUFF;
|
||||
|
||||
// Enable transmitter and receiver
|
||||
pSpiHw->SPI_PTCR = SPI_PTCR_RXTEN | SPI_PTCR_TXTEN; // BSS AT91C_PDC_RXTEN | AT91C_PDC_TXTEN;
|
||||
|
||||
// Interrupt enable shall be done after PDC TXTEN and RXTEN
|
||||
pSpiHw->SPI_IER = spiIer;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//! Should be moved to a new file
|
||||
//------------------------------------------------------------------------------
|
||||
/// Read data on SPI data bus;
|
||||
/// Returns 1 if read fails, returns 0 if no error.
|
||||
/// \param pSdSpi Pointer to a SD SPI driver instance.
|
||||
/// \param pData Data pointer.
|
||||
/// \param size Data size.
|
||||
//------------------------------------------------------------------------------
|
||||
unsigned char SDSPI_Read(SdSpi *pSdSpi, unsigned char *pData, unsigned int size)
|
||||
{
|
||||
unsigned char error;
|
||||
|
||||
// MOSI should hold high during read, or there will be wrong data in received data.
|
||||
memset(pData, 0xff, size);
|
||||
|
||||
error = SDSPI_PDC(pSdSpi, pData, size);
|
||||
|
||||
while(SDSPI_IsBusy(pSdSpi) == 1);
|
||||
|
||||
if( error == 0 ) {
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
TRACE_DEBUG("PB SDSPI_Read\n\r");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// Write data on SPI data bus;
|
||||
/// Returns 1 if write fails, returns 0 if no error.
|
||||
/// \param pSdSpi Pointer to a SD SPI driver instance.
|
||||
/// \param pData Data pointer.
|
||||
/// \param size Data size.
|
||||
//------------------------------------------------------------------------------
|
||||
unsigned char SDSPI_Write(SdSpi *pSdSpi, unsigned char *pData, unsigned int size)
|
||||
{
|
||||
unsigned char error;
|
||||
|
||||
error = SDSPI_PDC(pSdSpi, pData, size);
|
||||
|
||||
while(SDSPI_IsBusy(pSdSpi) == 1);
|
||||
|
||||
if( error == 0 ) {
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
TRACE_DEBUG("PB SDSPI_Write\n\r");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
unsigned char SDSPI_WaitDataBusy(SdSpi *pSdSpi)
|
||||
{
|
||||
unsigned char busyData;
|
||||
|
||||
SDSPI_Read(pSdSpi, &busyData, 1);
|
||||
|
||||
if (busyData != 0xff) {
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Table for CRC-7 (polynomial x^7 + x^3 + 1) */
|
||||
const uint8_t crc7_syndrome_table[256] = {
|
||||
0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f,
|
||||
0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77,
|
||||
0x19, 0x10, 0x0b, 0x02, 0x3d, 0x34, 0x2f, 0x26,
|
||||
0x51, 0x58, 0x43, 0x4a, 0x75, 0x7c, 0x67, 0x6e,
|
||||
0x32, 0x3b, 0x20, 0x29, 0x16, 0x1f, 0x04, 0x0d,
|
||||
0x7a, 0x73, 0x68, 0x61, 0x5e, 0x57, 0x4c, 0x45,
|
||||
0x2b, 0x22, 0x39, 0x30, 0x0f, 0x06, 0x1d, 0x14,
|
||||
0x63, 0x6a, 0x71, 0x78, 0x47, 0x4e, 0x55, 0x5c,
|
||||
0x64, 0x6d, 0x76, 0x7f, 0x40, 0x49, 0x52, 0x5b,
|
||||
0x2c, 0x25, 0x3e, 0x37, 0x08, 0x01, 0x1a, 0x13,
|
||||
0x7d, 0x74, 0x6f, 0x66, 0x59, 0x50, 0x4b, 0x42,
|
||||
0x35, 0x3c, 0x27, 0x2e, 0x11, 0x18, 0x03, 0x0a,
|
||||
0x56, 0x5f, 0x44, 0x4d, 0x72, 0x7b, 0x60, 0x69,
|
||||
0x1e, 0x17, 0x0c, 0x05, 0x3a, 0x33, 0x28, 0x21,
|
||||
0x4f, 0x46, 0x5d, 0x54, 0x6b, 0x62, 0x79, 0x70,
|
||||
0x07, 0x0e, 0x15, 0x1c, 0x23, 0x2a, 0x31, 0x38,
|
||||
0x41, 0x48, 0x53, 0x5a, 0x65, 0x6c, 0x77, 0x7e,
|
||||
0x09, 0x00, 0x1b, 0x12, 0x2d, 0x24, 0x3f, 0x36,
|
||||
0x58, 0x51, 0x4a, 0x43, 0x7c, 0x75, 0x6e, 0x67,
|
||||
0x10, 0x19, 0x02, 0x0b, 0x34, 0x3d, 0x26, 0x2f,
|
||||
0x73, 0x7a, 0x61, 0x68, 0x57, 0x5e, 0x45, 0x4c,
|
||||
0x3b, 0x32, 0x29, 0x20, 0x1f, 0x16, 0x0d, 0x04,
|
||||
0x6a, 0x63, 0x78, 0x71, 0x4e, 0x47, 0x5c, 0x55,
|
||||
0x22, 0x2b, 0x30, 0x39, 0x06, 0x0f, 0x14, 0x1d,
|
||||
0x25, 0x2c, 0x37, 0x3e, 0x01, 0x08, 0x13, 0x1a,
|
||||
0x6d, 0x64, 0x7f, 0x76, 0x49, 0x40, 0x5b, 0x52,
|
||||
0x3c, 0x35, 0x2e, 0x27, 0x18, 0x11, 0x0a, 0x03,
|
||||
0x74, 0x7d, 0x66, 0x6f, 0x50, 0x59, 0x42, 0x4b,
|
||||
0x17, 0x1e, 0x05, 0x0c, 0x33, 0x3a, 0x21, 0x28,
|
||||
0x5f, 0x56, 0x4d, 0x44, 0x7b, 0x72, 0x69, 0x60,
|
||||
0x0e, 0x07, 0x1c, 0x15, 0x2a, 0x23, 0x38, 0x31,
|
||||
0x46, 0x4f, 0x54, 0x5d, 0x62, 0x6b, 0x70, 0x79
|
||||
};
|
||||
|
||||
// BSS crc functions added
|
||||
static inline uint8_t crc7_byte(uint8_t crc, uint8_t data)
|
||||
{
|
||||
return crc7_syndrome_table[(crc << 1) ^ data];
|
||||
}
|
||||
|
||||
uint8_t crc7(uint8_t crc, const uint8_t *buffer, size_t len)
|
||||
{
|
||||
while (len--)
|
||||
crc = crc7_byte(crc, *buffer++);
|
||||
return crc;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// Convert SD MCI command to a SPI mode command token.
|
||||
/// \param pCmdToken Pointer to the SD command token.
|
||||
/// \param arg SD command argument
|
||||
//------------------------------------------------------------------------------
|
||||
void SDSPI_MakeCmd(unsigned char *pCmdToken, unsigned int arg)
|
||||
{
|
||||
unsigned char sdCmdNum;
|
||||
unsigned char crc = 0;
|
||||
unsigned char crcPrev = 0;
|
||||
|
||||
sdCmdNum = 0x3f & *pCmdToken;
|
||||
*pCmdToken = sdCmdNum | 0x40;
|
||||
*(pCmdToken+1) = (arg >> 24) & 0xff;
|
||||
*(pCmdToken+2) = (arg >> 16) & 0xff;
|
||||
*(pCmdToken+3) = (arg >> 8) & 0xff;
|
||||
*(pCmdToken+4) = arg & 0xff;
|
||||
|
||||
crc = crc7(crcPrev, (unsigned char *)(pCmdToken), 5);
|
||||
|
||||
*(pCmdToken+5) = (crc << 1) | 1;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// Get response after send SD command.
|
||||
/// Return 0 if no error, otherwise indicate an error.
|
||||
/// \param pSdSpi Pointer to the SD SPI instance.
|
||||
/// \param pCommand Pointer to the SD command
|
||||
//------------------------------------------------------------------------------
|
||||
unsigned char SDSPI_GetCmdResp(SdSpi *pSdSpi, SdSpiCmd *pCommand)
|
||||
{
|
||||
unsigned char resp[8]; // response
|
||||
unsigned char error;
|
||||
unsigned int respRetry = 8; //NCR max 8, refer to card datasheet
|
||||
|
||||
memset(resp, 0, 8);
|
||||
|
||||
// Wait for response start bit.
|
||||
do {
|
||||
error = SDSPI_Read(pSdSpi, &resp[0], 1);
|
||||
if (error) {
|
||||
TRACE_DEBUG("\n\rpb SDSPI_GetCmdResp: 0x%X\n\r", error);
|
||||
return error;
|
||||
}
|
||||
if ((resp[0]&0x80) == 0) {
|
||||
break;
|
||||
}
|
||||
respRetry--;
|
||||
} while(respRetry > 0);
|
||||
|
||||
switch (pCommand->resType) {
|
||||
case 1:
|
||||
*(pCommand->pResp) = resp[0];
|
||||
break;
|
||||
|
||||
case 2:
|
||||
error = SDSPI_Read(pSdSpi, &resp[1], 1);
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
*(pCommand->pResp) = resp[0]
|
||||
| (resp[1] << 8);
|
||||
break;
|
||||
|
||||
// Response 3, get OCR
|
||||
case 3:
|
||||
error = SDSPI_Read(pSdSpi, &resp[1], 4);
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
*(pCommand->pResp) = resp[0]
|
||||
| (resp[1] << 8)
|
||||
| (resp[2] << 16)
|
||||
| (resp[3] << 24);
|
||||
*(pCommand->pResp+1) = resp[4];
|
||||
break;
|
||||
|
||||
case 7:
|
||||
TRACE_DEBUG("case 7\n\r");
|
||||
error = SDSPI_Read(pSdSpi, &resp[1], 4);
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
*(pCommand->pResp) = resp[0]
|
||||
| (resp[1] << 8)
|
||||
| (resp[2] << 16)
|
||||
| (resp[3] << 24);
|
||||
*(pCommand->pResp+1) = resp[4];
|
||||
break;
|
||||
|
||||
default:
|
||||
TRACE_DEBUG("PB default\n\r");
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// Get response after send data.
|
||||
/// Return 0 if no error, otherwise indicate an error.
|
||||
/// \param pSdSpi Pointer to the SD SPI instance.
|
||||
/// \param pCommand Pointer to the SD command
|
||||
//------------------------------------------------------------------------------
|
||||
unsigned char SDSPI_GetDataResp(SdSpi *pSdSpi, SdSpiCmd *pCommand)
|
||||
{
|
||||
unsigned char resp = 0; // response
|
||||
unsigned char error;
|
||||
unsigned int respRetry = 18; //NCR max 8, refer to card datasheet
|
||||
|
||||
// Wait for response start bit.
|
||||
do {
|
||||
error = SDSPI_Read(pSdSpi, &resp, 1);
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
if (((resp & 0x11) == 0x1) || ((resp & 0xf0) == 0))
|
||||
break;
|
||||
|
||||
respRetry--;
|
||||
} while(respRetry > 0);
|
||||
//TRACE_DEBUG("SDSPI_GetDataResp 0x%X\n\r",resp);
|
||||
return resp;
|
||||
}
|
||||
|
||||
// BSS crc16 function added
|
||||
|
||||
const uint16_t crc_itu_t_table[256] = {
|
||||
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
|
||||
0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
|
||||
0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
|
||||
0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
|
||||
0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
|
||||
0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
|
||||
0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
|
||||
0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
|
||||
0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
|
||||
0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
|
||||
0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
|
||||
0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
|
||||
0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
|
||||
0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
|
||||
0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
|
||||
0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
|
||||
0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
|
||||
0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
|
||||
0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
|
||||
0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
|
||||
0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
|
||||
0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
|
||||
0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
|
||||
0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
|
||||
0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
|
||||
0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
|
||||
0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
|
||||
0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
|
||||
0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
|
||||
0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
|
||||
0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
|
||||
0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
|
||||
};
|
||||
|
||||
static inline uint16_t crc_itu_t_byte(uint16_t crc, const uint8_t data)
|
||||
{
|
||||
return (crc << 8) ^ crc_itu_t_table[((crc >> 8) ^ data) & 0xff];
|
||||
}
|
||||
|
||||
uint16_t crc_itu_t(uint16_t crc, const uint8_t *buffer, size_t len)
|
||||
{
|
||||
while (len--)
|
||||
crc = crc_itu_t_byte(crc, *buffer++);
|
||||
return crc;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// Starts a SPI master transfer. This is a non blocking function. It will
|
||||
/// return as soon as the transfer is started.
|
||||
/// Returns 0 if the transfer has been started successfully; otherwise returns
|
||||
/// error.
|
||||
/// \param pSdSpi Pointer to a SdSpi instance.
|
||||
/// \param pCommand Pointer to the SPI command to execute.
|
||||
//------------------------------------------------------------------------------
|
||||
unsigned char SDSPI_SendCommand(SdSpi *pSdSpi, SdSpiCmd *pCommand)
|
||||
{
|
||||
// BSS AT91S_SPI *pSpiHw = pSdSpi->pSpiHw;
|
||||
unsigned char CmdToken[6];
|
||||
unsigned char *pData;
|
||||
unsigned int blockSize;
|
||||
unsigned int i;
|
||||
unsigned char error;
|
||||
unsigned char dataHeader;
|
||||
unsigned int dataRetry1 = 100;
|
||||
unsigned int dataRetry2 = 100;
|
||||
unsigned char crc[2];
|
||||
unsigned char crcPrev = 0;
|
||||
unsigned char crcPrev2 = 0;
|
||||
|
||||
SANITY_CHECK(pSdSpi);
|
||||
// BSS SANITY_CHECK(pSpiHw);
|
||||
SANITY_CHECK(pCommand);
|
||||
|
||||
CmdToken[0] = pCommand->cmd & 0x3F;
|
||||
pData = pCommand->pData;
|
||||
blockSize = pCommand->blockSize;
|
||||
|
||||
SDSPI_MakeCmd((unsigned char *)&CmdToken, pCommand->arg);
|
||||
|
||||
// Command is now being executed
|
||||
pSdSpi->pCommand = pCommand;
|
||||
pCommand->status = SDSPI_STATUS_PENDING;
|
||||
|
||||
// Send the command
|
||||
if((pCommand->conTrans == SPI_NEW_TRANSFER) || (blockSize == 0)) {
|
||||
|
||||
for(i = 0; i < 6; i++) {
|
||||
error = SDSPI_Write(pSdSpi, &CmdToken[i], 1);
|
||||
if (error) {
|
||||
TRACE_DEBUG("Error: %d\n\r", error);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
// Specific for Cmd12()
|
||||
if ((pCommand->cmd & 0x3F) == 12) {
|
||||
if( 1 == SDSPI_Wait(pSdSpi, 2) ) {
|
||||
TRACE_DEBUG("Pb Send command 12\n\r");
|
||||
}
|
||||
}
|
||||
if (pCommand->pResp) {
|
||||
error = SDSPI_GetCmdResp(pSdSpi, pCommand);
|
||||
if (error) {
|
||||
TRACE_DEBUG("Error: %d\n\r", error);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( (blockSize > 0) && (pCommand->nbBlock == 0) ) {
|
||||
pCommand->nbBlock = 1;
|
||||
}
|
||||
|
||||
// For data block operations
|
||||
while (pCommand->nbBlock > 0) {
|
||||
|
||||
// If data block size is invalid, return error
|
||||
if (blockSize == 0) {
|
||||
TRACE_DEBUG("Block Size = 0\n\r");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// DATA transfer from card to host
|
||||
if (pCommand->isRead) {
|
||||
do {
|
||||
SDSPI_Read(pSdSpi, &dataHeader, 1);
|
||||
dataRetry1 --;
|
||||
if (dataHeader == SDSPI_START_BLOCK_1) {
|
||||
break;
|
||||
}
|
||||
else if((dataHeader & 0xf0) == 0x00) {
|
||||
pCommand->status = SDSPI_STATUS_ERROR;
|
||||
TRACE_DEBUG("Data Error 0x%X!\n\r", dataHeader);
|
||||
return 1;
|
||||
}
|
||||
} while(dataRetry1 > 0);
|
||||
|
||||
if (dataRetry1 == 0) {
|
||||
TRACE_DEBUG("Timeout dataretry1\n\r");
|
||||
return 1;
|
||||
}
|
||||
|
||||
SDSPI_Read(pSdSpi, pData, blockSize);
|
||||
|
||||
// Specific for Cmd9()
|
||||
if ((pCommand->cmd & 0x3f) != 0x9) {
|
||||
|
||||
SDSPI_Read(pSdSpi, crc, 2);
|
||||
#ifdef SDSPI_CRC_ON
|
||||
// Check data CRC
|
||||
TRACE_DEBUG("Check Data CRC\n\r");
|
||||
crcPrev = 0;
|
||||
crcPrev2 = 0;
|
||||
if (crc[0] != ((crc_itu_t(crcPrev, pData, blockSize) & 0xff00) >> 8 )
|
||||
|| crc[1] != (crc_itu_t(crcPrev2, pData, blockSize) & 0xff)) {
|
||||
TRACE_ERROR("CRC error 0x%X 0x%X 0x%X\n\r", \
|
||||
crc[0], crc[1], crc_itu_t(pData, blockSize));
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// DATA transfer from host to card
|
||||
else {
|
||||
SDSPI_NCS(pSdSpi);
|
||||
if ((pCommand->conTrans == SPI_CONTINUE_TRANSFER) || ((pCommand->cmd & 0x3f) == 25)) {
|
||||
dataHeader = SDSPI_START_BLOCK_2;
|
||||
}
|
||||
else {
|
||||
dataHeader = SDSPI_START_BLOCK_1;
|
||||
}
|
||||
|
||||
crcPrev = 0;
|
||||
crc[0] = (crc_itu_t(crcPrev, pData, blockSize) & 0xff00) >> 8;
|
||||
crcPrev2 = 0;
|
||||
crc[1] = (crc_itu_t(crcPrev2, pData, blockSize) & 0xff);
|
||||
SDSPI_Write(pSdSpi, &dataHeader, 1);
|
||||
SDSPI_Write(pSdSpi, pData, blockSize);
|
||||
SDSPI_Write(pSdSpi, crc, 2);
|
||||
|
||||
// If status bits in data response is not "data accepted", return error
|
||||
if ((SDSPI_GetDataResp(pSdSpi, pCommand) & 0xe) != 0x4) {
|
||||
TRACE_ERROR("Write resp error!\n\r");
|
||||
return 1;
|
||||
}
|
||||
|
||||
do {
|
||||
if (SDSPI_WaitDataBusy(pSdSpi) == 0) {
|
||||
break;
|
||||
}
|
||||
dataRetry2--;
|
||||
} while(dataRetry2 > 0);
|
||||
}
|
||||
pData += blockSize;
|
||||
pCommand->nbBlock--;
|
||||
}
|
||||
|
||||
if (pCommand->status == SDSPI_STATUS_PENDING) {
|
||||
pCommand->status = 0;
|
||||
}
|
||||
|
||||
//TRACE_DEBUG("end SDSPI_SendCommand\n\r");
|
||||
return 0;
|
||||
}
|
||||
//!
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// The SPI_Handler must be called by the SPI Interrupt Service Routine with the
|
||||
/// corresponding Spi instance.
|
||||
/// The SPI_Handler will unlock the Spi semaphore and invoke the upper application
|
||||
/// callback.
|
||||
/// \param pSdSpi Pointer to a SdSpi instance.
|
||||
//------------------------------------------------------------------------------
|
||||
void SDSPI_Handler(SdSpi *pSdSpi)
|
||||
{
|
||||
SdSpiCmd *pCommand = pSdSpi->pCommand;
|
||||
AT91S_SPI *pSpiHw = pSdSpi->pSpiHw;
|
||||
volatile unsigned int spiSr;
|
||||
|
||||
// Read the status register
|
||||
spiSr = pSpiHw->SPI_SR;
|
||||
if(spiSr & SPI_SR_RXBUFF/*BSS AT91C_SPI_RXBUFF*/) {
|
||||
|
||||
if (pCommand->status == SDSPI_STATUS_PENDING) {
|
||||
pCommand->status = 0;
|
||||
}
|
||||
// Disable transmitter and receiver
|
||||
pSpiHw->SPI_PTCR = SPI_PTCR_RXTDIS | SPI_PTCR_TXTDIS; // BSS AT91C_PDC_RXTDIS | AT91C_PDC_TXTDIS;
|
||||
|
||||
// Disable the SPI clock
|
||||
// BSS below AT91C_BASE_PMC->PMC_PCDR = (1 << pSdSpi->spiId);
|
||||
PMC->PMC_PCDR0 = (1 << pSdSpi->spiId);
|
||||
|
||||
// Disable buffer complete interrupt
|
||||
pSpiHw->SPI_IDR = SPI_IDR_RXBUFF | SPI_IDR_ENDTX; // BSS AT91C_SPI_RXBUFF | AT91C_SPI_ENDTX;
|
||||
|
||||
// Release the SPI semaphore
|
||||
pSdSpi->semaphore++;
|
||||
}
|
||||
|
||||
// Invoke the callback associated with the current command
|
||||
if (pCommand && pCommand->callback) {
|
||||
pCommand->callback(0, pCommand);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// Returns 1 if the given SPI transfer is complete; otherwise returns 0.
|
||||
/// \param pCommand Pointer to a SdSpiCmd instance.
|
||||
//------------------------------------------------------------------------------
|
||||
unsigned char SDSPI_IsTxComplete(SdSpiCmd *pCommand)
|
||||
{
|
||||
if (pCommand->status != SDSPI_STATUS_PENDING) {
|
||||
if (pCommand->status != 0){
|
||||
TRACE_DEBUG("SPI_IsTxComplete %d\n\r", pCommand->status);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// Close a SPI driver instance and the underlying peripheral.
|
||||
/// \param pSdSpi Pointer to a SD SPI driver instance.
|
||||
//------------------------------------------------------------------------------
|
||||
void SDSPI_Close(SdSpi *pSdSpi)
|
||||
{
|
||||
AT91S_SPI *pSpiHw = pSdSpi->pSpiHw;
|
||||
|
||||
SANITY_CHECK(pSdSpi);
|
||||
SANITY_CHECK(pSpiHw);
|
||||
|
||||
// Enable the SPI clock
|
||||
// BSS below AT91C_BASE_PMC->PMC_PCER = (1 << pSdSpi->spiId);
|
||||
PMC->PMC_PCER0 = (1 << pSdSpi->spiId);
|
||||
|
||||
// Disable the PDC transfer
|
||||
pSpiHw->SPI_PTCR = SPI_PTCR_RXTDIS | SPI_PTCR_TXTDIS; // BSS AT91C_PDC_RXTDIS | AT91C_PDC_TXTDIS;
|
||||
|
||||
// Enable the SPI
|
||||
pSpiHw->SPI_CR = SPI_CR_SPIDIS; // BSS AT91C_SPI_SPIDIS;
|
||||
|
||||
// Disable the SPI clock
|
||||
// BSS below AT91C_BASE_PMC->PMC_PCDR = (1 << pSdSpi->spiId);
|
||||
PMC->PMC_PCDR0 = (1 << pSdSpi->spiId);
|
||||
|
||||
// Disable all the interrupts
|
||||
pSpiHw->SPI_IDR = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// Returns 1 if the SPI driver is currently busy programming;
|
||||
/// otherwise returns 0.
|
||||
/// \param pSdSpi Pointer to a SD SPI driver instance.
|
||||
//------------------------------------------------------------------------------
|
||||
unsigned char SDSPI_IsBusy(SdSpi *pSdSpi)
|
||||
{
|
||||
if (pSdSpi->semaphore == 0) {
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// Wait several cycles on SPI bus;
|
||||
/// Returns 0 to indicates no error, otherwise return 1.
|
||||
/// \param pSdSpi Pointer to a SD SPI driver instance.
|
||||
/// \param cycles Wait data cycles.
|
||||
//------------------------------------------------------------------------------
|
||||
unsigned char SDSPI_Wait(SdSpi *pSdSpi, unsigned int cycles)
|
||||
{
|
||||
unsigned int i = cycles;
|
||||
unsigned char data = 0xff;
|
||||
|
||||
for (; i > 0; i--) {
|
||||
if (SDSPI_Read(pSdSpi, &data, 1)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// Send stop transfer data token;
|
||||
/// Returns 0 to indicates no error, otherwise return 1.
|
||||
/// \param pSdSpi Pointer to a SD SPI driver instance.
|
||||
//------------------------------------------------------------------------------
|
||||
unsigned char SDSPI_StopTranToken(SdSpi *pSdSpi)
|
||||
{
|
||||
unsigned char stopToken = SDSPI_STOP_TRAN;
|
||||
|
||||
TRACE_DEBUG("SDSPI_StopTranToken\n\r");
|
||||
return SDSPI_Write(pSdSpi, &stopToken, 1);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// Wait, SD card Ncs cycles;
|
||||
/// Returns 0 to indicates no error, otherwise return 1.
|
||||
/// \param pSdSpi Pointer to a SD SPI driver instance.
|
||||
//------------------------------------------------------------------------------
|
||||
unsigned char SDSPI_NCS(SdSpi *pSdSpi)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned char ncs;
|
||||
|
||||
for(i = 0; i < 15; i++) {
|
||||
ncs = 0xff;
|
||||
if (SDSPI_Write(pSdSpi, &ncs, 1)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,175 +0,0 @@
|
||||
/* ----------------------------------------------------------------------------
|
||||
* ATMEL Microcontroller Software Support
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2008, Atmel Corporation
|
||||
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// \page "sdspi"
|
||||
///
|
||||
/// !Purpose
|
||||
///
|
||||
/// sdcard spi-bus driver
|
||||
///
|
||||
/// !Usage
|
||||
///
|
||||
/// -# SDSPI_Configure: Initializes the SD Spi structure and the corresponding SPI hardware
|
||||
/// -# SDSPI_ConfigureCS : Configures the parameters for the device corresponding to the cs
|
||||
/// -# SDSPI_Read: Read data on SPI data bus
|
||||
/// -# SDSPI_Write : Write data on SPI data bus
|
||||
/// -# SDSPI_SendCommand : Starts a SPI master transfer
|
||||
/// -# SDSPI_StopTranToken : Send stop transfer data token
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#ifndef SDSPI_H
|
||||
#define SDSPI_H
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Headers
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#ifdef REVA
|
||||
#include "AT91SAM3S2.h"
|
||||
#else
|
||||
#include "AT91SAM3S4.h"
|
||||
#endif
|
||||
|
||||
//#include <board.h>
|
||||
//#include <spi/spi.h>
|
||||
|
||||
/// SPI CSR value
|
||||
#define SDSPI_CSR(scbr) ( AT91C_SPI_CPOL \
|
||||
| AT91C_SPI_BITS_8 \
|
||||
| (((scbr)<< 8) & AT91C_SPI_SCBR) \
|
||||
| ( (0x08 << 16) & AT91C_SPI_DLYBS)\
|
||||
| ( (0x01 << 24) & AT91C_SPI_DLYBCT) )
|
||||
|
||||
/// Calculates the value of the SCBR field of the Chip Select Register given
|
||||
/// MCK and SPCK.
|
||||
#define SPID_CSR_SCBR(mck, spck) ((((mck) / (spck)) << 8) & AT91C_SPI_SCBR)
|
||||
|
||||
/// Calculates the value of the DLYBS field of the Chip Select Register given
|
||||
/// the delay in ns and MCK.
|
||||
#define SPID_CSR_DLYBS(mck, delay) \
|
||||
((((((delay) * ((mck) / 1000000)) / 1000) + 1) << 16) & AT91C_SPI_DLYBS)
|
||||
|
||||
/// Calculates the value of the DLYBCT field of the Chip Select Register given
|
||||
/// the delay in ns and MCK.
|
||||
#define SPID_CSR_DLYBCT(mck, delay) \
|
||||
((((((delay) / 32 * ((mck) / 1000000)) / 1000) + 1) << 24) & AT91C_SPI_DLYBCT)
|
||||
|
||||
#define AT45_CSR(mck, spck) \
|
||||
(AT91C_SPI_NCPHA | SPID_CSR_DLYBCT(mck, 250) \
|
||||
| SPID_CSR_DLYBS(mck, 250) | SPID_CSR_SCBR(mck, spck))
|
||||
|
||||
|
||||
/// Start new data transfer
|
||||
#define SPI_NEW_TRANSFER 0
|
||||
/// Continue data transfer
|
||||
#define SPI_CONTINUE_TRANSFER 1
|
||||
|
||||
/// SD end-of-transfer callback function.
|
||||
typedef void (*SdSpiCallback)(unsigned char status, void *pCommand);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// SPI Transfer Request prepared by the application upper layer. This structure
|
||||
/// is sent to the SDSPI_SendCommand function to start the transfer. At the end of
|
||||
/// the transfer, the callback is invoked by the interrupt handler.
|
||||
//------------------------------------------------------------------------------
|
||||
typedef struct _SdSpiCmd {
|
||||
|
||||
/// Command status.
|
||||
volatile char status;
|
||||
/// Command code.
|
||||
unsigned int cmd;
|
||||
/// Command argument.
|
||||
unsigned int arg;
|
||||
/// Data buffer.
|
||||
unsigned char *pData;
|
||||
/// Size of data buffer in bytes.
|
||||
unsigned short blockSize;
|
||||
/// Number of blocks to be transfered
|
||||
unsigned short nbBlock;
|
||||
/// Indicate if continue to transfer data
|
||||
unsigned char conTrans;
|
||||
/// Indicates if the command is a read operation.
|
||||
unsigned char isRead;
|
||||
/// Response buffer.
|
||||
unsigned int *pResp;
|
||||
/// Size of SD card response in bytes.
|
||||
unsigned char resType;
|
||||
/// Optional user-provided callback function.
|
||||
SdSpiCallback callback;
|
||||
/// Optional argument to the callback function.
|
||||
void *pArg;
|
||||
|
||||
} SdSpiCmd;
|
||||
|
||||
/// Above should be put into SD card header file.
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// SPI driver structure. Holds the internal state of the SPI driver and
|
||||
/// prevents parallel access to a SPI peripheral.
|
||||
//------------------------------------------------------------------------------
|
||||
typedef struct {
|
||||
|
||||
/// Pointer to a SPI peripheral.
|
||||
AT91S_SPI *pSpiHw;
|
||||
/// SPI peripheral identifier.
|
||||
unsigned char spiId;
|
||||
/// Pointer to currently executing command.
|
||||
SdSpiCmd *pCommand;
|
||||
/// Mutex.
|
||||
volatile char semaphore;
|
||||
|
||||
} SdSpi;
|
||||
|
||||
extern void SDSPI_Configure(SdSpi *pSdSpi,AT91PS_SPI pSpiHw,unsigned char spiId);
|
||||
|
||||
extern void SDSPI_SetSpeed(SdSpi *pSdSpi, unsigned int spiSpeed);
|
||||
|
||||
extern unsigned char SDSPI_SendCommand(SdSpi *pSdSpi, SdSpiCmd *pSdSpiCmd);
|
||||
|
||||
extern void SDSPI_Handler(SdSpi *pSdSpi);
|
||||
|
||||
extern unsigned char SDSPI_IsTxComplete(SdSpiCmd *pSdSpiCmd);
|
||||
|
||||
extern unsigned char SDSPI_IsBusy(SdSpi *pSdSpi);
|
||||
|
||||
extern unsigned char SDSPI_NCS(SdSpi *pSdSpi);
|
||||
|
||||
extern void SDSPI_Close(SdSpi *pSdSpi);
|
||||
|
||||
extern void SDSPI_ConfigureCS(SdSpi *pSdSpi, unsigned char cs, unsigned int csr);
|
||||
|
||||
extern unsigned char SDSPI_StopTranToken(SdSpi *pSdSpi);
|
||||
|
||||
extern unsigned char SDSPI_Wait(SdSpi *pSdSpi, unsigned int cycles);
|
||||
|
||||
extern unsigned char SDSPI_WaitDataBusy(SdSpi *pSdSpi);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -50,7 +50,7 @@ enum EnumTabDiag {
|
||||
};
|
||||
|
||||
void menuProcSetup(uint8_t event);
|
||||
#if defined(PCBV4)
|
||||
#if defined(PCBV4) && defined(SDCARD)
|
||||
void menuProcTime(uint8_t event);
|
||||
#endif
|
||||
void menuProcTrainer(uint8_t event);
|
||||
@@ -61,7 +61,7 @@ void menuProcDiagCalib(uint8_t event);
|
||||
|
||||
const MenuFuncP_PROGMEM menuTabDiag[] PROGMEM = {
|
||||
menuProcSetup,
|
||||
#if defined(PCBV4)
|
||||
#if defined(PCBV4) && defined(SDCARD)
|
||||
menuProcTime,
|
||||
#endif
|
||||
menuProcTrainer,
|
||||
@@ -392,7 +392,7 @@ void menuProcSetup(uint8_t event)
|
||||
}
|
||||
|
||||
|
||||
#if defined(PCBV4)
|
||||
#if defined(PCBV4) && defined(SDCARD)
|
||||
// SD card interface contains Real-Time-Clock chip
|
||||
void menuProcTime(uint8_t event)
|
||||
{
|
||||
|
||||
@@ -395,7 +395,7 @@ DSTATUS disk_initialize (
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
DSTATUS disk_status (
|
||||
BYTE drv /* Physical drive nmuber (0) */
|
||||
BYTE drv /* Physical drive number (0) */
|
||||
)
|
||||
{
|
||||
if (drv) return STA_NOINIT; /* Supports only single drive */
|
||||
|
||||
@@ -120,6 +120,7 @@
|
||||
|
||||
#include "ff.h" /* FatFs configurations and declarations */
|
||||
#include "diskio.h" /* Declarations of low level disk I/O functions */
|
||||
#include "gtime.h"
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
@@ -2027,6 +2028,30 @@ FRESULT f_mount (
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------------*/
|
||||
/* User Provided Date/Time Function for FatFs module */
|
||||
/*---------------------------------------------------------*/
|
||||
/* This is a real time clock service to be called from */
|
||||
/* FatFs module. Any valid time must be returned even if */
|
||||
/* the system does not support a real time clock. */
|
||||
/* This is not required in read-only configuration. */
|
||||
|
||||
uint8_t g_ms100 = 0; // global to allow time set function to reset to zero
|
||||
gtime_t g_unixTime; // global date/time register, incremented each second in per10ms()
|
||||
|
||||
uint32_t o9x_get_fattime(void)
|
||||
{
|
||||
struct gtm t;
|
||||
filltm(&g_unixTime, &t); // create a struct tm date/time structure from global unix time stamp
|
||||
|
||||
/* Pack date and time into a DWORD variable */
|
||||
return ((DWORD)(t.tm_year - 80) << 25)
|
||||
| ((uint32_t)(t.tm_mon+1) << 21)
|
||||
| ((uint32_t)t.tm_mday << 16)
|
||||
| ((uint32_t)t.tm_hour << 11)
|
||||
| ((uint32_t)t.tm_min << 5)
|
||||
| ((uint32_t)t.tm_sec >> 1);
|
||||
}
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
@@ -57,6 +57,7 @@ extern "C" {
|
||||
#include "inttypes.h"
|
||||
#include "integer.h" /* Basic integer types */
|
||||
#include "ffconf.h" /* FatFs configuration options */
|
||||
#include "gtime.h"
|
||||
|
||||
#if _FATFS != _FFCONF
|
||||
#error Wrong configuration file (ffconf.h).
|
||||
@@ -572,4 +573,6 @@ void ff_rel_grant (_SYNC_t); /* Unlock sync object */
|
||||
}
|
||||
#endif
|
||||
|
||||
extern gtime_t g_unixTime; // Global date/time register, incremented each second in per10ms()
|
||||
|
||||
#endif /* _FATFS */
|
||||
|
||||
@@ -34,9 +34,12 @@
|
||||
#ifndef sdcard_h
|
||||
#define sdcard_h
|
||||
|
||||
#include "ff.h"
|
||||
#include "rtc.h"
|
||||
#include "gtime.h"
|
||||
|
||||
#define LOGS_PATH "/9XLOGS" // no trailing slash = important
|
||||
#define MODELS_PATH "/9XMODELS"
|
||||
|
||||
#define MODELS_EXT ".bin"
|
||||
|
||||
extern char g_logFilename[21]; // "/9XLOGS/M00_000.CSV\0" max required length = 21
|
||||
@@ -49,5 +52,9 @@ extern void writeLogs();
|
||||
|
||||
const pm_char *SDCARD_ERROR(FRESULT result);
|
||||
|
||||
// MM/SD card Disk IO Support
|
||||
extern void disk_timerproc(void);
|
||||
extern uint8_t g_ms100; // defined in drivers.cpp
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
+3
-31
@@ -42,11 +42,6 @@ const pm_uchar * s9xsplash = splashdata+4;
|
||||
|
||||
#include "menus.h"
|
||||
|
||||
// MM/SD card Disk IO Support
|
||||
#if defined (PCBV4)
|
||||
gtime_t g_unixTime; // Global date/time register, incremented each second in per10ms()
|
||||
#endif
|
||||
|
||||
EEGeneral g_eeGeneral;
|
||||
ModelData g_model;
|
||||
|
||||
@@ -1875,6 +1870,7 @@ void perMain()
|
||||
ee32_process();
|
||||
else if (TIME_TO_WRITE)
|
||||
eeCheck();
|
||||
sd_poll_10mS();
|
||||
}
|
||||
#else
|
||||
if (!eeprom_buffer_size) {
|
||||
@@ -2078,7 +2074,7 @@ void perMain()
|
||||
if((inacCounter&0x3F)==10) AUDIO_INACTIVITY();
|
||||
}
|
||||
|
||||
#if defined(SDCARD)
|
||||
#if defined(PCBV4) && defined(SDCARD)
|
||||
writeLogs();
|
||||
#endif
|
||||
|
||||
@@ -2258,7 +2254,7 @@ ISR(TIMER0_COMP_vect, ISR_NOBLOCK) //10ms timer
|
||||
|
||||
per10ms();
|
||||
|
||||
#if defined (PCBV4)
|
||||
#if defined (PCBV4) && defined(SDCARD)
|
||||
disk_timerproc();
|
||||
#endif
|
||||
|
||||
@@ -2415,30 +2411,6 @@ ISR(USART0_UDRE_vect)
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined (PCBV4)
|
||||
/*---------------------------------------------------------*/
|
||||
/* User Provided Date/Time Function for FatFs module */
|
||||
/*---------------------------------------------------------*/
|
||||
/* This is a real time clock service to be called from */
|
||||
/* FatFs module. Any valid time must be returned even if */
|
||||
/* the system does not support a real time clock. */
|
||||
/* This is not required in read-only configuration. */
|
||||
|
||||
uint32_t o9x_get_fattime(void) // TODO why not in ff.cpp?
|
||||
{
|
||||
struct gtm t;
|
||||
filltm(&g_unixTime, &t); // create a struct tm date/time structure from global unix time stamp
|
||||
|
||||
/* Pack date and time into a DWORD variable */
|
||||
return ((DWORD)(t.tm_year - 80) << 25)
|
||||
| ((uint32_t)(t.tm_mon+1) << 21)
|
||||
| ((uint32_t)t.tm_mday << 16)
|
||||
| ((uint32_t)t.tm_hour << 11)
|
||||
| ((uint32_t)t.tm_min << 5)
|
||||
| ((uint32_t)t.tm_sec >> 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
void instantTrim()
|
||||
|
||||
+1
-14
@@ -41,11 +41,6 @@
|
||||
#include <string.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#if defined(PCBV4)
|
||||
#include "gruvin9x/ff.h"
|
||||
#include "gruvin9x/gtime.h"
|
||||
#endif
|
||||
|
||||
#if defined(PCBARM)
|
||||
#include "board_ersky9x.h"
|
||||
#endif
|
||||
@@ -761,14 +756,6 @@ extern uint8_t beepAgain;
|
||||
extern uint16_t g_LightOffCounter;
|
||||
extern uint8_t mixWarning;
|
||||
|
||||
// MM/SD card Disk IO Support
|
||||
#if defined (PCBV4)
|
||||
#include "gruvin9x/rtc.h"
|
||||
extern void disk_timerproc(void);
|
||||
extern gtime_t g_unixTime; // global unix timestamp -- hold current time in seconds since 1970-01-01 00:00:00
|
||||
extern uint8_t g_ms100; // defined in drivers.cpp
|
||||
#endif
|
||||
|
||||
extern PhaseData *phaseaddress(uint8_t idx);
|
||||
extern ExpoData *expoaddress(uint8_t idx);
|
||||
extern MixData *mixaddress(uint8_t idx);
|
||||
@@ -880,7 +867,7 @@ enum AUDIO_SOUNDS {
|
||||
#endif
|
||||
|
||||
#if defined(SDCARD)
|
||||
#include "sdcard.h"
|
||||
#include "gruvin9x/sdcard.h"
|
||||
#endif
|
||||
|
||||
#if defined(SOMO)
|
||||
|
||||
Reference in New Issue
Block a user