diff --git a/Lib/FileSystem/fat.lib b/Lib/FileSystem/fat.lib index 0bbe5d4..0f95869 100644 --- a/Lib/FileSystem/fat.lib +++ b/Lib/FileSystem/fat.lib @@ -9,7 +9,7 @@ #ifndef __FAT_LIB #define __FAT_LIB -#define FAT_VERSION 0x0215 +#define FAT_VERSION 0x0216 /*** EndHeader */ @@ -39,7 +39,7 @@ Gotchas and general information: is likely to result in a total data loss for the active partition(s) or the whole device.. -- In order to understand the API and implementation propperly some terms need +- In order to understand the API and implementation properly some terms need to be defined more precisely. - We speak about a DRIVER as a software driver which works with the underlying hardware & media to create a storage system that can host @@ -51,7 +51,7 @@ Gotchas and general information: and therefore no partition table, these are not currently supported in this library. You may partition such removeable media and then it would be useable with this library. A real world example of such media is a - CompactFlash card. + CompactFlash or SD card. - We speak about a PARTITION as a range of logical sectors on a device which hold a file system. If this filesystem is a FAT filesystem we can operate on it. Real world examples of what we understand as a partition is what's @@ -149,7 +149,9 @@ END DESCRIPTION **********************************************************/ #define FAT_FAT12 // comment out to disable FAT12 support #define FAT_FAT16 // comment out to disable FAT16 support +#ifndef FAT_READ_ONLY #define FAT_WRITEACCESS // comment out to disable write operations +#endif //#define FAT_BLOCK // sets library to 'blocking' mode //#define FAT_DEBUG // outputs debug printf statements etc. @@ -161,6 +163,17 @@ END DESCRIPTION **********************************************************/ //#define FAT_USE_FORWARDSLASH // Sets forward slash instead of back slash // as the path separator +// Min/max cluster counts and FAT16 sector count per Microsoft: +// https://technet.microsoft.com/en-us/library/cc776720(v=ws.10).aspx +#define FAT16_MAX_CLUSTERS 65524 +#define FAT32_MIN_CLUSTERS 65527 + +// Maximum partition based on 32KB cluster size, 512 byte sector size. +// Calculation underestimates actual maximum, since it doesn't take into +// account space for reserved sectors, FATs and root directory. Changes +// here require changes to sectors/cluster calculation in fat_FormatPartition(). +#define FAT16_MAX_PARTSECSIZE (FAT16_MAX_CLUSTERS * 32UL * 1024 / 512) + /***********************************************************************/ /* END OF CONFIGURATION - END OF CONFIGURATION - END OF CONFIGURATION */ /***********************************************************************/ @@ -289,7 +302,14 @@ END DESCRIPTION **********************************************************/ #define FAT_BRK_POS -2 // Break file at current position pointer /* Some fixed FAT constants */ +/* Note that FAT_MAX_PARTITIONS defines the number of supported partitions + on a device. The similarly-named macro FAT_MAXPARTITIONS limits the + number of partitions mounted at any one time, and because it's used in + the BIOS you must define it in your Project Options. +*/ +#ifndef FAT_MAX_PARTITIONS #define FAT_MAX_PARTITIONS 4 /* Deal only with primary partitions */ +#endif #define FAT_DIRPS 16 /* number of directory entries per sector */ #define FAT_DIRSZ 32 /* size in bytes of a directory entry */ #define FAT_ROOTSZ 512 /* default max entries in root directory */ @@ -341,6 +361,7 @@ typedef struct unsigned long cluster; /* temporary cluster */ unsigned long offset; /* offset within cluster */ + // 32-bit sector * 512bytes/sector = 2 terabytes, beyond SDHC max of 32GB unsigned long sector; /* sector of entry/file (for access speed) */ unsigned int sofs; /* sector offset */ @@ -373,7 +394,7 @@ typedef struct _FATfile struct _fat_part *part; /* partition on which this file resides */ int type; /* type of file see FAT_FILE etc. */ char flag; /* flag: see below */ - #define FAT_ACCESSED 0x01 /* this file was accsessed - set the time + #define FAT_ACCESSED 0x01 /* this file was accessed - set the time at close */ #define FAT_MODIFIED 0x02 /* this file was modified - set the time and date at close */ @@ -531,7 +552,7 @@ typedef struct _fat_part typedef struct { char jmpBoot[3]; // Jump instuction to Boot Code - char OEMname[8]; // OS Name string + char OEMname[8]; // OS Name string (typically "MSWIN4.1") word byte_sec; // Bytes per sector char sec_clust; // Sectors per cluster word res_sec; // Reserved sector count (FAT12/16=1 FAT32=32) @@ -1160,7 +1181,11 @@ _fat_debug int _fat_new_clust( fat_part *part, unsigned long clust, // Compute ending offset of FAT table fat_end_offset = (part->type == FAT_TYPE_12 ? ( part->fat_len + ((part->fat_len + 1) >> 1)) : (part->fat_len << 1)) % part->byte_sec; - fat_end_offset = (fat_end_offset ? fat_end_offset : part->byte_sec) - 1; + // Note: Next line contains backported bugfix from Dynamic C 10.64 that + // removed an unnecessary "-1" from this calculation. Range checks use a + // >= comparison to fat_end_offset, so it should be the first "out of range" + // value. + fat_end_offset = (fat_end_offset ? fat_end_offset : part->byte_sec); #ifdef FAT_BLOCK if ( !count ) #else @@ -1170,7 +1195,7 @@ _fat_debug int _fat_new_clust( fat_part *part, unsigned long clust, part->freecluster = 0L; // Count cycle requested, clear counts part->totcluster = part->fat_len - 2; // Set total clusters in data area part->nextcluster = 2L; // Set next cluster to allocate - if (part->badcluster = 0xFFFFFFFFL) + if (part->badcluster == 0xFFFFFFFFL) part->badcluster = 0; myclust = 2; fat_sector = 0; @@ -2279,11 +2304,7 @@ _fat_debug int _fat_getname( char *fname, char *buf ) auto word len, i, c, plen; strcpy(buf, " "); // 11 blanks plus null -#ifdef USE_FAR_STRING_LIB - slash = _n_strchr(fname, FAT_SLASH_CH); -#else slash = strchr(fname, FAT_SLASH_CH); -#endif if (slash) len = slash - fname; else @@ -2315,11 +2336,7 @@ _fat_debug int _fat_getname( char *fname, char *buf ) name[0] = 0x05; // Now we use 'name'... -#ifdef USE_FAR_STRING_LIB - dot = _n_strchr(name, '.'); -#else dot = strchr(name, '.'); -#endif if (dot) { // Have extension *dot++ = 0; // Null out the dot @@ -3052,25 +3069,25 @@ _fat_debug int _fat_PartCalc( fat_part *part ) c = ((part->mpart->startsector + part->mpart->partsecsize - part->datastart) / part->sec_clust ) + 2; rc = 0; - if( c < 4087 ) - { + if (c <= CLUST_12MAX) { part->type |= FAT_TYPE_12; /* Volume is FAT12 */ part->fat_len = (unsigned)((c + ( c >> 1 ) + 1) >> 1); #ifndef FAT_FAT12 rc = -ENOSYS; // Error if FAT 12 code not included #endif } - else if( c < 65527 ) - { + else if(c <= FAT16_MAX_CLUSTERS) { part->type |= FAT_TYPE_16; /* Volume is FAT16 */ part->fat_len = (unsigned)c; } - else - { + else if (c >= FAT32_MIN_CLUSTERS) { part->type |= FAT_TYPE_32; /* Volume is FAT32 */ part->fat_len = (unsigned)c << 1; rc = -ENOSYS; /* FAT32 is not supported at this time */ } + else { + rc = -ENOSYS; // too many clusters for FAT16, but not enough for FAT32 + } return rc; } @@ -3418,16 +3435,12 @@ int _fat_automount(word nDrvs, word nDevs, #ifdef FAT_NAND_DEVICE_USED // NAND specific initialization check #ifdef FAT_ALLOW_HOTSWAP // #define'd in fat_config.lib #ifndef FAT_NOHOTSWAP // #define'able by user - // A NULL default volume label indicates that this isa removable + // A NULL default volume label indicates that this is a removable // device. _fat_driver_table[0].type[j] == 0 means that the driver // initialization for this device wasn't complete the last time // through automount. if(strlen(devdesc->sig)==0&&_fat_driver_table[0].type[j]==0 && -#ifdef USE_FAR_STRING_LIB - devdesc->sig && !_n_strcmp(_fatConfig[j].type, "NF")) -#else devdesc->sig && !strcmp(_fatConfig[j].type, "NF")) -#endif { // This is to allow autotmount to succeed to mount a removable XD // card after automount was already called with no XD present. This @@ -3513,11 +3526,7 @@ int _fat_automount(word nDrvs, word nDevs, ladrDev = xalloc(16384); //*** Set offset if not NAND flash *** while((driver->xxx_ReadSector(0L,NULL,dev,ladrDev,0L)) == -EBUSY); -#ifdef USE_FAR_STRING_LIB - if (_n_strcmp(_fatConfig[i].type, "NF")) { -#else if (strcmp(_fatConfig[i].type, "NF")) { -#endif while((driver->xxx_ReadSector(1L,NULL,dev,ladrDev+512,0L))==-EBUSY); } // Read the volume serial number @@ -3547,11 +3556,7 @@ int _fat_automount(word nDrvs, word nDevs, //*** Create volume label from the volume serial number sprintf(devVolLabel, "%08lx", serial); //*** Compare volume label from device to cache -#ifdef USE_FAR_STRING_LIB - if(_n_memcmp(devVolLabel,cacheVolLabel,8)){ -#else if(memcmp(devVolLabel,cacheVolLabel,8)){ -#endif newVolume = 1; #ifdef FAT_VERBOSE printf( @@ -3975,11 +3980,7 @@ int fat_EnumDevice( mbr_drvr *driver, mbr_dev *dev, int devnum, // If NAND flash driver, verify that MBR was created by this libray - // xD factory formatted MBRs aren't valid with this FAT. -#ifdef USE_FAR_STRING_LIB - if (rc || (!_n_strcmp(_fatConfig[dev->dev_num].type, "NF") && -#else if (rc || (!strcmp(_fatConfig[dev->dev_num].type, "NF") && -#endif xmemcmp(mbr_start, temp, 0xE0)) || (xgetint(xptr+510) != 0xAA55)) { #ifdef FAT_VERBOSE @@ -4160,8 +4161,11 @@ _fat_debug int fat_FormatDevice( mbr_dev *dev, int mode ) sec_clust = dev->byte_page / dev->byte_sec; // Sectors in entire device (less first cluster for MBR) dev->part[0].partsecsize = dev->seccount - sec_clust; + if (dev->part[0].partsecsize > FAT16_MAX_PARTSECSIZE) { + dev->part[0].partsecsize = FAT16_MAX_PARTSECSIZE; + } dev->part[0].parttype = ((dev->part[0].partsecsize / sec_clust) - < CLUST_12MAX) ? 1 : 6; + <= CLUST_12MAX) ? 1 : 6; if ((mode == 3) && (retcode != -EUNFORMAT)) { rc = mbr_CreatePartition(dev, 0, type); if (rc) @@ -5518,7 +5522,8 @@ _fat_debug int fat_FormatPartition( mbr_dev *dev, fat_part *part, int pnum, while (part->mpart->partsecsize > (((long)part->sec_clust) << 16)) { part->sec_clust <<= 1; - if (part->sec_clust >= 32) break; + // go up to a maximum sec_clust value of 64 + if (part->sec_clust > 32) break; } } } @@ -5551,11 +5556,7 @@ _fat_debug int fat_FormatPartition( mbr_dev *dev, fat_part *part, int pnum, dev->driver != &(_fat_driver_table[i]); i++); if (i >= num_fat_drivers) return -EIO; //Set part->res_sec based on whether SD card or other device -#ifdef USE_FAR_STRING_LIB - part->res_sec = (_n_strcmp(_fatConfig[i].type, "SD") ? 1 : 4); -#else part->res_sec = (strcmp(_fatConfig[i].type, "SD") ? 1 : 4); -#endif // calculate available clusters for data and FAT x = (part->mpart->partsecsize - (FAT_ROOTSZ / FAT_DIRPS)) / @@ -5683,16 +5684,18 @@ _fat_debug int fat_FormatPartition( mbr_dev *dev, fat_part *part, int pnum, // Set Volume Label // Copy label to vol_label and pad with spaces - if (label) - { + if (label) { i = strlen(label); strncpy(bpb_dat.vol_label, label, 11); - if(i<11)bpb_dat.vol_label[i]=0x20; } - else{ - bpb_dat.vol_label[0] = 0x20; + else { + // If no label provided, create one using the volume ID. + i = sprintf(bpb_dat.vol_label, "%08lX", bpb_dat.vol_ID); + } + while (i < 11) { + // pad volume label with spaces + bpb_dat.vol_label[i++] = ' '; } - if ((rc = fatwtc_write(part->wtc_prt, part->mpart->startsector, 0, 62, paddrSS(&bpb_dat), FAT_BLOCK_FLAGS | WTC_NO_PREIMAGE)) != 62) return rc; diff --git a/Lib/SDflash/SDFLASH.LIB b/Lib/SDflash/SDFLASH.LIB index ce50ce0..0114684 100644 --- a/Lib/SDflash/SDFLASH.LIB +++ b/Lib/SDflash/SDFLASH.LIB @@ -14,19 +14,22 @@ The functions are: sdspi_initDevice sdspi_read_sector +_sdspi_read_sector sdspi_write_sector +_sdspi_write_sector sdspi_WriteContinue sdspi_notbusy +sdspi_print_cid sdspi_print_dev sdspi_getSectorCount sdspi_isWriting sdspi_reset_card -sdspi_sendingAP sdspi_get_status_reg sdspi_init_card sdspi_process_command sdspi_get_csd sdspi_get_scr +sdspi_get_cid sdspi_set_block_length sdspi_debounce sdspi_setLED @@ -40,18 +43,6 @@ Revision History: Rev 1.0 Initial Release #ifndef __SDFLASH_LIB__ #define __SDFLASH_LIB__ -/* -_XMEM_XLAT is a macro to jump to the assembly routine _xmem_xlat from non-root -code -*/ -// Expects A to contain the relevant XPC value; -// HL contains a logical address in 0xE000-0xEFFF range of the data to translate, -// B contains number of bytes to translate (1 <= B <= 255, or 0 for 256 bytes), -// DE' points to a 256-byte translation table in root memory. -// On return, AF and HL' trashed; B set to zero, HL points to first byte after -// translated section. Other regs preserved. -#define _XMEM_XLAT db 0xCF $ dw _xmem_xlat $ db 0 - // Number of SD sockets available, NOT the number of supported devices. // All standard SD memory cards are supported. // Every SD socket must have a static sd_dev_interface structure with @@ -60,6 +51,8 @@ code // values rather than a constant look-up table. #define SDFLASH_MAX_DEVS 1 +#define SDFLASH_SDHC 1 + #ifdef SDFLASH_DEBUG #define _sdflash_nodebug debug #else @@ -205,43 +198,49 @@ code /* * Data packet sizes and buffer offsets */ -#define COMMAND_BYTE_COUNT 6 -#define R1_BYTE_COUNT 1 -#define R2_BYTE_COUNT 2 -#define R3_BYTE_COUNT 3 +#define COMMAND_BYTE_COUNT 6 // All SPI commands sent as 48 bits +#define R1_BYTE_COUNT 1 // R1 responses are 1 byte +#define R2_BYTE_COUNT 2 // R2 responses are 2 bytes +#define R3_BYTE_COUNT 5 // R3 (READ_OCR) responses are 5 bytes +#define R7_BYTE_COUNT 5 // R7 (SEND_IF_COND) responses are 5 bytes + +// largest response that doesn't include a data block +#define MAX_RESPONSE_COUNT R7_BYTE_COUNT + /* CSD = 16 bytes data, 1 byte start block and 2 bytes for 16 bit CRC */ #define CSD_BYTE_COUNT 19 #define BLOCK_SIZE 512L /* DATA BLOCK = 512 bytes data, 1 byte start block and 2 bytes for 16 bit CRC */ -#define DATA_BLOCK_SIZE BLOCK_SIZE + 3 +#define DATA_BLOCK_SIZE (BLOCK_SIZE + 3) #define DATA_RESPONSE_BYTE_COUNT 1 -// COMMAND R1 = NCS_MIN + COMMAND_BYTE_COUNT + NCR_MAX + R1_BYTE_COUNT + NEC_MIN -#define CMD_R1_BUFFER_SIZE 1 -// COMMAND R2 = NCS_MIN + COMMAND_BYTE_COUNT + NCR_MAX + R2_BYTE_COUNT + NEC_MIN -#define CMD_R2_BUFFER_SIZE 2 -#define READ_CSD_BUFFER_SIZE CMD_R2_BUFFER_SIZE + CSD_BYTE_COUNT -#define READ_BLOCK_BUFFER_SIZE CMD_R2_BUFFER_SIZE + DATA_BLOCK_SIZE -#define READ_SCR_BUFFER_SIZE CMD_R2_BUFFER_SIZE + SCR_BYTE_COUNT +#define READ_CSD_BUFFER_SIZE (R2_BYTE_COUNT + CSD_BYTE_COUNT) +#define READ_BLOCK_BUFFER_SIZE (R2_BYTE_COUNT + DATA_BLOCK_SIZE) +#define READ_SCR_BUFFER_SIZE (R2_BYTE_COUNT + SCR_BYTE_COUNT) #define SCR_BYTE_COUNT 11 /* * SD commands supported */ -#define CMD0 0 -#define CMD1 1 -#define CMD9 9 -#define CMD13 13 -#define CMD16 16 -#define CMD17 17 -#define CMD24 24 -#define CMD32 32 -#define CMD33 33 -#define CMD38 38 -#define CMD55 55 -#define CMD59 59 -#define ACMD51 51 -#define ACMD41 41 -#define ACMD42 42 +#define CMD0 0 // GO_IDLE_STATE +#define CMD1 1 // (deprecated command related to MMC) +#define CMD8 8 // SEND_IF_COND +#define CMD9 9 // SEND_CSD +#define CMD10 10 // SEND_CID +#define CMD13 13 // SEND_STATUS +#define CMD16 16 // SET_BLOCKLEN +#define CMD17 17 // READ_SINGLE_BLOCK +#define CMD24 24 // WRITE_BLOCK +#define CMD32 32 // ERASE_WR_BLK_START +#define CMD33 33 // ERASE_WR_BLK_END +#define CMD38 38 // ERASE +#define CMD55 55 // APP_CMD +#define CMD58 58 // READ_OCR +#define CMD59 59 // CRC_ON_OFF + +// Re-use CMD_START flag for application commands (ACMDs) to automate sending CMD55 first +#define ACMD51 (CMD_START + 51) // SEND_SCR +#define ACMD41 (CMD_START + 41) // SD_SEND_OP_COND +#define ACMD42 (CMD_START + 42) // SET_CLR_CARD_DETECT /* * Command retry count @@ -250,6 +249,9 @@ code #define CMD1_RETRIES 5000 #define BUSY_RETRIES 5400 +// number of milliseconds allowed before timeout +#define REPLY_TIMEOUT_MS 2 + /* * Command R1 (one byte command response) error codes */ @@ -284,7 +286,6 @@ code #define CMD_CRC_INDEX NCS_MIN + 5 #define CMD_NCR_OFFSET NCS_MIN + COMMAND_BYTE_COUNT #define R1_MASK_LOW_BITS 0x80 -#define REPLY_TIMEOUT 0x41 #define DATALINE_HIGH 0xFF #define DATALINE_LOW 0x00 #define READ_WRITE_START_BLOCK 0xFE @@ -345,46 +346,37 @@ code extern unsigned short crc_table[256]; /* for optimal ccitt crc16 calculation */ #endif -extern char tx_buffer[READ_BLOCK_BUFFER_SIZE]; extern char rx_buffer[READ_BLOCK_BUFFER_SIZE]; // Non-zero if card in, 0 if no card #define SD_cardDetect(dev) (RdPortI(dev->SDintf->cdport)&(1<SDintf->cdpin)) -//BPM change unnessary longs to ints and chars +#define CSD_IS_SDHC(csd) (csd->CSD_STR == SD_CSD_STR_V2) +#define SD_IS_SDHC(sd) (sd->CSD.CSD_STR == SD_CSD_STR_V2) + + typedef struct sd_csd_type { unsigned char init_ok; unsigned char CSD_STR; - unsigned int SPEC_VERS; + #define SD_CSD_STR_V1 0x00 + #define SD_CSD_STR_V2 0x01 unsigned char TAAC; unsigned char NSAC; unsigned char TRANSPEED; unsigned int CCC; unsigned char R_BL_LEN; - unsigned char R_BL_PART; - unsigned char WR_BL_MIS; - unsigned char RD_BL_MIS; unsigned char DSR_IMP; unsigned int CSIZE; - unsigned char RC_MIN; - unsigned char RC_MAX; - unsigned char WC_MAX; - unsigned char WC_MIN; unsigned char C_SIZE_M; unsigned char ERASE_BLK_EN; - unsigned char SECTOR_SIZE; - unsigned char WP_G_S; - unsigned char WP_G_EN; unsigned char DEF_ECC; unsigned char R2W_FACT; unsigned char WR_BL_LEN; unsigned char WR_BL_PAR; - unsigned char F_FORMATG; unsigned char COPY; unsigned char P_WR_PROT; unsigned char T_WR_PROT; - unsigned char F_FORMAT; unsigned char CRC7; } SD_CSD_TYPE; @@ -398,6 +390,16 @@ typedef struct sd_scr_type char SD_BUS_WIDTHS; } SD_SCR_TYPE; +typedef struct sd_cid_type +{ + unsigned char MID; // manufacturer ID + char OID[2]; // 2-character OEM ID + char PNM[5]; // 5-character product name + unsigned char PRV; // product revision + unsigned long PSN; // 32-bit product serial number + unsigned int MDT; // manufacturing date + unsigned char CRC7; // CRC7 checksum +} SD_CID_TYPE; typedef struct { // Chip select PxDR reg, pin number, control registers @@ -489,10 +491,8 @@ typedef struct sd_device_st unsigned int pagesize; // size (in bytes) of pages in flash device int pagebitshift; // # of 'don't care' bits following page addr. int write_state; // state for write timeout (used by FAT) - unsigned long write_sector; // current sector being written (used by FAT) - char *bptr; // pointer to current write source buffer - int erasebitshift; // "don't care" bits in an erase block address - unsigned int data_timeout; // Computed data timeout value + unsigned int read_timeout_ms; // Computed data timeout value + unsigned int write_timeout_ms; // Computed data timeout value sd_cspin cspin; // Structure with Pin for Chip Select info int port; // Base address for the SD card's SPI port sd_dev_interface *SDintf; // Pointer to sd_dev_interface structure @@ -507,8 +507,8 @@ typedef struct sd_cmd_reply unsigned int reply; unsigned int reply_size; unsigned int data_size; - char * tx_buffer; - char * rx_buffer; + char * data_buffer; + char reply_buffer[MAX_RESPONSE_COUNT]; } SD_CMD_REPLY; int sdspi_initDevice(int indx, sd_dev_interface *sd_dev); @@ -602,7 +602,6 @@ sd_device SD[SDFLASH_MAX_DEVS]; /*** EndHeader */ -char tx_buffer[READ_BLOCK_BUFFER_SIZE]; char rx_buffer[READ_BLOCK_BUFFER_SIZE]; // for optimal ccitt crc16 calculation @@ -678,7 +677,7 @@ DESCRIPTION: Initializes the SD card pointed to by sd_dev and adds PARAMETER1: indx - index into the SD device array to add the card. PARAMETER2: sd_dev - pointer to sd_dev_interface for the SD card. -RETURN VALUE: 0 Success +RETURN VALUE: 0 Success -EIO I/O Error -EINVAL Invalid parameter given -ENOMEDIUM No SD card in socket @@ -690,11 +689,11 @@ _sdflash_nodebug int sdspi_initDevice(int indx, sd_dev_interface *sd_dev) { unsigned long t; - int rc, status; -#GLOBAL_INIT { - memset(SD,0,sizeof(SD)); - } - + int rc, status, retry; + sd_device *sd; +#GLOBAL_INIT{ + memset(SD,0,sizeof(SD)); +} if (indx >= SDFLASH_MAX_DEVS || sd_dev == NULL || sd_dev->txport < PCDR || sd_dev->txport > PEDR || (sd_dev->txport & 15) != 0) { return -EINVAL; @@ -707,16 +706,18 @@ int sdspi_initDevice(int indx, sd_dev_interface *sd_dev) *sd_dev->sptcrShadow | sd_dev->sptcrValue); WrPortI(sd_dev->spdivreg, sd_dev->spdivregShadow, sd_dev->divisor); - SD[indx].SDintf = sd_dev; - SD[indx].port = sd_dev->spdr; - SD[indx].cspin.port = sd_dev->csport; - SD[indx].cspin.shadow = sd_dev->csportdrShadow; - SD[indx].cspin.pin = sd_dev->cspin; + sd = &SD[indx]; + sd->SDintf = sd_dev; + sd->port = sd_dev->spdr; + sd->cspin.port = sd_dev->csport; + sd->cspin.shadow = sd_dev->csportdrShadow; + sd->cspin.pin = sd_dev->cspin; - SD[indx].write_state = 0; // Used by FAT, just set to zero - SD[indx].write_sector = 0; - SD[indx].data_timeout = 1000; // Initial timeout, will be replaced - // when CSD has been read from card + sd->write_state = 0; // Used by FAT, just set to zero + // set default read/write timeouts for SDHC cards, updated + // for SD cards after reading CSD. + sd->read_timeout_ms = 100; + sd->write_timeout_ms = 250; // Initial disabling of Chip Select if(sd_dev->csport == GOCR) { @@ -828,139 +829,52 @@ int sdspi_initDevice(int indx, sd_dev_interface *sd_dev) #endif #ifdef SDFLASH_VERBOSE - printf("sdspi_initDevice: calling sdspi_reset_card()\n"); + printf("%s: calling %s()\n", "sdspi_initDevice", "sdspi_reset_card"); #endif - if(rc = sdspi_reset_card(&SD[indx])) + if(rc = sdspi_reset_card(sd)) { return rc; } -#ifdef SDFLASH_VERBOSE - printf("sdspi_initDevice: calling sdspi_init_card()\n"); -#endif // All commands following the card reset have single level retry // on an I/O error condition. SD cards seem prone to these after // being reset. - if ((rc = sdspi_init_card(&SD[indx])) == -EIO) { - rc = sdspi_init_card(&SD[indx]); - } - if (rc) { - return rc; - } + #define _RETRY(CMD) \ + for (retry = 2; retry && (rc = CMD) == -EIO; --retry); if (rc) return rc; #ifdef SDFLASH_VERBOSE - printf("sdspi_initDevice: calling sdspi_get_csd()\n"); + printf("%s: calling %s()\n", "sdspi_initDevice", "sdspi_init_card"); #endif - if ((rc = sdspi_get_csd(&SD[indx])) == -EIO) { - rc = sdspi_get_csd(&SD[indx]); - } - if (rc) { - return rc; - } + _RETRY(sdspi_init_card(sd)) #ifdef SDFLASH_VERBOSE - printf("sdspi_initDevice: calling sdspi_get_scr()\n"); + printf("%s: calling %s()\n", "sdspi_initDevice", "sdspi_get_csd"); #endif - if ((rc = sdspi_get_scr(&SD[indx])) == -EIO) { - rc = sdspi_get_scr(&SD[indx]); - } - if (rc) { - return rc; - } + _RETRY(sdspi_get_csd(sd)) #ifdef SDFLASH_VERBOSE - printf("sdspi_initDevice: calling sdspi_set_block_length()\n"); + printf("%s: calling %s()\n", "sdspi_initDevice", "sdspi_get_scr"); #endif - if ((rc = sdspi_set_block_length(&SD[indx], 512)) == -EIO) { - rc = sdspi_set_block_length(&SD[indx], 512); - } - if (rc) { - return rc; - } + _RETRY(sdspi_get_scr(sd)) + if (sd->CSD.R_BL_LEN != 9) { + // try to change block length if not already 512 #ifdef SDFLASH_VERBOSE - printf("sdspi_initDevice: calling sdspi_get_status_reg()\n"); + printf("%s: calling %s()\n", "sdspi_initDevice", "sdspi_set_block_length"); #endif - if ((rc = sdspi_get_status_reg(&SD[indx], &status)) == -EIO) { - rc = sdspi_get_status_reg(&SD[indx], &status); + _RETRY(sdspi_set_block_length(sd, 512)) } - if (rc) { - return rc; - } - SD[indx].next = NULL; - - return rc; -} - -/*** BeginHeader sdspi_bitrev */ -void sdspi_bitrev(char *buffer, int len); - -/************************************************************************* -sdspi_bitrev - -SYNTAX: int sdspi_bitrev(char *buffer, int len) - -DESCRIPTION: Translates in place a number of bytes in a root buffer - into their bit-reversed equivelants. (e.g. 0x34 -> 0x2C) - -PARAMETER1: buffer - root buffer with bytes to be altered -PARAMETER2: len - number of bytes to bit reverse - -**************************************************************************/ - -/*** EndHeader */ + +#ifdef SDFLASH_VERBOSE + printf("%s: calling %s()\n", "sdspi_initDevice", "sdspi_get_status_reg"); +#endif + _RETRY(sdspi_get_status_reg(sd, &status)) -_sdflash_nodebug void sdspi_bitrev(char *buffer, int len) -{ + sd->next = NULL; - while(len > 0) - { - #asm - ld hl,BitRevTable - ex de',hl ; DE' has table address - ld hl,(sp+@sp+len) - ld b, 0 ; reset b to zero - ld a,h ; get upper byte of len - and a ; check if zero - jr nz,.sdnoload ; don't load b if greater than 255 - ld b,L ; Count in B (1..256) -.sdnoload: - ld hl,(sp+@sp+buffer) - _XMEM_XLAT ; This won't care about the value of A, since not xmem. - ; Residual HL value is returned. - #endasm - len -= 256; - buffer += 256; - } + return rc; } -/*** BeginHeader _xmem_xlat */ -/*=== Do NOT call this function from C! ===*/ -/* -_xmem_xlat translates bytes in a buffer using a supplied translation table -hl - logical address of bytes to translate -'de - translation table in root memory -b - number of bytes to translate, 0 means 256 -*/ -root char * _xmem_xlat(/* register params */void); -/*** EndHeader */ -#asm root nodebug -_xmem_xlat:: - ld xpc,a -.loop: - ld a,(hl) - exx - bool hl - ld L,a - add hl,de - ld a,(hl) - exx - ld (hl),a - inc hl - djnz .loop - lret -#endasm - /*** BeginHeader sdspi_print_dev */ void sdspi_print_dev(sd_device *dev); @@ -986,7 +900,6 @@ void sdspi_print_dev(sd_device *dev) printf("\tpagesize: %d\n", dev->pagesize); printf("\tpagebitshift: %d\n", dev->pagebitshift); printf("\twrite_state: %d\n", dev->write_state); - printf("\twrite_sector: %lu\n", dev->write_sector); printf("\tcs_pin:\n"); printf("\t port: 0x%x\n", dev->cspin.port); printf("\t shadow: 0x%x\n", (unsigned int)(dev->cspin.shadow) ); @@ -1043,51 +956,17 @@ int sdspi_isWriting(sd_device *dev) return (sdspi_notbusy(dev->port) ? 0 : 1); } -/*** BeginHeader _sdspi_print_data */ -void _sdspi_print_data(char *dataBuffer, int dataSize); +/*** BeginHeader sdspi_init_reply ***/ +void sdspi_init_reply(SD_CMD_REPLY *reply, int command); /*** EndHeader */ - -/*********************************************************************** -_sdspi_print_data - -SYNTAX: void _sdspi_print_data(char *dataBuffer, int dataSize) - -DESCRIPTION: Prints a formated hex/ASCII dump of (16 bytes per line) - of dataSize bytes of the dataBuffer. - -PARAMETER1: dataBuffer - Pointer to the buffer to be printed -PARAMETER2: dataSize - Number of bytes to be printed - -RETURN VALUE: None -************************************************************************/ _sdflash_nodebug -void _sdspi_print_data(char *dataBuffer, int dataSize) +void sdspi_init_reply(SD_CMD_REPLY *reply, int command) { - auto char ascii_buffer[17]; - auto char hex_buffer[58]; - auto char fbyte; - auto int k; - auto int j; - - ascii_buffer[sizeof(ascii_buffer) - 1] = 0; - for (j = 0L; j < dataSize; j += 16) { - sprintf(hex_buffer, "%04x ", j); - for (k = 0; k < 16; k++) { - if ((j + (long) k) < dataSize) { - fbyte = *(dataBuffer + k + j); - sprintf(hex_buffer + 5 + (3 * k), "%02x ", fbyte); - if (fbyte > 31 && fbyte < 127) { - ascii_buffer[k] = fbyte; - } else { - ascii_buffer[k] = '.'; - } - } else { - sprintf(hex_buffer + 9 + (3 * k), " "); - ascii_buffer[k] = 0; - } - } - printf("%s%s\n", hex_buffer, ascii_buffer); - } + memset(reply, 0, sizeof *reply); + + reply->cmd = command; + reply->reply_size = R1_BYTE_COUNT; + reply->data_buffer = rx_buffer; } /*** Beginheader sdspi_reset_card ***/ @@ -1105,7 +984,7 @@ DESCRIPTION: Resets the SD card pointed to by sd. Function executes PARAMETER1: sd Pointer to sd_device structure for the SD card. -RETURN VALUE: 0 Success +RETURN VALUE: 0 Success -EIO I/O Error -EINVAL Invalid parameter given -ENOMEDIUM No SD card in socket @@ -1122,15 +1001,14 @@ int sdspi_reset_card(sd_device *sd) if (!SD_cardDetect(sd)) { #ifdef SDFLASH_VERBOSE - printf("sdspi_reset_card: no SD card to reset\n"); + printf("%s: no SD card to reset\n", "sdspi_reset_card"); #endif return -ENOMEDIUM; } #ifdef SDFLASH_VERBOSE - printf("sdspi_reset_card: attempting reset\n"); + printf("%s: attempting reset\n", "sdspi_reset_card"); #endif - memset(&cmd_reply, 0, sizeof(SD_CMD_REPLY) ); result = 0; @@ -1140,11 +1018,8 @@ int sdspi_reset_card(sd_device *sd) while (MS_TIMER - t < 1) ; // Send Go to Idle mode command (reset) - cmd_reply.cmd = CMD0; - cmd_reply.reply_size = CMD_R1_BUFFER_SIZE; - cmd_reply.data_size = 0; - cmd_reply.tx_buffer = tx_buffer; - cmd_reply.rx_buffer = rx_buffer; + sdspi_init_reply(&cmd_reply, CMD0); + for (j = 0; j < CMD0_RETRIES; j++) { #ifdef SDFLASH_VERBOSE @@ -1160,7 +1035,7 @@ int sdspi_reset_card(sd_device *sd) if (result != -EAGAIN) { #ifdef SDFLASH_VERBOSE - printf("sdspi_reset_card: Process command failed.\n"); + printf("%s: Process command failed.\n", "sdspi_reset_card"); #endif break; } @@ -1175,9 +1050,8 @@ int sdspi_reset_card(sd_device *sd) if (j >= CMD0_RETRIES) { #ifdef SDFLASH_VERBOSE - printf("sdspi_reset_card: sdspi_process_command() retried %d times," - , CMD0_RETRIES); - printf(" but could not reset SD card\n"); + printf("%s: %s() retried %d times, but could not reset SD card\n", + "sdspi_reset_card", "sdspi_process_command", CMD0_RETRIES); #endif result = -EIO; } @@ -1191,52 +1065,7 @@ int sdspi_reset_card(sd_device *sd) /*** Beginheader sdspi_sendingAP ***/ int sdspi_sendingAP(sd_device *sd); /*** endheader ***/ - -/* START FUNCTION DESCRIPTION ******************************************** -sdspi_sendingAP - -SYNTAX: int sdspi_sendingAP(sd_device *sd) - -DESCRIPTION: Sends AP command 55 to set Alternate Command mode on - the next command sent to the card. This function does - not release the port sharing semaphore unless an error - is encountered. - -PARAMETER1: sd Pointer to sd_device structure for the SD card. - -RETURN VALUE: 0 Success - -EIO I/O Error - -ENOMEDIUM No SD card in socket - -ESHAREDBUSY Shared SPI port busy - -END DESCRIPTION **********************************************************/ - -_sdflash_nodebug -int sdspi_sendingAP(sd_device *sd) -{ - - int result; - SD_CMD_REPLY cmd_reply; - - memset(&cmd_reply, 0, sizeof(SD_CMD_REPLY) ); - - cmd_reply.cmd = CMD55; - cmd_reply.reply_size = CMD_R1_BUFFER_SIZE; - cmd_reply.data_size = 0; - cmd_reply.tx_buffer = tx_buffer; - cmd_reply.rx_buffer = rx_buffer; - if (result = sdspi_process_command(sd, &cmd_reply, 0)) - { -#ifdef SDFLASH_VERBOSE - printf("sdspi_sendingAP: sdspi_process_command() failed, error %d\n", - result); -#endif - _sdspi_end_command(sd); - _SPIfreeSemaphore(SPI_SD); - } - - return result; -} +#fatal "sdspi_sendingAP functionality incorporated into sdspi_process_command()" /*** Beginheader sdspi_get_status_reg ***/ @@ -1254,7 +1083,7 @@ DESCRIPTION: This function is called to execute protocol command 13 to PARAMETER1: sd Pointer to the device structure for the SD card. PARAMETER2: status Pointer to variable that returns the status. -RETURN VALUE: 0 Success, Card status placed in status +RETURN VALUE: 0 Success, Card status placed in status -EIO I/O Error -ENOMEDIUM No SD card in socket -ESHAREDBUSY Shared SPI port busy @@ -1267,23 +1096,11 @@ int sdspi_get_status_reg(sd_device *sd, int * status) int result; SD_CMD_REPLY cmd_reply; - memset(&cmd_reply, 0, sizeof(SD_CMD_REPLY) ); - result = 0; + sdspi_init_reply(&cmd_reply, CMD13); + cmd_reply.reply_size = R2_BYTE_COUNT; - cmd_reply.cmd = CMD13; - cmd_reply.reply_size = CMD_R2_BUFFER_SIZE; - cmd_reply.data_size = 0; - cmd_reply.tx_buffer = tx_buffer; - cmd_reply.rx_buffer = rx_buffer; - - if (result = sdspi_process_command(sd, &cmd_reply, 1)) - { -#ifdef SDFLASH_VERBOSE - printf("sdspi_get_status_reg: process command failed, error %d(%d)\n", - result, *status); -#endif - } - else + result = sdspi_process_command(sd, &cmd_reply, 1); + if (result == 0) { *status = cmd_reply.reply; } @@ -1291,9 +1108,13 @@ int sdspi_get_status_reg(sd_device *sd, int * status) } -/*** Beginheader sdspi_init_card ***/ +/*** BeginHeader sdspi_init_card */ int sdspi_init_card(sd_device *sd); -/*** endheader ***/ +/*** EndHeader */ +#define CMD8_VOLTAGE_SUPPLIED 0x0100 // 2.7V to 3.6V +#define CMD8_CHECK_PATTERN 0xA5 + +#define ACMD41_HCS_BIT 0x40000000 /* START FUNCTION DESCRIPTION ******************************************** sdspi_init_card @@ -1306,42 +1127,63 @@ DESCRIPTION: Initializes the SD card pointed to by sd. Function PARAMETER1: sd Pointer to sd_device structure for the SD card. -RETURN VALUE: 0 Success +RETURN VALUE: 0 Success -EIO I/O Error -EINVAL Invalid parameter given -ENOMEDIUM No SD card in socket -ESHAREDBUSY Shared SPI port busy END DESCRIPTION **********************************************************/ - _sdflash_nodebug int sdspi_init_card(sd_device *sd) { int result, j; + int cmd8_success; SD_CMD_REPLY cmd_reply; #ifdef SDFLASH_VERBOSE - printf("sdspi_init_card: attempting init"); + printf("%s: attempting init\n", "sdspi_init_card"); #endif result = 0; - memset(&cmd_reply, 0, sizeof(SD_CMD_REPLY) ); - cmd_reply.cmd = CMD1; - cmd_reply.reply_size = CMD_R1_BUFFER_SIZE; - cmd_reply.data_size = 0; - cmd_reply.tx_buffer = tx_buffer; - cmd_reply.rx_buffer = rx_buffer; - - for (j = 0; j < CMD1_RETRIES; j++) + + sdspi_init_reply(&cmd_reply, CMD8); + cmd_reply.argument = CMD8_VOLTAGE_SUPPLIED | CMD8_CHECK_PATTERN; + cmd_reply.reply_size = R7_BYTE_COUNT; + if (result = sdspi_process_command(sd, &cmd_reply, 1)) + { + return result; + } + else + { + if (cmd_reply.reply & R1_ILLEGAL_COMMAND) { + cmd8_success = FALSE; + } + else if (! (cmd_reply.reply & ~R1_IDLE_STATE)) { + cmd8_success = (cmd_reply.reply_buffer[4] == CMD8_CHECK_PATTERN); + } + else // some error bit other than ILLEGAL_COMMAND or IDLE_STATE set + { + return -EIO; + } + } + + for (j = 0; j < 2000; j++) { #ifdef SDFLASH_VERBOSE printf("*"); +#endif + sdspi_init_reply(&cmd_reply, ACMD41); +#if SDFLASH_SDHC + cmd_reply.argument = cmd8_success ? ACMD41_HCS_BIT : 0; +#else + cmd_reply.argument = 0; #endif if (result = sdspi_process_command(sd, &cmd_reply, 1)) { #ifdef SDFLASH_VERBOSE - printf("sdspi_init_card: sdspi_process_command failed, error %d\n", - result); + printf("%s: %s failed, error %d\n", "sdspi_init_card", + "sdspi_process_command", result); #endif return result; } @@ -1352,14 +1194,14 @@ int sdspi_init_card(sd_device *sd) if (cmd_reply.reply != R1_IDLE_STATE) { #ifdef SDFLASH_VERBOSE - printf("sdspi_init_card: command response error %d\n", - cmd_reply.reply); + printf("%s: command response error %d\n", + "sdspi_init_card", cmd_reply.reply); #endif return -EIO; } } else - break; + break; } } @@ -1370,6 +1212,59 @@ int sdspi_init_card(sd_device *sd) return result; } + +/*** BeginHeader crc16_calc */ +unsigned crc16_calc(void *data, unsigned length, unsigned current); +/*** EndHeader */ +// Dynamic C 10 has a shared crc16_calc(). Mimic its API for SDFLASH.LIB +// in Dynamic C 9. +_sdflash_nodebug +unsigned crc16_calc(void *data, unsigned length, unsigned current) +{ + unsigned char *bytes; + + bytes = data; + while (length--) { + current = (current << 8) ^ crc_table[(current >> 8) ^ *bytes++]; + } + return current; +} + + +/*** BeginHeader mem_dump */ +// Copied from Dynamic C 10. Used for verbose debug output. +void mem_dump(void *pblock, word len); +/*** EndHeader */ +_sdflash_nodebug +void mem_dump(void *pblock, word len) +{ + auto char buf[67]; + auto word i, j, k, l, m; + auto char *block; + + block = pblock; + i = 0; + for (j = 0; j < len; j += 16) { + memset(buf, ' ', sizeof(buf)-1); + buf[sizeof(buf)-1] = 0; + k = len - j; + if (k > 16) + k = 16; + for(i = j, l = 0, m = 0; l < k; ++i, ++l, m += 3) { + sprintf(buf+m,"%02X", block[i]); + buf[m+2] = ' '; + if (block[i] >= ' ' && block[i] < 0x7F) + buf[50+l] = block[i]; + if((i & 15) == 15) { + printf("%s\n", buf); + } + } + } + if (i & 15) + printf("%s\n", buf); +} + + /*** Beginheader sdspi_process_command ***/ int sdspi_process_command(sd_device *sd, SD_CMD_REPLY * cmd_reply, int mode); /*** endheader ***/ @@ -1409,14 +1304,14 @@ PARAMETER2: cmd_reply Pointer to cmd_reply structure, which contains: reply - storage for command reply reply_size - size in bytes of expected reply data_size - size in bytes of expected data - tx_buffer - pointer to TX buffer to use - rx_buffer - pointer to RX buffer to use + data_buffer - pointer to RX buffer for data + reply_buffer - reply bytes before data block PARAMETER3: mode Zero = SPI port semaphore should be retained. One = If SPI port to be released before return. Two = Attempting SD card reset, otherwise same as one. (Enables -EAGAIN return value) -RETURN VALUE: 0 Success +RETURN VALUE: 0 Success -EIO I/O Error -EAGAIN Allowable I/O error during card reset -EINVAL Invalid parameter given @@ -1428,111 +1323,163 @@ END DESCRIPTION **********************************************************/ _sdflash_nodebug int sdspi_process_command(sd_device *sd, SD_CMD_REPLY * cmd_reply, int mode) { - int result, rc, i; - unsigned short crc7; - char * cmd_buffer; + static const unsigned char _cmd55[8] = + { 0xFF, 0x77, 0x00, 0x00, 0x00, 0x00, 0x65, 0xFF }; + int rc, i, j; + unsigned short crc7, crc16; + unsigned char request[8]; + unsigned char r1, r2; + +#ifdef SDFLASH_VERBOSE + if (cmd_reply) { + printf("%s: %s%u 0x%08lX\n", "sdspi_process_command", + (cmd_reply->cmd & CMD_START) ? "ACMD" : "CMD", + (cmd_reply->cmd & ~CMD_START), cmd_reply->argument); + } +#endif - if (!sd) { + if (!sd || !cmd_reply) { +#ifdef SDFLASH_VERBOSE + printf("%s: invalid parameter.\n", "sdspi_process_command"); +#endif return -EINVAL; } + if (cmd_reply->reply_size > MAX_RESPONSE_COUNT) { +#ifdef SDFLASH_VERBOSE + printf("%s: reply size (%u) > %u\n", "sdspi_process_command", + cmd_reply->reply_size, MAX_RESPONSE_COUNT); +#endif + return -EINVAL; + } if (!SD_cardDetect(sd)) { #ifdef SDFLASH_VERBOSE - printf("sdspi_process_command: No SD card to present.\n"); + printf("%s: No SD card present.\n", "sdspi_process_command"); #endif return -ENOMEDIUM; } - result = 0; - cmd_buffer = NULL; - crc7 = 0; - cmd_reply->tx_buffer[CMD_INDEX_OFFSET] = CMD_START | cmd_reply->cmd; - cmd_reply->tx_buffer[CMD_ARGUMENT_OFFSET] = (char)(cmd_reply->argument>>24L); - cmd_reply->tx_buffer[CMD_ARGUMENT_OFFSET+1]=(char)(cmd_reply->argument>>16L); - cmd_reply->tx_buffer[CMD_ARGUMENT_OFFSET+2]=(char)(cmd_reply->argument>>8L); - cmd_reply->tx_buffer[CMD_ARGUMENT_OFFSET+3]=(char)(cmd_reply->argument); - - cmd_buffer = &cmd_reply->tx_buffer[CMD_INDEX_OFFSET]; - for (i = 0; i < COMMAND_BYTE_COUNT - 1; i++) + request[0] = 0xFF; + request[1] = CMD_START | cmd_reply->cmd; + request[2] = (char)(cmd_reply->argument>>24L); + request[3] = (char)(cmd_reply->argument>>16L); + request[4] = (char)(cmd_reply->argument>>8L); + request[5] = (char)(cmd_reply->argument); + for (crc7 = 0, i = 1; i < 6; i++) { - crc7 = _sd_crc7(crc7, cmd_buffer[i]); + crc7 = _sd_crc7(crc7, request[i]); } - - cmd_reply->tx_buffer[CMD_CRC_INDEX] = (crc7 << 1) | CMD_END; - sdspi_bitrev(cmd_buffer, COMMAND_BYTE_COUNT); - + request[6] = (crc7 << 1) | CMD_END; + request[7] = 0xFF; + rc = _SPIgetSemaphore(SPI_SD); if (rc) { // Semaphore is being held by another device, SPI port is busy #ifdef SDFLASH_VERBOSE - printf("_SPIgetSemaphore returned %d in sdspi_process_command\n", rc); + printf("%s: _SPIgetSemaphore returned %d\n", "sdspi_process_command", rc); #endif return -ESHAREDBUSY; // And return error that SPI port is busy } - rc = _sdspi_ReadWrite(sd, cmd_reply->tx_buffer, cmd_reply->rx_buffer, - cmd_reply->reply_size, cmd_reply->data_size, mode); - - if (rc) - { + SD_ENABLECS(sd->SDintf); + if (cmd_reply->cmd & CMD_START) { + // send CMD55 prefix for ACMD + _sdspi_write_block(_cmd55, sizeof(_cmd55), sd->port); + _sdspi_read_block(&r1, 1, sd->port, REPLY_TIMEOUT_MS); #ifdef SDFLASH_VERBOSE - printf("sdspi_process_command: Error sending command\n"); + printf("%s: (CMD55's R1=0x%02X)\n", "sdspi_process_command", r1); #endif - _sdspi_end_command(sd); - _SPIfreeSemaphore(SPI_SD); - return (mode == 2 ? -EAGAIN : rc); } - - for (i = 0; i < (int)cmd_reply->reply_size; i++) - { - if (cmd_reply->rx_buffer[i] != DATALINE_HIGH) - { - if (cmd_reply->rx_buffer[i] & 0x01) // Bits still reversed - { // so MSB is currently LSB + _sdspi_write_block(request, 8, sd->port); + rc = _sdspi_read_block(cmd_reply->reply_buffer, cmd_reply->reply_size, + sd->port, REPLY_TIMEOUT_MS); + if (cmd_reply->data_size && rc > 0) { + rc = _sdspi_read_block(cmd_reply->data_buffer, cmd_reply->data_size, + sd->port, sd->read_timeout_ms); + if (rc > 0) { +#ifdef SDFLASH_VERBOSE + printf("%s: read %u bytes:\n", "sdspi_process_command", rc); + mem_dump(cmd_reply->data_buffer, rc); +#endif + if (cmd_reply->data_buffer[0] != READ_WRITE_START_BLOCK) { #ifdef SDFLASH_VERBOSE - printf("sdspi_process_command: Response high bit not 0\n"); + printf("%s: invalid data block start 0x%x\n", + "sdspi_process_command", cmd_reply->data_buffer[0]); #endif - if (cmd_reply->reply_size == 1) cmd_reply->reply_size = 2; - cmd_reply->rx_buffer[i] = BitRevTable[cmd_reply->rx_buffer[i]]; - _sdspi_end_command(sd); - _SPIfreeSemaphore(SPI_SD); - return (mode == 2 ? -EAGAIN : -EIO); + return -EIO; } - else - { - if (cmd_reply->cmd == CMD13) - { - // SD card returns 2 bytes when command 13 is issued - cmd_reply->reply = BitRevTable[cmd_reply->rx_buffer[i]]; - cmd_reply->reply <<= 8; - cmd_reply->reply |= BitRevTable[cmd_reply->rx_buffer[i+1]]; - } - else - { - cmd_reply->reply = BitRevTable[cmd_reply->rx_buffer[i]]; - } - break; + + /* The crc16 for data block, including 2-byte CRC, should be 0. */ + crc16 = crc16_calc(&cmd_reply->data_buffer[1], rc - 1, 0); + if (crc16) { +#ifdef SDFLASH_VERBOSE + printf("%s: CRC16 failed 0x%04x\n", "sdspi_process_command", crc16); +#endif + return -EIO; } } } - - if (i >= (int)cmd_reply->reply_size) + if (mode) { + _sdspi_end_command(sd); + _SPIfreeSemaphore(SPI_SD); + } + + if (rc < 0) { #ifdef SDFLASH_VERBOSE - printf("sdspi_process_command: SD device did not respond\n"); + printf("%s: Error %d sending command\n", "sdspi_process_command", rc); #endif - _sdspi_end_command(sd); - _SPIfreeSemaphore(SPI_SD); - result = -EIO; + _sdspi_end_command(sd); + _SPIfreeSemaphore(SPI_SD); + return (mode == 2 ? -EAGAIN : rc); } - // Reverse data bits (if there are any) - if (cmd_reply->data_size) { - sdspi_bitrev(cmd_reply->rx_buffer + cmd_reply->reply_size, - cmd_reply->data_size); + r1 = cmd_reply->reply_buffer[0]; + if (r1 & R1_MASK_LOW_BITS) { +#ifdef SDFLASH_VERBOSE + printf("%s: Response high bit not 0 (0x%02X)\n", "sdspi_process_command", r1); +#endif + _sdspi_end_command(sd); + _SPIfreeSemaphore(SPI_SD); + return (mode == 2 ? -EAGAIN : -EIO); + } + + if (cmd_reply->reply_size == 2) { + r2 = cmd_reply->reply_buffer[1]; + cmd_reply->reply = (r1 << 8) | r2; + } else { + cmd_reply->reply = r1; } - return result; +#ifdef SDFLASH_VERBOSE + printf("%s: reply R1 0x%x ", "sdspi_process_command", r1); + if (r1 & R1_IDLE_STATE) printf("IDLE "); + if (r1 & R1_ERASE_RESET) printf("ERASE_RST "); + if (r1 & R1_ILLEGAL_COMMAND) printf("ILLEGAL_CMD "); + if (r1 & R1_CRC_ERROR) printf("CRC_ERR "); + if (r1 & R1_ERASE_SEQUENCE_ERROR) printf("ERASE_SEQ_ERR "); + if (r1 & R1_ADDRESS_ERROR) printf("ADDR_ERR "); + if (r1 & R1_PARAMETER_ERROR) printf("PARAM_ERR "); + printf("\n"); + if (cmd_reply->reply_size == 2) { + printf("%s: reply R2 0x%x ", "sdspi_process_command", r2); + if (r2 & R2_CARD_LOCKED) printf("CARD_LOCK "); + if (r2 & R2_WRITE_PROTECT_ERASE) printf("WR_PROT_ERASE "); + if (r2 & R2_GENERAL_ERROR) printf("GEN_ERR "); + if (r2 & R2_CC_ERROR) printf("CC_ERR "); + if (r2 & R2_CARD_ECC_FAILED) printf("CARD_LOCK "); + if (r2 & R2_WRITE_PROTECT_VIOLATION) printf("WR_PROT_VIOL "); + if (r2 & R2_ERASE_PARAM) printf("ERASE_PARAM "); + if (r2 & R2_OUT_OF_RANGE) printf("OUT_OF_RANGE "); + printf("\n"); + } else if (cmd_reply->reply_size > 2) { + printf("%s: reply data:\n", "sdspi_process_command"); + mem_dump(&cmd_reply->reply_buffer[1], cmd_reply->reply_size - 1); + } +#endif + + _SPIfreeSemaphore(SPI_SD); + return 0; } /*** Beginheader _sd_crc7 ***/ @@ -1570,6 +1517,117 @@ unsigned short _sd_crc7(unsigned short crc7, unsigned char ch) return crc7; } +/*** BeginHeader _sdspi_get_R2_cmd */ +int _sdspi_get_R2_cmd(sd_device *sd, SD_CMD_REPLY *cmd_reply); +/*** EndHeader */ +_sdflash_nodebug +int _sdspi_get_R2_cmd(sd_device *sd, SD_CMD_REPLY *cmd_reply) +{ + int result; + int j; + + j = 4; + cmd_reply->data_size = CSD_BYTE_COUNT; + do { + result = sdspi_process_command(sd, cmd_reply, 1); + } while (!result && cmd_reply->reply && --j); + if (j == 0) { + result = -EIO; + } + + return result; +} + +/*** BeginHeader sdspi_get_cid */ +int sdspi_get_cid(sd_device *sd, SD_CID_TYPE *cid); +/*** EndHeader */ +/* START FUNCTION DESCRIPTION ******************************************** +sdspi_get_cid + +SYNTAX: int sdspi_get_cid(sd_device *sd, SD_CID_TYPE *cid) + +DESCRIPTION: This function is called to execute protocol command 10 to + retrieve the SD card's Card IDenticiation (CID). See + sdspi_print_cid() for information on parsing that structure. + +PARAMETER1: sd The device structure for the SD card. + +PARAMETER2: cid Structure to hold the 16-byte CID + +RETURN VALUE: 0 Success + -EIO I/O Error + -EINVAL Invalid parameter given + -ENOMEDIUM No SD card in socket + -ESHAREDBUSY Shared SPI port busy + +END DESCRIPTION **********************************************************/ +_sdflash_nodebug +int sdspi_get_cid(sd_device *sd, SD_CID_TYPE *cid) +{ + int result; + SD_CMD_REPLY cmd_reply; + + if (cid == NULL) { + return -EINVAL; + } + + sdspi_init_reply(&cmd_reply, CMD10); + result = _sdspi_get_R2_cmd(sd, &cmd_reply); + if (result == 0) { + memcpy(cid, &cmd_reply.data_buffer[1], 16); + } + + return result; +} + +/*** BeginHeader sdspi_print_cid */ +void sdspi_print_cid(const SD_CID_TYPE *cid); +/*** EndHeader */ +/* START FUNCTION DESCRIPTION ******************************************** +sdspi_print_cid + +SYNTAX: void sdspi_print_cid(const SD_CID_TYPE *cid) + +DESCRIPTION: Prints parameters from the SD Card IDentification register. + +PARAMETER1: cid - pointer to SD_CID_TYPE structure loaded by sdspi_get_cid(). + +RETURN VALUE: None + +END DESCRIPTION **********************************************************/ + +// byte-swapping functions copied from net.lib +root unsigned long sd_intel(unsigned long); +root unsigned short sd_intel16(unsigned short); + +#asm root +sd_intel:: + ex de,hl + ld e,b + ld d,c + ld b,l + ld c,h + ret + +sd_intel16:: + ld a,l + ld l,h + ld h,a + ret +#endasm + +_sdflash_nodebug +void sdspi_print_cid(const SD_CID_TYPE *cid) +{ + unsigned int mdt; + + mdt = sd_intel16(cid->MDT); + printf("Manufacturer:0x%02X OEM:'%c%c' Product Name:'%.5s'\n", + cid->MID, cid->OID[0], cid->OID[1], cid->PNM); + printf("Product Rev:%X.%X Serial #:0x%08lX Mfg Date:%u/%u CRC7:0x%02X\n", + cid->PRV >> 4, cid->PRV & 0x0F, sd_intel(cid->PSN), + mdt & 0x000F, 2000 + ((mdt >> 4) & 0x00FF), cid->CRC7); +} /* START FUNCTION DESCRIPTION ******************************************** sdspi_get_csd @@ -1584,7 +1642,7 @@ DESCRIPTION: This function is called to execute protocol command 9 to PARAMETER1: sd The device structure for the SD card. -RETURN VALUE: 0 Success +RETURN VALUE: 0 Success -EIO I/O Error -EINVAL Invalid parameter given -ENOMEDIUM No SD card in socket @@ -1599,217 +1657,164 @@ int sdspi_get_csd(sd_device *sd); _sdflash_nodebug int sdspi_get_csd(sd_device *sd) { + // mapping of TAAC values * 10 + static const unsigned char _taac_table[16] = { + 10, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80 }; int result, j, k; char *csd_buffer; SD_CSD_TYPE *sd_csd; - unsigned short crc7, crc16, x; + unsigned short x; SD_CMD_REPLY cmd_reply; unsigned long temp, l; + char current_byte; sd_csd = &sd->CSD; - - csd_buffer = NULL; - result = 0; - crc16 = 0; - - memset(&cmd_reply, 0x0, sizeof(SD_CMD_REPLY)); memset(sd_csd, 0x0, sizeof(SD_CSD_TYPE)); - cmd_reply.cmd = CMD9; - cmd_reply.reply_size = CMD_R1_BUFFER_SIZE; - cmd_reply.data_size = CSD_BYTE_COUNT; - cmd_reply.tx_buffer = tx_buffer; - cmd_reply.rx_buffer = rx_buffer; - -#ifdef SDFLASH_VERBOSE - printf("sdspi_get_csd: calling sdspi_process_command().\n"); -#endif - if (result = sdspi_process_command(sd, &cmd_reply, 1)) - { + sdspi_init_reply(&cmd_reply, CMD9); + result = _sdspi_get_R2_cmd(sd, &cmd_reply); + if (result != 0) { return result; } - else - { - if (cmd_reply.reply) - { -#ifdef SDFLASH_VERBOSE - printf("sdspi_get_csd: command response error %d\n", cmd_reply.reply); -#endif - return -EIO; - } - } - - for (j = cmd_reply.reply_size; j < READ_CSD_BUFFER_SIZE; j++) - { - if (cmd_reply.rx_buffer[j] != DATALINE_HIGH) - { - if (cmd_reply.rx_buffer[j] == READ_WRITE_START_BLOCK) - break; - else - { -#ifdef SDFLASH_VERBOSE - printf("sdspi_get_csd: Read data error %x\n", - cmd_reply.rx_buffer[j]); -#endif - return -EIO; - } - } - } - if (j >= READ_CSD_BUFFER_SIZE) - { -#ifdef SDFLASH_VERBOSE - printf("sdspi_get_csd: _sdspi_ReadWrite() returned invalid data\n"); -#endif - return -EIO; - } - - - csd_buffer = &cmd_reply.rx_buffer[j + 1]; - - /* Get the crc16 for CSD block and 2 byte CRC */ - for (k = 0; k < CSD_BYTE_COUNT - 1; ++k) - crc16 = (crc16 << 8) ^ crc_table[(crc16 >> 8) ^ csd_buffer[k]]; - - /* - Using the 2 CRC bytes in the crc16 calculation should result in 0; - if not 0 then try the crc7 calculation. - */ - if (crc16) - { - /* The crc16 check failed, so compute crc7 for CSD data */ - crc7 = 0; - for (k = 0; k < CSD_BYTE_COUNT - 4; ++k) - crc7 = _sd_crc7(crc7, csd_buffer[k]); - - if (csd_buffer[CSD_BYTE_COUNT - 4] != (((crc7 << 1) | CMD_END) & 0xFF)) - { -#ifdef SDFLASH_VERBOSE - printf("sdspi_get_csd: CRC mismatch error\n"); -#endif - return -EIO; - } - } - + csd_buffer = &cmd_reply.data_buffer[1]; /* extract the CSD information from the CSD block */ for (k = 0; k < CSD_BYTE_COUNT - 3; k++) { + current_byte = csd_buffer[k]; switch (k) { - case CSD_BLOCK_OFFSET_0: - sd_csd->CSD_STR = csd_buffer[k] >> 6; + case CSD_BLOCK_OFFSET_0: // [127:120] + sd_csd->CSD_STR = current_byte >> 6; break; - case CSD_BLOCK_OFFSET_1: - sd_csd->TAAC = csd_buffer[k]; - x = (sd_csd->TAAC & 0x7C) >> 3; - if ((x < 3) || (x == 15)) { - x++; - } - else { - if (x > 3) x--; - } - // Now x has value times 2 - j = sd_csd->TAAC & 7; - // Create base multiplier in nanoseconds - for (temp = 1; j--; temp *= 10); - // Base multiplier times value divided by character time - temp = ((temp * x) / 1000) + 1; + case CSD_BLOCK_OFFSET_1: // [119:112] + sd_csd->TAAC = current_byte; break; - case CSD_BLOCK_OFFSET_2: - sd_csd->NSAC = csd_buffer[k]; - // Add NSAC timeout to TAAC timeout - temp += (unsigned long)(sd_csd->NSAC) * 100; - // Save timeout in character time in data_timeout (w/ max check) - sd->data_timeout = (temp >= 0x10000 ? 0xFFFF : (unsigned)temp); + case CSD_BLOCK_OFFSET_2: // [111:104] + sd_csd->NSAC = current_byte; +#if SDFLASH_SDHC + if (! CSD_IS_SDHC(sd_csd)) +#endif + { + // Calculate timeout in ms + x = _taac_table[(sd_csd->TAAC >> 3) & 0xF]; + // x has value times 10 (correct value for j == 7) + for (j = sd_csd->TAAC & 7; x && (j != 7); ++j) { + x /= 10; + } + // Calculate NSAC timeout on conservative 1Mhz clock + // NSAC * 100 clocks / 1,000 clocks/msec = NSAC / 10 + x += sd_csd->NSAC / 10; + + // minimum timeout of 2ms + sd->read_timeout_ms = x < 2 ? 2 : x; +#ifdef SDFLASH_VERBOSE + printf("%s: TAAC=0x%02x NSAC=%u\n", "sdspi_get_csd", + sd_csd->TAAC, sd_csd->NSAC); + printf("%s: set %s to %u\n", "sdspi_get_csd", + "read_timeout_ms", sd->read_timeout_ms); +#endif + } break; - case CSD_BLOCK_OFFSET_3: - sd_csd->TRANSPEED = csd_buffer[k]; + case CSD_BLOCK_OFFSET_3: // [103:96] + sd_csd->TRANSPEED = current_byte; break; - case CSD_BLOCK_OFFSET_4: - sd_csd->CCC = csd_buffer[k]; - sd_csd->CCC <<= 4; + case CSD_BLOCK_OFFSET_4: // [95:88] + sd_csd->CCC = current_byte << 4; break; - case CSD_BLOCK_OFFSET_5: - sd_csd->CCC |= csd_buffer[k] >> 4; - sd_csd->R_BL_LEN = csd_buffer[k] & 0x0F; + case CSD_BLOCK_OFFSET_5: // [87:80] + sd_csd->CCC |= current_byte >> 4; + sd_csd->R_BL_LEN = current_byte & 0x0F; break; - case CSD_BLOCK_OFFSET_6: - sd_csd->R_BL_PART = (csd_buffer[k] >> 7) & 0x01; - sd_csd->WR_BL_MIS = (csd_buffer[k] >> 6) & 0x01; - sd_csd->RD_BL_MIS = (csd_buffer[k] >> 5) & 0x01; - sd_csd->DSR_IMP = (csd_buffer[k] >> 4) & 0x01; - sd_csd->CSIZE = csd_buffer[k] & 0x3; - sd_csd->CSIZE <<= 8; + case CSD_BLOCK_OFFSET_6: // [79:72] + sd_csd->DSR_IMP = (current_byte >> 4) & 0x01; + sd_csd->CSIZE = (current_byte & 0x3) << 8; break; - case CSD_BLOCK_OFFSET_7: - sd_csd->CSIZE |= csd_buffer[k]; + case CSD_BLOCK_OFFSET_7: // [71:64] + sd_csd->CSIZE |= current_byte; sd_csd->CSIZE <<= 2; break; - case CSD_BLOCK_OFFSET_8: - sd_csd->CSIZE |= csd_buffer[k] >> 6; - sd_csd->RC_MIN = (csd_buffer[k] >> 3) & 0x07; - sd_csd->RC_MAX = csd_buffer[k] & 0x07; + case CSD_BLOCK_OFFSET_8: // [63:56] +#if SDFLASH_SDHC + if (CSD_IS_SDHC(sd_csd)) { + sd_csd->CSIZE = current_byte << 8; + } else +#endif + { + sd_csd->CSIZE |= current_byte >> 6; + } break; - case CSD_BLOCK_OFFSET_9: - sd_csd->WC_MIN = (csd_buffer[k] >> 5) & 0x07; - sd_csd->WC_MAX = (csd_buffer[k] >> 2) & 0x07; - sd_csd->C_SIZE_M = csd_buffer[k] & 0x3; - sd_csd->C_SIZE_M <<= 1; + case CSD_BLOCK_OFFSET_9: // [55:48] +#if SDFLASH_SDHC + if (CSD_IS_SDHC(sd_csd)) { + sd_csd->CSIZE |= current_byte; + } else +#endif + { + sd_csd->C_SIZE_M = (current_byte & 0x3) << 1; + } break; - case CSD_BLOCK_OFFSET_10: - sd_csd->C_SIZE_M |= (csd_buffer[k] >> 7) & 0x1; - sd_csd->ERASE_BLK_EN = (csd_buffer[k] >> 6) & 0x1; - sd_csd->SECTOR_SIZE = csd_buffer[k] & 0x3F; - sd_csd->SECTOR_SIZE <<= 1; - // Compute the number of 512 byte sectors on the SD card - sd->sectors = ((sd_csd->CSIZE + 1L) << (sd_csd->C_SIZE_M + 2)) - << (sd_csd->R_BL_LEN - 9); + case CSD_BLOCK_OFFSET_10: // [47:40] +#if SDFLASH_SDHC + if (CSD_IS_SDHC(sd_csd)) { + sd->sectors = (sd_csd->CSIZE + 1L) << 10; + } else +#endif + { + sd_csd->C_SIZE_M |= (current_byte >> 7) & 0x1; + // Compute the number of 512 byte sectors on the SD card + // shift C_SIZE_M + 2 and R_BL_LEN - 9 + sd->sectors = (sd_csd->CSIZE + 1L) << + (sd_csd->C_SIZE_M + sd_csd->R_BL_LEN - 7); + } + sd_csd->ERASE_BLK_EN = (current_byte >> 6) & 0x1; break; - case CSD_BLOCK_OFFSET_11: - sd_csd->SECTOR_SIZE += ((csd_buffer[k] & 0x80) >> 7) + 1; - sd_csd->WP_G_S = (csd_buffer[k] & 0x7F) + 1; + case CSD_BLOCK_OFFSET_11: // [39:32] break; - case CSD_BLOCK_OFFSET_12: - sd_csd->WP_G_EN = (csd_buffer[k] >> 7) & 0x01; - sd_csd->R2W_FACT = (csd_buffer[k] >> 2) & 0x07; - sd_csd->WR_BL_LEN = csd_buffer[k] & 0x3; - sd_csd->WR_BL_LEN <<= 2; + case CSD_BLOCK_OFFSET_12: // [31:24] + sd_csd->R2W_FACT = (current_byte >> 2) & 0x07; + sd_csd->WR_BL_LEN = (current_byte & 0x3) << 2; +#if SDFLASH_SDHC + if (! CSD_IS_SDHC(sd_csd)) +#endif + { + sd->write_timeout_ms = sd->read_timeout_ms * (1 << sd_csd->R2W_FACT); +#ifdef SDFLASH_VERBOSE + printf("%s: R2W_FACT=%u (%u)\n", "sdspi_get_csd", + sd_csd->R2W_FACT, (1 << sd_csd->R2W_FACT)); + printf("%s: set %s to %u\n", "sdspi_get_csd", + "write_timeout_ms", sd->write_timeout_ms); +#endif + } break; - case CSD_BLOCK_OFFSET_13: - sd_csd->WR_BL_LEN |= (csd_buffer[k] >> 6) & 0x03; - sd_csd->WR_BL_PAR = (csd_buffer[k] >> 5) & 0x01; + case CSD_BLOCK_OFFSET_13: // [23:16] + sd_csd->WR_BL_LEN |= (current_byte >> 6) & 0x03; + sd_csd->WR_BL_PAR = (current_byte >> 5) & 0x01; sd->pagebitshift = (int)(sd_csd->WR_BL_LEN); sd->pagesize = (int)(1L << sd_csd->WR_BL_LEN); - sd->erasebitshift = sd->pagebitshift; - // Calculate erasebitshift from pagebitshift and sector size - for (j = 1; !(sd_csd->SECTOR_SIZE & j); ++sd->erasebitshift) { - j <<= 1; - } break; - case CSD_BLOCK_OFFSET_14: - sd_csd->F_FORMATG = (csd_buffer[k] >> 7) & 0x01; - sd_csd->COPY = (csd_buffer[k] >> 6) & 0x01; - sd_csd->P_WR_PROT = (csd_buffer[k] >> 5) & 0x01; - sd_csd->T_WR_PROT = (csd_buffer[k] >> 4) & 0x01; - sd_csd->F_FORMAT = (csd_buffer[k] >> 2) & 0x03; + case CSD_BLOCK_OFFSET_14: // [15:8] + sd_csd->COPY = (current_byte >> 6) & 0x01; + sd_csd->P_WR_PROT = (current_byte >> 5) & 0x01; + sd_csd->T_WR_PROT = (current_byte >> 4) & 0x01; break; - case CSD_BLOCK_OFFSET_15: - sd_csd->CRC7 = csd_buffer[k] >> 1; + case CSD_BLOCK_OFFSET_15: // [7:0] + sd_csd->CRC7 = current_byte >> 1; break; } } @@ -1832,7 +1837,7 @@ DESCRIPTION: This function executes application specific command 51 to PARAMETER1: sd The device structure for the SD card. -RETURN VALUE: 0 Success +RETURN VALUE: 0 Success -EIO I/O Error -EINVAL Invalid parameter given -ENOMEDIUM No SD card in socket @@ -1846,97 +1851,32 @@ int sdspi_get_scr(sd_device *sd); _sdflash_nodebug int sdspi_get_scr(sd_device *sd) { - int result, j, k; + int result, k; char *scr_buffer; SD_SCR_TYPE *sd_scr; - unsigned short crc16; SD_CMD_REPLY cmd_reply; - unsigned long temp; - - if (result = sdspi_sendingAP(sd)) { -#ifdef SDFLASH_VERBOSE - printf("sdspi_get_scr: APCMD51 response error %d\n", cmd_reply.reply); -#endif - return result; - } - _sdspi_end_command(sd); sd_scr = &sd->SCR; - - scr_buffer = NULL; - result = 0; - crc16 = 0; - - memset(&cmd_reply, 0x0, sizeof(SD_CMD_REPLY)); memset(sd_scr, 0x0, sizeof(SD_SCR_TYPE)); - cmd_reply.cmd = ACMD51; - cmd_reply.reply_size = CMD_R1_BUFFER_SIZE; + sdspi_init_reply(&cmd_reply, ACMD51); cmd_reply.data_size = SCR_BYTE_COUNT; - cmd_reply.tx_buffer = tx_buffer; - cmd_reply.rx_buffer = rx_buffer; - - if (result = sdspi_process_command(sd, &cmd_reply, 1)) + result = sdspi_process_command(sd, &cmd_reply, 1); + + if (result) { -#ifdef SDFLASH_VERBOSE - printf("sdspi_get_scr: sdspi_process_command() failed, error %d\n", - result); -#endif return result; } - else + else if (cmd_reply.reply) { - if (cmd_reply.reply) - { #ifdef SDFLASH_VERBOSE - printf("sdspi_get_scr: command response error %d\n", cmd_reply.reply); -#endif - return -EIO; - } - } - - for (j = cmd_reply.reply_size; j < READ_SCR_BUFFER_SIZE; j++) - { - if (cmd_reply.rx_buffer[j] != DATALINE_HIGH) - { - if (cmd_reply.rx_buffer[j] == READ_WRITE_START_BLOCK) - break; - else - { -#ifdef SDFLASH_VERBOSE - printf("sdspi_get_scr: Read data error %x\n", - cmd_reply.rx_buffer[j]); -#endif - return -EIO; - } - } - } - if (j >= READ_SCR_BUFFER_SIZE) - { -#ifdef SDFLASH_VERBOSE - printf("sdspi_get_scr: _sdspi_ReadWrite() returned invalid data\n"); + printf("%s: CRC mismatch error\n", "sdspi_get_scr"); #endif return -EIO; } - - scr_buffer = &cmd_reply.rx_buffer[j + 1]; - - /* Get the CRC for SCR block and 2 byte CRC */ - for (k = 0; k < SCR_BYTE_COUNT - 1; k++) - crc16 = (crc16 << 8) ^ crc_table[(crc16 >> 8) ^ scr_buffer[k]]; - - /* Using the 2 CRC bytes in the CRC calculation results in 0 */ - if (crc16) - { -#ifdef SDFLASH_VERBOSE - printf("sdspi_get_scr: CRC mismatch error\n"); -#endif - return -EIO; - } - - - /* extract the SCR information from the CSD block */ + scr_buffer = &cmd_reply.data_buffer[1]; + /* extract the SCR information from the data block */ for (k = 0; k < SCR_BYTE_COUNT - 3; k++) { switch (k) @@ -1962,9 +1902,10 @@ int sdspi_get_scr(sd_device *sd) } -/*** Beginheader sdspi_read_sector ***/ -int sdspi_read_sector(sd_device *sd, unsigned long sector_number, - void * data_buffer); +/*** Beginheader _sdspi_read_sector ***/ +#define sdspi_read_sector(sd, n, buffer) _sdspi_read_sector(sd, n, buffer, 0) +int _sdspi_read_sector(sd_device *sd, unsigned long sector_number, + void * data_buffer, long xbuffer); /*** endheader ***/ /* START FUNCTION DESCRIPTION ******************************************** @@ -1980,7 +1921,31 @@ PARAMETER1: sd The device structure for the SD card. PARAMETER2: sector_number The sector number to read. PARAMETER3: data_buffer Pointer to a buffer for the 512 bytes read -RETURN VALUE: 0 Success +RETURN VALUE: 0 Success + -EIO I/O Error + -EINVAL Invalid parameter given + -ENOMEDIUM No SD card in socket + -ESHAREDBUSY Shared SPI port busy + +END DESCRIPTION **********************************************************/ +/* START FUNCTION DESCRIPTION ******************************************** +_sdspi_read_sector + +SYNTAX: int _sdspi_read_sector(sd_device *sd, unsigned long sector_number, + void * data_buffer, long xbuffer) + +DESCRIPTION: This function is called to execute protocol command 17 to + read a 512 byte block of data from the SD card. + + Pass NULL and 0 for the last two parameters to drop the data. + +PARAMETER1: sd The device structure for the SD card. +PARAMETER2: sector_number The sector number to read. +PARAMETER3: data_buffer Pointer to a buffer for the 512 bytes read, or + NULL to read into xbuffer. +PARAMETER4: xbuffer Pointer to an xmem buffer for the 512 bytes read + +RETURN VALUE: 0 Success -EIO I/O Error -EINVAL Invalid parameter given -ENOMEDIUM No SD card in socket @@ -1989,35 +1954,30 @@ RETURN VALUE: 0 Success END DESCRIPTION **********************************************************/ _sdflash_nodebug -int sdspi_read_sector(sd_device *sd, unsigned long sector_number, - void * data_buffer) +int _sdspi_read_sector(sd_device *sd, unsigned long sector_number, + void * data_buffer, long xbuffer) { - int result, j, k; - char * read_data_ptr; - unsigned short crc16; + int result; SD_CMD_REPLY cmd_reply; - result = 0; - read_data_ptr = NULL; - crc16 = 0; - - WrPortI(GOCR, &GOCRShadow, GOCRShadow | 3); // PATCH FOR GOCR bug in 9.52 -// SD_DISABLECS(sd->SDintf); - - memset(&cmd_reply, 0, sizeof(SD_CMD_REPLY)); + SD_DISABLECS(sd->SDintf); - cmd_reply.cmd = CMD17; - cmd_reply.argument = sector_number * BLOCK_SIZE; - cmd_reply.reply_size = CMD_R1_BUFFER_SIZE; + sdspi_init_reply(&cmd_reply, CMD17); +#if SDFLASH_SDHC + if (SD_IS_SDHC(sd)) { + cmd_reply.argument = sector_number; + } else +#endif + { + cmd_reply.argument = sector_number * BLOCK_SIZE; + } cmd_reply.data_size = DATA_BLOCK_SIZE; - cmd_reply.tx_buffer = tx_buffer; - cmd_reply.rx_buffer = rx_buffer; if (result = sdspi_process_command(sd, &cmd_reply, 1)) { #ifdef SDFLASH_VERBOSE - printf("sdspi_read_sector: sdspi_process_command() failed, error %d\n", - result); + printf("%s: %s() failed, error %d\n", + "sdspi_read_sector", "sdspi_process_command", result); #endif return result; } @@ -2026,60 +1986,28 @@ int sdspi_read_sector(sd_device *sd, unsigned long sector_number, if (cmd_reply.reply) { #ifdef SDFLASH_VERBOSE - printf("sdspi_read_sector: command response error, reply=%02x\n", - cmd_reply.reply); + printf("%s: command response error, reply=%02x\n", + "sdspi_read_sector", cmd_reply.reply); #endif return -EIO; } } - if (cmd_reply.rx_buffer[cmd_reply.reply_size] != READ_WRITE_START_BLOCK) - { // Automatic retry on bad start block reception - if (result = sdspi_process_command(sd, &cmd_reply, 1)) - { // If it happens again, report it as an error -#ifdef SDFLASH_VERBOSE - printf("sdspi_read_sector: command failed retry, error %d\n", - result); -#endif - return result; - } - else - { - if (cmd_reply.rx_buffer[cmd_reply.reply_size] != READ_WRITE_START_BLOCK) - { -#ifdef SDFLASH_VERBOSE - printf("sdspi_read_sector: Expected start block, received %x\n", - cmd_reply.rx_buffer[cmd_reply.reply_size]); -#endif - return -EIO; - } - } + if (data_buffer) { + memcpy(data_buffer, &cmd_reply.data_buffer[1], BLOCK_SIZE); + } else if (xbuffer) { + root2xmem(xbuffer, &cmd_reply.data_buffer[1], BLOCK_SIZE); } - - read_data_ptr = &cmd_reply.rx_buffer[cmd_reply.reply_size + 1]; - - /* Get the CRC for CSD block and 2 byte CRC */ - for (k = 0; k < DATA_BLOCK_SIZE - 1; k++) - crc16 = (crc16 << 8) ^ crc_table[(crc16 >> 8) ^ read_data_ptr[k]]; - - /* Using the 2 CRC bytes in the CRC calculation results in 0 */ - if (crc16) - { -#ifdef SDFLASH_VERBOSE - printf("sdspi_read_sector: CRC mismatch error\n"); -#endif - return -EIO; - } - - memcpy(data_buffer, read_data_ptr, BLOCK_SIZE); - - return result; + + return 0; } -/*** Beginheader sdspi_write_sector ***/ -int sdspi_write_sector(sd_device *sd, unsigned long sector_number, - char * data_buffer); + +/*** Beginheader _sdspi_write_sector ***/ +#define sdspi_write_sector(sd, n, buffer) _sdspi_write_sector(sd, n, buffer, 0) +int _sdspi_write_sector(sd_device *sd, unsigned long sector_number, + char * data_buffer, long xbuffer); /*** endheader ***/ /* START FUNCTION DESCRIPTION ******************************************** @@ -2091,11 +2019,37 @@ SYNTAX: int sdspi_write_sector(sd_device *sd, unsigned long sector_number, DESCRIPTION: This function is called to execute protocol command 24 to write a 512 byte block of data to the SD card. -PARAMETER1: sd The device structure for the SD card. +PARAMETER1: sd The device structure for the SD card. +PARAMETER2: sector_number The sector number to write. +PARAMETER3: data_buffer Pointer to a buffer of 512 bytes to write. + +RETURN VALUE: 0 Success + -EIO I/O Error + -EACCES Write protected block, no write access + -EINVAL Invalid parameter given + -ENOMEDIUM No SD card in socket + -ESHAREDBUSY Shared SPI port busy + -EBUSY SD card is busy with write operation, + call sdspi_WriteContinue to complete + (Only when SD_NON_BLOCK is defined) + +END DESCRIPTION **********************************************************/ +/* START FUNCTION DESCRIPTION ******************************************** +_sdspi_write_sector + +SYNTAX: int _sdspi_write_sector(sd_device *sd, unsigned long sector_number, + char * data_buffer, long xbuffer) + +DESCRIPTION: This function is called to execute protocol command 24 to + write a 512 byte block of data to the SD card. + +PARAMETER1: sd The device structure for the SD card. PARAMETER2: sector_number The sector number to write. -PARAMETER3: data_buffer Pointer to a buffer of 512 bytes to write. +PARAMETER3: data_buffer Pointer to a buffer of 512 bytes to write, or NULL + to use xbuffer instead. +PARAMETER4: xbuffer Pointer to an xmem buffer of 512 bytes to write. -RETURN VALUE: 0 Success +RETURN VALUE: 0 Success -EIO I/O Error -EACCES Write protected block, no write access -EINVAL Invalid parameter given @@ -2108,8 +2062,8 @@ RETURN VALUE: 0 Success END DESCRIPTION **********************************************************/ _sdflash_nodebug -int sdspi_write_sector(sd_device *sd, unsigned long sector_number, - char * data_buffer) +int _sdspi_write_sector(sd_device *sd, unsigned long sector_number, + char * data_buffer, long xbuffer) { int result, j, k, status; char * read_data_ptr; @@ -2121,19 +2075,20 @@ int sdspi_write_sector(sd_device *sd, unsigned long sector_number, result = 0; read_data_ptr = NULL; - memset(&cmd_reply, 0, sizeof(SD_CMD_REPLY)); - - cmd_reply.cmd = CMD24; - cmd_reply.argument = sector_number * BLOCK_SIZE; - cmd_reply.reply_size = CMD_R1_BUFFER_SIZE; - cmd_reply.data_size = 0; - cmd_reply.tx_buffer = tx_buffer; - cmd_reply.rx_buffer = rx_buffer; + sdspi_init_reply(&cmd_reply, CMD24); +#if SDFLASH_SDHC + if (SD_IS_SDHC(sd)) { + cmd_reply.argument = sector_number; + } else +#endif + { + cmd_reply.argument = sector_number * BLOCK_SIZE; + } if (result = sdspi_process_command(sd, &cmd_reply,0)) { #ifdef SDFLASH_VERBOSE - printf("sdspi_write_sector: process command failed.\n"); + printf("%s: process command failed.\n", "sdspi_write_sector"); #endif _sdspi_end_command(sd); _SPIfreeSemaphore(SPI_SD); @@ -2144,8 +2099,8 @@ int sdspi_write_sector(sd_device *sd, unsigned long sector_number, if (cmd_reply.reply) { #ifdef SDFLASH_VERBOSE - printf("sdspi_write_sector: command response error (%d).\n", - cmd_reply.reply); + printf("%s: command response error (%d).\n", + "sdspi_write_sector", cmd_reply.reply); #endif _sdspi_end_command(sd); _SPIfreeSemaphore(SPI_SD); @@ -2153,39 +2108,41 @@ int sdspi_write_sector(sd_device *sd, unsigned long sector_number, } } - tx_buffer[0] = 0xFE; // Write start data token - crc16 = 0; - // Create CRC while copying data_buffer to tx_buffer - for(j=1; j<513; j++){ - tx_buffer[j] = data_buffer[j-1]; - crc16 = (crc16 << 8) ^ crc_table[(crc16 >> 8) ^ tx_buffer[j]]; + // re-use rx_buffer for our write block + rx_buffer[0] = READ_WRITE_START_BLOCK; + + // Copy data_buffer to rx_buffer and calculate crc + if (data_buffer) { + memcpy(&rx_buffer[1], data_buffer, 512); + } else { + xmem2root(&rx_buffer[1], xbuffer, 512); } - // Last bit of CRC must be set or we get CRC error back from the card - tx_buffer[514] = (char)crc16 | 1 ; - tx_buffer[513] = (char)(crc16>>8); + crc16 = crc16_calc(&rx_buffer[1], 512, 0); - sdspi_bitrev(tx_buffer, 515); + // Last bit of CRC must be set or we get CRC error back from the card + rx_buffer[514] = (char)crc16 | 1 ; // LSB | 0x01 + rx_buffer[513] = (char)(crc16>>8); // MSB - _sdspi_write_block(tx_buffer, 515, sd->port); - result = _sdspi_read_block(rx_buffer, 1, sd->port, REPLY_TIMEOUT); + _sdspi_write_block(rx_buffer, 515, sd->port); + result = _sdspi_read_block(rx_buffer, 1, sd->port, sd->write_timeout_ms); if (result == 1) { - rx_buffer[0] |= 7; // Set don't care bits high for comparing - if(rx_buffer[0]==0xD7) { + rx_buffer[0] |= 0xE0; // Set don't care bits high for comparing + if(rx_buffer[0]==0xEB) { #ifdef SDFLASH_VERBOSE - printf("sdspi_write_sector: CRC mismatch error.\n"); + printf("%s: CRC mismatch error.\n", "sdspi_write_sector"); #endif result = -EIO; } - else if(rx_buffer[0]==0xB7) { + else if(rx_buffer[0]==0xED) { #ifdef SDFLASH_VERBOSE - printf("sdspi_write_sector: Write data error.\n"); + printf("%s: Write data error.\n", "sdspi_write_sector"); #endif result = -EIO; } - else if(rx_buffer[0]!=0xA7) { + else if(rx_buffer[0]!=0xE5) { #ifdef SDFLASH_VERBOSE - printf("sdspi_write_sector: Invalid command response error.\n"); + printf("%s: Invalid command response error.\n", "sdspi_write_sector"); #endif result = -EIO; } @@ -2212,7 +2169,7 @@ int sdspi_write_sector(sd_device *sd, unsigned long sector_number, if(!count) { #ifdef SDFLASH_VERBOSE - printf("sdspi_write_sector: Busy response timeout.\n"); + printf("%s: Busy response timeout.\n", "sdspi_write_sector"); #endif result = -EIO; } @@ -2221,15 +2178,15 @@ int sdspi_write_sector(sd_device *sd, unsigned long sector_number, if (!result && status) { if (status & 0x0023) { #ifdef SDFLASH_VERBOSE - printf("sdspi_write_sector(%ld): Write protected, access denied.\n", - sector_number); + printf("%s(%ld): Write protected, access denied.\n", + "sdspi_write_sector", sector_number); #endif result = -EACCES; } else { #ifdef SDFLASH_VERBOSE - printf("sdspi_write_sector: Write operation failed (%04x).\n", - status); + printf("%s: Write operation failed (0x%04x).\n", + "sdspi_write_sector", status); #endif result = -EIO; } @@ -2278,23 +2235,19 @@ int sdspi_WriteContinue(sd_device *sd) if (sdspi_notbusy(sd->port)) { SD_DISABLECS(sd->SDintf); SD_ENABLECS(sd->SDintf); - WrPortI(GOCR, &GOCRShadow, GOCRShadow | 3); // PATCH FOR GOCR bug in 9.52 - BitWrPortI(GOCR, &GOCRShadow, 0,0); // PATCH FOR GOCR bug in 9.52 -// SD_DISABLECS(sd->SDintf); -// SD_ENABLECS(sd->SDintf); - _sdspi_end_command(sd); + _sdspi_end_command(sd); sd->write_state = 0; - _SPIfreeSemaphore(SPI_SD); + _SPIfreeSemaphore(SPI_SD); // Check status response from SD card result = sdspi_get_status_reg(sd, &status); if (!result && status) { #ifdef SDFLASH_VERBOSE - printf("sdspi_writeContinue: Write operation failed (%04x).\n", - status); + printf("%s: Write operation failed (0x%04x).\n", + "sdspi_WriteContinue", status); #endif result = -EIO; - } + } } else { // SD card still busy, increment write_state as timeout if (++sd->write_state > BUSY_RETRIES) { @@ -2302,7 +2255,7 @@ int sdspi_WriteContinue(sd_device *sd) sd->write_state = 0; _SPIfreeSemaphore(SPI_SD); #ifdef SDFLASH_VERBOSE - printf("sdspi_writeContinue: Write busy timeout.\n"); + printf("%s: Write busy timeout.\n", "sdspi_WriteContinue"); #endif result = -EIO; } @@ -2311,7 +2264,7 @@ int sdspi_WriteContinue(sd_device *sd) } } - return result; + return result; } /*** Beginheader sdspi_set_block_length ***/ @@ -2335,7 +2288,7 @@ DESCRIPTION: This function executes protocol command 16 to set the block PARAMETER1: sd The device structure for the SD card. PARAMETER2: block_length The block size in bytes for the SD card. -RETURN VALUE: 0 Success +RETURN VALUE: 0 Success -EIO I/O Error -EINVAL Invalid parameter given -ENOMEDIUM No SD card in socket @@ -2350,17 +2303,12 @@ int sdspi_set_block_length(sd_device *sd, int block_length) SD_CMD_REPLY cmd_reply; result = 0; - memset(&cmd_reply, 0, sizeof(cmd_reply)); - cmd_reply.cmd = CMD16; + sdspi_init_reply(&cmd_reply, CMD16); cmd_reply.argument = (long)block_length; - cmd_reply.reply_size = CMD_R1_BUFFER_SIZE; - cmd_reply.data_size = 0; - cmd_reply.tx_buffer = tx_buffer; - cmd_reply.rx_buffer = rx_buffer; #ifdef SDFLASH_VERBOSE - printf("sdspi_set_block_length: calling sdspi_process_command\n"); + printf("%s: calling %s\n", "sdspi_set_block_length", "sdspi_process_command"); #endif if (result = sdspi_process_command(sd, &cmd_reply, 1)) { @@ -2371,7 +2319,7 @@ int sdspi_set_block_length(sd_device *sd, int block_length) if (cmd_reply.reply) { #ifdef SDFLASH_VERBOSE - printf("sdspi_set_block_length: command response error (%d)\n", + printf("%s: command response error (%d)\n", "sdspi_set_block_length", cmd_reply.reply); #endif result = -EIO; @@ -2394,10 +2342,10 @@ DESCRIPTION: This function waits for and debounces the card insertion switch. When it returns True(1), then a card is fully inserted. -PARAMETER1: sd The device structure for the SD card. +PARAMETER1: sd The device structure for the SD card. -RETURN VALUE: 1 Success, Card Fully Inserted - 0 No Card Present +RETURN VALUE: 1 Success, Card Fully Inserted + 0 No Card Present END DESCRIPTION **********************************************************/ _sdflash_nodebug @@ -2494,54 +2442,6 @@ BZret: ret #endasm -/*** Beginheader _sdspi_ReadWrite ***/ -root int _sdspi_ReadWrite(sd_device *sd, char *tx_buffer, char *rx_buffer, - unsigned int reply_size, unsigned int data_size, int disable); -/*** endheader ***/ - -/************************************************************************* -SYNTAX: int _sdspi_ReadWrite(sd_device *sd, char *tx_buffer, - char *rx_buffer, unsigned int reply_size, - unsigned int data_size, int disable) - -DESCRIPTION: Performs an end of command sequence - raising the chip - select and clocking out a high line character. This - finishes the command and puts the SD out in hi-Z mode. - You must obtain the SPI semaphore before calling this - function as it raises and lowers the SD card chip select. - It will end the command and release the SPI semaphore if - disable is passed as true. - -PARAMETER1: sd - Pointer to an SD device structure -PARAMETER2: len - number of bytes to transmit ( maximum 64K) -PARAMETER3: port - Base address of the SPI serial port to use - -RETURN VALUE: 0 Success - -EIO Timeout Occured in Command Response -**************************************************************************/ -_sdflash_nodebug -root int _sdspi_ReadWrite(sd_device *sd, char *tx_buffer, char *rx_buffer, - unsigned int reply_size, unsigned int data_size, int disable) -{ - int rc; - - BitWrPortI(GOCR, &GOCRShadow, 1,1); // PATCH FOR GOCR bug in 9.52 - BitWrPortI(GOCR, &GOCRShadow, 0,0); // PATCH FOR GOCR bug in 9.52 -// SD_ENABLECS(sd->SDintf); - tx_buffer[6]=0xff; //extra character needed to keep clk on - _sdspi_write_block(tx_buffer, 7, sd->port); - rc = _sdspi_read_block(rx_buffer, reply_size, sd->port, REPLY_TIMEOUT); - if (data_size) { - rc = _sdspi_read_block(rx_buffer + reply_size, data_size, sd->port, - sd->data_timeout); - } - if(disable) { - _sdspi_end_command(sd); - _SPIfreeSemaphore(SPI_SD); - } - return (rc < 0 ? rc : 0); -} - /*** Beginheader _sdspi_end_command ***/ void _sdspi_end_command(sd_device *sd); @@ -2562,10 +2462,8 @@ PARAMETER3: port - Base address of the SPI serial port to use _sdflash_nodebug void _sdspi_end_command(sd_device *sd) { - WrPortI(GOCR, &GOCRShadow, GOCRShadow | 3); // PATCH FOR GOCR bug in 9.52 -// SD_DISABLECS(sd->SDintf); - tx_buffer[0] = 0xFF; - _sdspi_write_block(tx_buffer, 1, sd->port); + SD_DISABLECS(sd->SDintf); + _sdspi_write_block("\xFF", 1, sd->port); } @@ -2595,6 +2493,7 @@ void _sdspi_write_block(char *buffer, unsigned int len, int port) #asm ; set up the registers ex de,hl ; save src in de + ld de', BitRevTable ; use de' to reverse bytes when written ld hl, (sp+@SP+len) ; get the number of bytes ld c,L ld b,H @@ -2605,6 +2504,13 @@ void _sdspi_write_block(char *buffer, unsigned int len, int port) _SPIWriteA0: ld a, (de) ; get a byte + ; reverse bit order before sending a = BitRevTable[a] + exx + bool hl + ld L, a + add hl, de + ld a, (hl) + exx ioi ld (iy), a ; load it ld a, SD_SPI_CONTROL_VALUE | SD_SPI_TXMASK @@ -2626,14 +2532,14 @@ ioi bit 2,(iy + SD_SR_OFFSET) ; test trans bit /*** Beginheader _sdspi_read_block ***/ root int _sdspi_read_block(char *buffer, unsigned int len, int port, - unsigned int timeout); + unsigned int timeout_ms); /*** endheader ***/ /************************************************************************* _sdspi_read_block SYNTAX: int _sdspi_read_block(char *buffer, unsigned int len, int port, - unsigned int timeout) + unsigned int timeout_ms) DESCRIPTION: Reads in len bytes of data (ignoring high line sequence) from the SPI port into a buffer. Timeout is based on the @@ -2645,7 +2551,7 @@ DESCRIPTION: Reads in len bytes of data (ignoring high line sequence) PARAMETER1: buffer - buffer for reply and received bytes PARAMETER2: len - number of bytes to receive (after high line condition) PARAMETER3: port - Base address of the SPI serial port to use -PARAMETER4: timeout - number of high line bytes allowed before timeout +PARAMETER4: timeout - number of milliseconds before timeout RETURN VALUE: number of bytes received (if positive) -EIO = Response Timeout occured @@ -2653,18 +2559,21 @@ RETURN VALUE: number of bytes received (if positive) **************************************************************************/ _sdflash_nodebug root int _sdspi_read_block(char *buffer, unsigned int len, int port, - unsigned int timeout) + unsigned int timeout_ms) { #asm ; set up the registers - ex de,hl ; save dest in de - ld hl, (sp+@SP+timeout) ; get timeout count + ex de, hl ; save dest in de + ld hl, (sp+@SP+timeout_ms) ; get timeout count + ld bc, (MS_TIMER) ; ...add it to low half of MS_TIMER + scf ; set carry flag for additional 1ms + adc hl, bc ld c,L - ld b,H + ld b,H ; BC = timeout 16-bit MS_TIMER value ld iy, (sp+@SP+port) ; receive the reply/data bytes ; de = destination address -; bc = timeout counter +; bc = timeout value ; iy = serial port register base (SxDR) ; High line condition loop @@ -2682,15 +2591,19 @@ _Rx0Wait: cp 0xFF ; Compare to high line condition jr nz, _RxGetData ; If not, then go get reply/data - dec bc ; Decrement timeout counter - ld a,b - or c ; check if expired: z=0 if expired + ; if (MS_TIMER - target >= 0), timeout occurred + ld hl, (MS_TIMER) + xor a ; clear carry + sbc hl, bc ; calculate MS_TIMER - target + bit 7, h ; if result is non-negative we timed out jr nz,_Rx0Loop ; Loop back if not expired + ld a, 0xFF ; Timeout occurred ld (de), a ; Save FF byte to indicate timeout jr _Rx0Exit ; And exit _RxGetData: + ld de', BitRevTable ; use de' to reverse bytes as read ld hl, (sp+@SP+len) ; get the number of bytes to receive ld c,L ld b,H ; Replace timeout count with byte count @@ -2709,6 +2622,13 @@ _Rx1Wait: ioi ld a, (iy) ; get the byte _RxSaveByte: + ; reverse bit order before storing (de) = BitRevTable[a] + exx + bool hl + ld L, a + add hl, de + ld a, (hl) + exx ld (de), a ; store the byte inc de ; point to next byte dec bc ; decrement bytes remaining to receive @@ -2717,27 +2637,11 @@ _RxSaveByte: jr nz, _Rx1Loop ; jump if not done _Rx0Exit: #endasm - return (*buffer == 0xFF ? -EIO : len); + return *buffer == 0xFF ? -EIO : len; } /*** BeginHeader */ -#endif +#endif // __SDFLASH_LIB__ /*** EndHeader */ - - - - - - - - - - - - - - - - diff --git a/Lib/SDflash/SD_FAT.LIB b/Lib/SDflash/SD_FAT.LIB index 654b2fe..dbc7246 100644 --- a/Lib/SDflash/SD_FAT.LIB +++ b/Lib/SDflash/SD_FAT.LIB @@ -27,9 +27,6 @@ The only function that will need to be called directly is sd_InitDriver() #define SD_NON_BLOCK #endif -#if (RCM4300_SERIES) - #use "RCM43xx.lib" // Needed for SPI port sharing routines -#endif #use "sdflash.lib" #use "part_defs.lib" @@ -233,12 +230,9 @@ END DESCRIPTION **********************************************************/ /*** BeginHeader sd_InitDriver */ int sd_InitDriver(mbr_drvr *driver, void *device_list); -extern char scratch[512]; /*** EndHeader */ -char scratch[512]; - _sdfat_debug int sd_InitDriver(mbr_drvr *driver, void *device_list) { @@ -260,7 +254,7 @@ int sd_InitDriver(mbr_drvr *driver, void *device_list) driver->maxdev = 1; driver->dlist = NULL; driver->next = NULL; - driver->type[0] = 0x80; + driver->type[0] = MBRTYPE_FLASH; if(device_list == NULL) { rc = sdspi_initDevice(0, &SD_dev0); //use compile-time default device @@ -347,17 +341,10 @@ int sd_ReadSector(unsigned long sector, } // Auto retry read calls once if an I/O error is received - if(buffer){ - if ((rc = sdspi_read_sector(dev, sector, buffer)) == -EIO) { - rc = sdspi_read_sector(dev, sector, buffer); - } - } - else if(xbuffer){ - if ((rc = sdspi_read_sector(dev, sector, scratch)) == -EIO) { - rc = sdspi_read_sector(dev, sector, scratch); - } - root2xmem(xbuffer, scratch, 512); + if ((rc = _sdspi_read_sector(dev, sector, buffer, xbuffer)) == -EIO) { + rc = _sdspi_read_sector(dev, sector, buffer, xbuffer); } + #ifdef SDFLASH_VERBOSE printf("Read Sector %08lx\n", sector); #endif @@ -433,20 +420,12 @@ int sd_WriteSector( unsigned long sector, } else { // Otherwise, start new write to SD card #endif - rc = 0; - dev->write_sector = sector; dev->write_state = 1; - if(xbuffer){ - xmem2root(scratch, xbuffer, 512); - dev->bptr = scratch; - } - else - dev->bptr = buffer; #ifdef SDFLASH_VERBOSE printf("Write sector %08lx\n", sector); #endif - rc = sdspi_write_sector(dev, dev->write_sector, dev->bptr); + rc = _sdspi_write_sector(dev, sector, buffer, xbuffer); #ifdef SD_NON_BLOCK } if (rc == -EBUSY) return -EBUSY; diff --git a/Samples/FileSystem/FAT/FAT_SHELL.C b/Samples/FileSystem/FAT/FAT_SHELL.C index 498eaf4..c7049a4 100644 --- a/Samples/FileSystem/FAT/FAT_SHELL.C +++ b/Samples/FileSystem/FAT/FAT_SHELL.C @@ -109,33 +109,66 @@ void pdump() int i; FATfile * f; - printf("sec_clust = %u\n", fat_part_mounted[active_part]->sec_clust); - printf("fat_cnt = %u\n", fat_part_mounted[active_part]->fat_cnt); - printf("fat_len = %u\n", fat_part_mounted[active_part]->fat_len); - printf("root_cnt = %u\n", fat_part_mounted[active_part]->root_cnt); - printf("res_sec = %u\n", fat_part_mounted[active_part]->res_sec); - printf("byte_sec = %u\n", fat_part_mounted[active_part]->byte_sec); - printf("sec_fat = %lu\n", fat_part_mounted[active_part]->sec_fat); - printf("serialnumber = %lu\n", fat_part_mounted[active_part]->serialnumber); - printf("totcluster = %lu\n", fat_part_mounted[active_part]->totcluster); - printf("badcluster = %lu\n", fat_part_mounted[active_part]->badcluster); - printf("freecluster = %lu\n", fat_part_mounted[active_part]->freecluster); - printf("nextcluster = %lu\n\n", fat_part_mounted[active_part]->nextcluster); - printf("fatstart = %lu\n", fat_part_mounted[active_part]->fatstart); - printf("rootstart = %lu\n", fat_part_mounted[active_part]->rootstart); - printf("datastart = %lu\n", fat_part_mounted[active_part]->datastart); - printf("clustlen = %lu\n", fat_part_mounted[active_part]->clustlen); - printf("type = %d\n", fat_part_mounted[active_part]->type); - printf("wtc_prt = %d\n", fat_part_mounted[active_part]->wtc_prt); - printf("pnum = %d\n\n", fat_part_mounted[active_part]->pnum); -// printf("opstate = %d\n", fat_part_mounted[active_part]->opstate); -// printf("clust1 = %u\n", fat_part_mounted[active_part]->clust1); -// printf("clust2 = %u\n", fat_part_mounted[active_part]->clust2); -// printf("linkclust = %u\n", fat_part_mounted[active_part]->linkclust); + printf("partition number %d, type %d\n", + fat_part_mounted[active_part]->pnum, + fat_part_mounted[active_part]->type); + printf("serialnumber = %lu (0x%08lx)\n", + fat_part_mounted[active_part]->serialnumber, + fat_part_mounted[active_part]->serialnumber); + printf("journal number (wtc_prt) = %d\n", + fat_part_mounted[active_part]->wtc_prt); + + printf("\n"); + + printf("%10u FATs (fat_cnt)\n", + fat_part_mounted[active_part]->fat_cnt); + printf("%10lu bytes in a FAT (fat_len * 2)\n", + 2L * fat_part_mounted[active_part]->fat_len); + printf("%10lu sectors per FAT (sec_fat)\n", + fat_part_mounted[active_part]->sec_fat); + printf("%10u entries in root directory (root_cnt)\n", + fat_part_mounted[active_part]->root_cnt); + printf("%10u reserved sectors (res_sect)\n", + fat_part_mounted[active_part]->res_sec); + + printf("\n"); + + printf("%10u sectors per cluster (sec_clust)\n", + fat_part_mounted[active_part]->sec_clust); + printf("%10u bytes per sector (byte_sec)\n", + fat_part_mounted[active_part]->byte_sec); + printf("%10lu bytes per cluster (clustlen)\n", + fat_part_mounted[active_part]->clustlen); + + printf("%10lu total clusters (totcluster) (%.3fMB)\n", + fat_part_mounted[active_part]->totcluster, + (float) fat_part_mounted[active_part]->totcluster + * fat_part_mounted[active_part]->clustlen / (1024L * 1024)); + + printf("%10lu bad clusters (badcluster) (%.3fKB)\n", + fat_part_mounted[active_part]->badcluster, + (float) fat_part_mounted[active_part]->badcluster + * fat_part_mounted[active_part]->clustlen / 1024); + + printf("%10lu free clusters (freecluster) (%.3fMB)\n", + fat_part_mounted[active_part]->freecluster, + (float) fat_part_mounted[active_part]->freecluster + * fat_part_mounted[active_part]->clustlen / (1024L * 1024)); + + printf("%10lu is next cluster (nextcluster)\n\n", + fat_part_mounted[active_part]->nextcluster); + + printf("%10lu is first sector of first FAT (fatstart)\n", + fat_part_mounted[active_part]->fatstart); + printf("%10lu is first sector of root dir (rootstart)\n", + fat_part_mounted[active_part]->rootstart); + printf("%10lu is first sector of data area (datastart)\n", + fat_part_mounted[active_part]->datastart); + for (f = fat_part_mounted[active_part]->first, i = 0; f; f = f->next, ++i); - printf("open files = %d\n", i); + printf("%10d open files\n", i); - printf("\nmpart.bootflag = %02X\n", + printf("\nmpart.bootflag = 0x%02X\n", fat_part_mounted[active_part]->mpart->bootflag); printf("mpart.starthead = %u\n", fat_part_mounted[active_part]->mpart->starthead); @@ -687,6 +720,8 @@ int main() strcpy(pwd[i], ""); } + printf("Calling fat_AutoMount()...\n"); + // Auto-mount the FAT filesystem rc = fat_AutoMount(FDDF_USE_DEFAULT); if (rc == -EIO || rc == -ENOMEDIUM) { diff --git a/Samples/FileSystem/FAT/FAT_WRITE_MBR.C b/Samples/FileSystem/FAT/FAT_WRITE_MBR.C index eeecde3..8dfe626 100644 --- a/Samples/FileSystem/FAT/FAT_WRITE_MBR.C +++ b/Samples/FileSystem/FAT/FAT_WRITE_MBR.C @@ -16,8 +16,6 @@ /***************************************************************************** Samples\FileSystem\FAT\fat_write_mbr.c - Requires the FAT file system module to be installed. - Requires that you run this on a core module with a FAT compatible flash memory device. This sample works with the primary device defined by MBR_DRIVER_INIT as the default. If you need to work @@ -148,6 +146,11 @@ if (rc == -ENOMEDIUM) { if (megs > 0.01) { partsize = (unsigned long) (megs * 2048.0); if (partsize > sectors) partsize = sectors; + if (partsize > FAT16_MAX_PARTSECSIZE) { + partsize = FAT16_MAX_PARTSECSIZE; + printf("Partition %d limited to FAT16 maximum of %6.1fMB\n", + i + 1, (float)partsize / 2048.0); + } my_device.part[i].starthead = 254; my_device.part[i].parttype = 6; my_device.part[i].endhead = 254; diff --git a/Samples/FileSystem/FAT/Fmt_Device.C b/Samples/FileSystem/FAT/Fmt_Device.C index 9c43262..8193cf0 100644 --- a/Samples/FileSystem/FAT/Fmt_Device.C +++ b/Samples/FileSystem/FAT/Fmt_Device.C @@ -18,9 +18,7 @@ Formats the configured device(s) for use with the FAT file system. - Requires the FAT filesystem module be installed. - - Also requires that you run this on a board with a compatible + Requires that you run this on a board with a compatible storage medium (serial flash, NAND flash or SD card). IMPORTANT!!!! Please use with caution. @@ -371,6 +369,8 @@ void main(void) fat_print_config(); #endif + printf("Calling fat_AutoMount()...\n"); + rc = fat_AutoMount(FDDF_MOUNT_DEV_ALL | FDDF_MOUNT_PART_ALL); if (rc) { printf("\nfat_AutoMount() error (%d) %ls.\n", rc, error_message(rc)); diff --git a/Samples/RCM3900/SD_Flash/sdflash_info.c b/Samples/RCM3900/SD_Flash/sdflash_info.c new file mode 100644 index 0000000..b6716d5 --- /dev/null +++ b/Samples/RCM3900/SD_Flash/sdflash_info.c @@ -0,0 +1,105 @@ +/* + Copyright (c) 2017, Digi International Inc. + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +/***************************************************************************** +sdflash_info.c + +This program dumps information about the SD card, including size information +and data parsed from the CSD (Card-Specific Data), SCR (SD Configuration +Register) and CID (Card Identification). + +*****************************************************************************/ + + +#define SDFLASH_DEBUG +//#define SDFLASH_VERBOSE + +#use "sdflash.lib" + +#define dump_CSD_char(x) printf("CSD." #x ": 0x%02X %u\n", sd->CSD. ## x, sd->CSD. ## x) +#define dump_CSD_int(x) printf("CSD." #x ": 0x%04X %u\n", sd->CSD. ## x, sd->CSD. ## x) +#define dump_SCR(x) printf("SCR." #x ": 0x%02X\n", sd->SCR. ## x) + +void print_sd_device(const sd_device *sd) +{ + printf("sectors: %lu (%lu MB, %lu MiB)\n", sd->sectors, + sd->sectors * 8 / 15625, // (512 / 1,000,000 reduces to 8/15,625) + sd->sectors / (1024 * 1024 / 512) ); + printf("pagesize: %u\n", sd->pagesize); + printf("pagebitshift: %d (%lu)\n", sd->pagebitshift, 1UL << sd->pagebitshift); + switch (sd->CSD.CSD_STR) + { + case SD_CSD_STR_V1: + printf("CSD Version 1.0\n"); + break; + case SD_CSD_STR_V2: + printf("CSD Version 2.0\n"); + break; + default: + printf("invalid CSD version %u\n", sd->CSD.CSD_STR); + } + dump_CSD_char(init_ok); + dump_CSD_char(CSD_STR); + dump_CSD_char(TAAC); + dump_CSD_char(NSAC); + dump_CSD_char(TRANSPEED); + dump_CSD_int( CCC); + dump_CSD_char(R_BL_LEN); + dump_CSD_char(DSR_IMP); + dump_CSD_int( CSIZE); + + if (sd->CSD.CSD_STR == SD_CSD_STR_V1) { + dump_CSD_char(C_SIZE_M); + } + + dump_CSD_char(ERASE_BLK_EN); + dump_CSD_char(DEF_ECC); + dump_CSD_char(R2W_FACT); + dump_CSD_char(WR_BL_LEN); + dump_CSD_char(WR_BL_PAR); + dump_CSD_char(COPY); + dump_CSD_char(P_WR_PROT); + dump_CSD_char(T_WR_PROT); + dump_CSD_char(CRC7); + + dump_SCR(init_ok); + dump_SCR(SCR_STRUCTURE); + dump_SCR(SD_SPEC); + dump_SCR(DATA_STAT_AFTER_ERASE); + dump_SCR(SD_SECURITY); + dump_SCR(SD_BUS_WIDTHS); +} + +int main() +{ + int rc; + sd_device *dev; + SD_CID_TYPE cid; + + printf("SD Info on %s at %s.\n", __DATE__, __TIME__); + dev = &SD[0]; + if (rc = sdspi_initDevice(0, &SD_dev0)) + { + printf("Flash init failed (%d)\n\n", rc); + exit(rc); + } + + print_sd_device(dev); + + if (sdspi_get_cid(dev, &cid) == 0) { + sdspi_print_cid(&cid); + } +} +