#if defined(CSR_SPISDCARD_BASE) || defined(CSR_SDCORE_BASE)
+#if defined(CSR_SPISDCARD_BASE)
+#define read_block spisdcard_read_block
+#endif
+
+#if defined(CSR_SDCORE_BASE)
+#define read_block sdcard_read_block
+#endif
+
// FAT16 Specific code starts here
// Details from https://codeandlife.com/2012/04/02/simple-fat-and-sd-tutorial-part-1/
// Return 0 success, 1 failure
//
// Details from https://codeandlife.com/2012/04/02/simple-fat-and-sd-tutorial-part-1/
-uint8_t sdcard_readMBR(void)
+uint8_t fat16_read_mbr(void)
{
int i, n;
// Read Sector 0x00000000
printf("Reading MBR\n");
- if( readSector(0x00000000, sdCardSector)==SUCCESS ) {
+ if( read_block(0x00000000, sdCardSector)==SUCCESS ) {
// Copy Partition 1 Entry from byte 0x1be
// FIXME should check 0x55 0xaa at end of sector
memcpy(&sdCardPartition, &sdCardSector[0x1be], sizeof(PartitionTable));
// Read Parition 1 Boot Sector - Found from Partion Table
printf("\nRead FAT16 Boot Sector\n");
- if( readSector(sdCardPartition.start_sector, sdCardSector)==SUCCESS ) {
+ if( read_block(sdCardPartition.start_sector, sdCardSector)==SUCCESS ) {
memcpy(&sdCardFatBootSector, &sdCardSector, sizeof(Fat16BootSector));
}
else {
return FAILURE;
}
-#ifdef USE_SPISCARD_RECLOCKING
- // Reclock the card
- // Calculate 16MHz as an integer divider from the CONFIG_CLOCK_FREQUENCY
- // Add 1 as will be rounded down
- // Always ensure divider is at least 2 - half the processor speed
- int divider;
- divider = (int)(CONFIG_CLOCK_FREQUENCY/(16e6)) + 1;
- if( divider<2 )
- divider=2;
- printf("Reclocking from %dKHz to %dKHz\n\n", CONFIG_CLOCK_FREQUENCY/(int)spisdcard_clk_divider_read()/1000, CONFIG_CLOCK_FREQUENCY/divider/1000);
- spisdcard_clk_divider_write(divider);
-#endif
-
// Read in FAT16 File Allocation Table, array of 16bit unsinged integers
// Calculate Storage from TOP of MAIN RAM
sdCardFatTable = (uint16_t *)(MAIN_RAM_BASE+MAIN_RAM_SIZE-sdCardFatBootSector.sector_size*sdCardFatBootSector.fat_size_sectors);
// Calculate Start of FAT16 File Allocation Table (start of partition plus reserved sectors)
fatSectorStart=sdCardPartition.start_sector+sdCardFatBootSector.reserved_sectors;
for(n=0; n<sdCardFatBootSector.fat_size_sectors; n++) {
- if( readSector(fatSectorStart+n, (uint8_t *)((uint8_t*)sdCardFatTable)+sdCardFatBootSector.sector_size*n)==FAILURE ) {
+ if( read_block(fatSectorStart+n, (uint8_t *)((uint8_t*)sdCardFatTable)+sdCardFatBootSector.sector_size*n)==FAILURE ) {
printf("Error reading FAT16 table - sector %d\n",n);
return FAILURE;
}
// Calculate Start of FAT ROOT DIRECTORY (start of partition plues reserved sectors plus size of File Allocation Table(s))
rootDirSectorStart=sdCardPartition.start_sector+sdCardFatBootSector.reserved_sectors+sdCardFatBootSector.number_of_fats*sdCardFatBootSector.fat_size_sectors;
for(n=0; n<sdCardFatBootSector.root_dir_entries*sizeof(Fat16Entry)/sdCardFatBootSector.sector_size; n++) {
- if( readSector(rootDirSectorStart+n, (uint8_t *)(sdCardFatBootSector.sector_size*n+(uint8_t *)(sdCardFat16RootDir)))==FAILURE ) {
+ if( read_block(rootDirSectorStart+n, (uint8_t *)(sdCardFatBootSector.sector_size*n+(uint8_t *)(sdCardFat16RootDir)))==FAILURE ) {
printf("Error reading Root Dir - sector %d\n",n);
return FAILURE;
}
// Return 0 success, 1 failure
//
// Details from https://codeandlife.com/2012/04/02/simple-fat-and-sd-tutorial-part-1/
-uint8_t sdcard_readFile(char *filename, char *ext, unsigned long address)
+uint8_t fat16_read_file(char *filename, char *ext, unsigned long address)
{
int i, n, sector;
uint16_t fileClusterStart;
// If whole sector to be read, read directly into memory
// Otherwise, read to sdCardSector buffer and transfer appropriate number of bytes
if(bytesRemaining>sdCardFatBootSector.sector_size) {
- if( readSector(clusterSectorStart+sector,(uint8_t *)address) == FAILURE ) {
+ if( read_block(clusterSectorStart+sector,(uint8_t *)address) == FAILURE ) {
printf("\nRead Error\n");
return FAILURE;
}
bytesRemaining=bytesRemaining-sdCardFatBootSector.sector_size;
address=address+sdCardFatBootSector.sector_size;
} else {
- if( readSector(clusterSectorStart+sector,sdCardSector) == FAILURE ) {
+ if( read_block(clusterSectorStart+sector,sdCardSector) == FAILURE ) {
printf("\nRead Error\n");
return FAILURE;
}
// This file is Copyright (c) 2020 Rob Shelton <rob.s.ng15@googlemail.com>
+// This file is Copyright (c) 2020 Florent Kermarrec <florent@enjoy-digital.fr>
// License: BSD
//
-// SD CARD bitbanging code for loading files from a FAT16 forrmatted partition into memory
-//
-// Code is known to work on a de10nano with MiSTer SDRAM and IO Boards - IO Board has a secondary SD CARD interface connected to GPIO pins
-// SPI signals CLK, CS and MOSI are configured as GPIO output pins, and MISO is configued as GPIO input pins
-//
-// Protocol details developed from https://openlabpro.com/guide/interfacing-microcontrollers-with-sd-card/
-//
-// FAT16 details developed from https://codeandlife.com/2012/04/02/simple-fat-and-sd-tutorial-part-1/ and https://codeandlife.com/2012/04/07/simple-fat-and-sd-tutorial-part-2/
+// SDCard SPI-Mode support for LiteX's SPIMaster.
-// Import LiteX SoC details that are generated each time the SoC is compiled for the FPGA
-// csr defines the SPI Control registers
-// soc defines the clock CONFIG_CLOCK_FREQUENCY (50MHz for the VexRiscV processor on the MiSTer FPGA
-// mem defines the addresses for the SDRAM MAIN_RAM_BASE and MAIN_RAM_SIZE
-#include <generated/csr.h>
-#include <generated/soc.h>
-#include <generated/mem.h>
-
-#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
-#include <time.h>
#include <string.h>
+
+#include <generated/csr.h>
+#include <generated/mem.h>
#include <system.h>
-#ifdef CSR_SPISDCARD_BASE
-// Import prototypes for the functions
#include "spisdcard.h"
-// SPI
-// cs line - high to indicate DESELECT
-// - low to indicate SELECT
-#define CS_HIGH 0x00
-#define CS_LOW 0x01
-
-// control register values
-// onebyte to indicate 1 byte being transferred
-// spi_start to indicate START of transfer
-// spi_done to indicate transfer DONE
-#define ONEBYTE 0x0800
-#define SPI_START 0x01
-#define SPI_DONE 0x01
-
-// Return values
-#define SUCCESS 0x01
-#define FAILURE 0x00
-
-// spi_write_byte
-// Send a BYTE (8bits) to the SD CARD
-// Seqeunce
-// Set MOSI
-// Set START bit and LENGTH=8
-// Await DONE
-//
-// No return values
-//
-// Details from https://openlabpro.com/guide/interfacing-microcontrollers-with-sd-card/ section "SD Commands"
-void spi_write_byte(uint8_t char_to_send);
-void spi_write_byte(uint8_t char_to_send)
-{
- // Place data into MOSI register
- // Pulse the START bit and set LENGTH=8
- spisdcard_mosi_write(char_to_send);
- spisdcard_control_write(ONEBYTE | SPI_START);
-
- // Wait for DONE
- while( (spisdcard_status_read() != SPI_DONE)) {}
-
- // Signal end of transfer
- spisdcard_control_write( 0x00 );
-}
-
+#ifdef CSR_SPISDCARD_BASE
-// spi_read_rbyte
-// Read a command response from the SD CARD - Equivalent to and R1 response or first byte of an R7 response
-// Sequence
-// Read MISO
-// If MSB != 0 then send dsummy byte and re-read MISO
-//
-// Return value is the response from the SD CARD
-// If the MSB is not 0, this would represent an ERROR
-// Calling function to determine if the correct response has been received
-//
-// Details from https://openlabpro.com/guide/interfacing-microcontrollers-with-sd-card/ section "SD Commands"
-uint8_t spi_read_rbyte(void);
-uint8_t spi_read_rbyte(void)
-{
- int timeout=32;
- uint8_t r=0;
-
- // Check if MISO is 0x0xxxxxxx as MSB=0 indicates valid response
- r = spisdcard_miso_read();
- while( ((r&0x80)!=0) && timeout>0) {
- spisdcard_mosi_write( 0xff );
- spisdcard_control_write(ONEBYTE | SPI_START);
- while( (spisdcard_status_read() != SPI_DONE)) {}
- r = spisdcard_miso_read();
- spisdcard_control_write( 0x00 );
- timeout--;
- }
+/* SPI Master flags */
+
+#define SPI_CS_HIGH (0 << 0)
+#define SPI_CS_LOW (1 << 0)
+#define SPI_START (1 << 0)
+#define SPI_DONE (1 << 0)
+#define SPI_LENGTH (1 << 8)
+
+/* SPI Master low-level functions */
+
+static void spi_set_clk_freq(uint32_t clk_freq) {
+ uint32_t divider;
+ divider = CONFIG_CLOCK_FREQUENCY/clk_freq + 1;
+ printf("divider: %d\n", divider);
+ if (divider >= 65535) /* 16-bit hardware divider */
+ divider = 65535;
+ if (divider <= 2) /* At least half CPU speed */
+ divider = 2;
+ printf("Setting SDCard clk freq to ");
+ if (clk_freq > 1000000)
+ printf("%d MHz\n", (CONFIG_CLOCK_FREQUENCY/divider)/1000000);
+ else
+ printf("%d KHz\n", (CONFIG_CLOCK_FREQUENCY/divider)/1000);
+ spisdcard_clk_divider_write(divider);
+}
-// printf("Done\n");
- return r;
+static uint8_t spi_xfer(uint8_t byte) {
+ /* Write byte on MOSI */
+ spisdcard_mosi_write(byte);
+ /* Initiate SPI Xfer */
+ spisdcard_control_write(8*SPI_LENGTH | SPI_START);
+ /* Wait SPI Xfer to be done */
+ while(spisdcard_status_read() != SPI_DONE);
+ /* Read MISO and return it */
+ return spisdcard_miso_read();
}
-// spi_read_byte
-// Sequence
-// Send dummy byte
-// Read MISO
-//
-// Read subsequenct bytes from the SD CARD - MSB first
-// NOTE different from the spi_read_rbyte as no need to await an intial 0 bit as card is already responsing
-// Used to read additional response bytes, or data bytes from the SD CARD
-//
-// Return value is the byte read
-// NOTE no error status as assumed bytes are read via CLK pulses
-//
-// Details from https://openlabpro.com/guide/interfacing-microcontrollers-with-sd-card/ section "SD Commands"
-uint8_t spi_read_byte(void);
-uint8_t spi_read_byte(void)
-{
- uint8_t r=0;
+/* SPI SDCard functions */
- spi_write_byte( 0xff );
- r = spisdcard_miso_read();
+static uint8_t spisdcard_wait_response(void) {
+ uint8_t timeout;
+ uint8_t response;
- return r;
+ timeout = 32;
+ /* Do SPI Xfers on SDCard until MISO MSB's is 0 (valid response) or timeout is expired */
+ do {
+ response = spi_xfer(0xff);
+ timeout--;
+ } while(((response & 0x80) !=0) && timeout > 0);
+ return response;
}
-// SETSPIMODE
-// Signal the SD CARD to switch to SPI mode
-// Pulse the CLK line HIGH/LOW repeatedly with MOSI and CS_N HIGH
-// Drop CS_N LOW and pulse the CLK
-// Check MISO for HIGH
-// Return 0 success, 1 failure
-//
-// Details from https://openlabpro.com/guide/interfacing-microcontrollers-with-sd-card/ section "Initializing the SD Card"
-uint8_t spi_setspimode(void);
-uint8_t spi_setspimode(void)
-{
- uint32_t r;
- int i, timeout=32;
-
- // Initialise SPI mode
- // set CS to HIGH
- // Send pulses
- do {
- // set CS HIGH and send pulses
- spisdcard_cs_write(CS_HIGH);
- for (i=0; i<10; i++) {
- spi_write_byte( 0xff );
- }
-
- // set CS LOW and send pulses
- spisdcard_cs_write(CS_LOW);
- r = spi_read_rbyte();
+static uint8_t spisdcard_set_mode(void) {
+ uint8_t timeout;
+ uint8_t response;
+
+ timeout = 32;
+ do {
+ int i;
+ /* Set CS and send 80 clock pulses to set the SDCard in SPI Mode */
+ spisdcard_cs_write(SPI_CS_HIGH);
+ for (i=0; i<10; i++)
+ spi_xfer(0xff);
+ /* Clear CS and read response, if 0 the SDCard has been initialized to SPI Mode */
+ spisdcard_cs_write(SPI_CS_LOW);
+ response = spisdcard_wait_response();
timeout--;
- } while ( (timeout>0) && (r==0) );
+ } while ((timeout > 0) && (response == 0));
- if(timeout==0) return FAILURE;
+ if(timeout == 0)
+ return 0;
- return SUCCESS;
+ return 1;
}
-// SPI_SDCARD_GOIDLE
-// Function exposed to BIOS to initialise SPI mode
-//
-// Sequence
-// Set 100KHz timer mode
-// Send CLK pulses to set SD CARD to SPI mode
-// Send CMD0 - Software RESET - force SD CARD IDLE
-// Send CMD8 - Check SD CARD type
-// Send CMD55+ACMD41 - Force SD CARD READY
-// Send CMD58 - Read SD CARD OCR (status register)
-// Send CMD16 - Set SD CARD block size to 512 - Sector Size for the SD CARD
-// NOTE - Each command is prefixed with a dummy set of CLK pulses to prepare SD CARD to receive a command
-// Return 0 success, 1 failure
-//
-// Details from https://openlabpro.com/guide/interfacing-microcontrollers-with-sd-card/ section "Initializing the SD Card"
-uint8_t spi_sdcard_goidle(void)
-{
- uint8_t r; // Response from SD CARD
- int i, timeout; // TIMEOUT loop to send CMD55+ACMD41 repeatedly
-
- r = spi_setspimode(); // Set SD CARD to SPI mode
- if( r != 0x01 ) return FAILURE;
-
- // CMD0 - Software reset - SD CARD IDLE
- // Command Sequence is DUMMY=0xff CMD0=0x40 0x00 0x00 0x00 0x00 CRC=0x95
- // Expected R1 response is 0x01 indicating SD CARD is IDLE
- spi_write_byte( 0xff ); spi_write_byte( 0x40 ); spi_write_byte( 0x00 ); spi_write_byte( 0x00 ); spi_write_byte( 0x00 ); spi_write_byte( 0x00 ); spi_write_byte( 0x95 );
- r = spi_read_rbyte();
- if(r!=0x01) return FAILURE;
-
- // CMD8 - Check SD CARD type
- // Command sequence is DUMMY=0xff CMD8=0x48 0x00 0x00 0x01 0xaa CRC=0x87
- // Expected R7 response is 0x01 followed by 0x00 0x00 0x01 0xaa (these trailing 4 bytes not currently checked)
- spi_write_byte( 0xff ); spi_write_byte( 0x48 ); spi_write_byte( 0x00 ); spi_write_byte( 0x00 ); spi_write_byte( 0x01 ); spi_write_byte( 0xaa ); spi_write_byte( 0x87 );
- r = spi_read_rbyte();
- if(r!=0x01) return FAILURE;
- // Receive the trailing 4 bytes for R7 response - FIXME should check for 0x00 0x00 0x01 0xaa
+uint8_t spisdcard_init(void) {
+ uint8_t i;
+ uint8_t r;
+ uint8_t timeout;
+
+ /* Set SPI clk freq to 400KHz */
+ spi_set_clk_freq(400000);
+
+ /* Set SDCard in SPI Mode */
+ r = spisdcard_set_mode();
+ if(r != 0x01)
+ return 0;
+
+ /* Send SD CARD IDLE */
+ /* CMD0 */
+ spi_xfer(0xff);
+ spi_xfer(0x40);
+ spi_xfer(0x00);
+ spi_xfer(0x00);
+ spi_xfer(0x00);
+ spi_xfer(0x00);
+ spi_xfer(0x95);
+ /* R1 response, expects 0x1 */
+ r = spisdcard_wait_response();
+ if(r != 0x01)
+ return 0;
+
+ /* Send Check SD CARD type */
+ /* CMD8 */
+ spi_xfer(0xff);
+ spi_xfer(0x48);
+ spi_xfer(0x00);
+ spi_xfer(0x00);
+ spi_xfer(0x01);
+ spi_xfer(0xaa);
+ spi_xfer(0x87);
+ /* R7, expects 0x1 */
+ r = spisdcard_wait_response();
+ if(r != 0x01)
+ return 0;
+ /* Reveice the 4 trailing bytes */
for(i=0; i<4; i++)
- r=spi_read_byte();
-
- // CMD55+ACMD41 - Force SD CARD READY - prepare card for reading/writing
- // Command sequence is CMD55 followed by ACMD41
- // Send commands repeatedly until SD CARD indicates READY 0x00
- // CMD55 Sequence is DUMMY=0xff CMD55=0x77 0x00 0x00 0x00 0x00 CRC=0x00
- // ACMD41 Sequence is DUMMY=0xff ACMD41=0x69 0x40 0x00 0x00 0x00 CRC=0x00
- // Expected R1 response is 0x00 indicating SD CARD is READY
- timeout=32;
- do {
- spi_write_byte( 0xff ); spi_write_byte( 0x77 ); spi_write_byte( 0x00 ); spi_write_byte( 0x00 ); spi_write_byte( 0x00 ); spi_write_byte( 0x00 ); spi_write_byte( 0x00 );
- r = spi_read_rbyte();
+ r = spi_xfer(0xff); /* FIXME: add check? */
- spi_write_byte( 0xff ); spi_write_byte( 0x69 ); spi_write_byte( 0x40 ); spi_write_byte( 0x00 ); spi_write_byte( 0x00 ); spi_write_byte( 0x00 ); spi_write_byte( 0x00 );
- r = spi_read_rbyte();
+ /* Send Force SD CARD READY (CMD55 + ACMD41), expects 0x00 R1 response */
+ timeout = 32;
+ do {
+ /* CMD55 */
+ spi_xfer(0xff);
+ spi_xfer(0x77);
+ spi_xfer(0x00);
+ spi_xfer(0x00);
+ spi_xfer(0x00);
+ spi_xfer(0x00);
+ spi_xfer(0x00);
+ r = spisdcard_wait_response();
+ /* ACMD41 */
+ spi_xfer(0xff);
+ spi_xfer(0x69);
+ spi_xfer(0x40);
+ spi_xfer(0x00);
+ spi_xfer(0x00);
+ spi_xfer(0x00);
+ spi_xfer(0x00);
+ /* R1 */
+ r = spisdcard_wait_response();
timeout--;
+ /* 20ms delay */
busy_wait(20);
- } while ((r != 0x00) && (timeout>0));
- if(r!=0x00) return FAILURE;
-
- // CMD58 - Read SD CARD OCR (status register)
- // FIXME - Find details on expected response from CMD58 to allow accurate checking of SD CARD R3 response
- // Command sequence is DUMMY=0xff CMD58=0x7a 0x00 0x00 0x01 0xaa CRC=0xff
- // Expected R3 response is 0x00 OR 0x01 followed by 4 (unchecked) trailing bytes
- spi_write_byte( 0xff ); spi_write_byte( 0x7a ); spi_write_byte( 0x00 ); spi_write_byte( 0x00 ); spi_write_byte( 0x00 ); spi_write_byte( 0x00 ); spi_write_byte( 0xff );
- r = spi_read_rbyte();
- if(r>0x01) return FAILURE;
- // // Receive the trailing 4 bytes for R3 response
+ } while ((r != 0x00) && (timeout > 0));
+ if(r != 0x00)
+ return 0;
+
+ /* Send Read SD CARD OCR (status register) */
+ /* CMD58 */
+ spi_xfer(0xff);
+ spi_xfer(0x7a);
+ spi_xfer(0x00);
+ spi_xfer(0x00);
+ spi_xfer(0x00);
+ spi_xfer(0x00);
+ spi_xfer(0xff);
+ /* R3, expects 0x1 */
+ r = spisdcard_wait_response();
+ if(r > 0x01)
+ return 0;
+ /* Reveice the 4 trailing bytes */
for(i=0; i<4; i++)
- r=spi_read_byte();
-
- // CMD16 - Set SD CARD block size to 512 - Sector Size for the SD CARD
- // Command Sequence is DUMMY=0xff CMD16=0x50 (512 as unsigned 32bit = 0x00000200) 0x00 0x00 0x02 0x00 CRC=0xff
- // Expected R1 response is 0x00 indicating SD CARD is READY
- spi_write_byte( 0xff ); spi_write_byte( 0x50 ); spi_write_byte( 0x00 ); spi_write_byte( 0x00 ); spi_write_byte( 0x02 ); spi_write_byte( 0x00 ); spi_write_byte( 0xff );
- r=spi_read_rbyte();
- if(r!=0x00) return FAILURE;
-
- return SUCCESS;
+ r = spi_xfer(0xff); /* FIXME: add check? */
+
+ /* Send Set SD CARD block size */
+ /* CMD16 */
+ spi_xfer(0xff);
+ spi_xfer(0x50);
+ spi_xfer(0x00);
+ spi_xfer(0x00);
+ spi_xfer(0x02);
+ spi_xfer(0x00);
+ spi_xfer(0xff);
+ /* RI, expects 0x00 */
+ r = spisdcard_wait_response();
+ if(r != 0x00)
+ return 0;
+
+ /* Set SPI clk freq to 16MHz */
+ spi_set_clk_freq(16000000);
+
+ return 1;
}
-// READSECTOR
-// Read a 512 byte sector from the SD CARD
-// Given SECTORNUMBER and memory STORAGE
-//
-// Sequence
-// Send CMD17 - Read Block
-// Command Sequence is DUMMY=0xff CMD17=0x51 SECTORNUMBER (32bit UNSIGNED as bits 32-25,24-17, 16-9, 8-1) CRC=0xff
-// Wait for SD CARD to send 0x00 indicating SD CARD is processing
-// Wait for SD CARD to send 0xfe indicating SD CARD BLOCK START
-// Read 512 bytes
-// Read 8 DUMMY bytes
-// Return 0 success, 1 failure
-//
-// Details from https://openlabpro.com/guide/interfacing-microcontrollers-with-sd-card/ section "Read/Write SD Card"
-uint8_t readSector(uint32_t sectorNumber, uint8_t *storage);
-uint8_t readSector(uint32_t sectorNumber, uint8_t *storage)
-{
- int n, timeout; // Number of bytes loop, timeout loop awaiting response bytes
- uint8_t r; // Response bytes from SD CARD
-
- // CMD17 - Read Block
- // Command Sequence is DUMMY=0xff CMD17=0x51 SECTORNUMBER (32bit UNSIGNED as bits 32-25,24-17, 16-9, 8-1) CRC=0xff
- // Expected R1 response is 0x00 indicating SD CARD is processing
- spi_write_byte( 0xff ); spi_write_byte( 0x51 ); spi_write_byte( (sectorNumber>>24)&0xff ); spi_write_byte( (sectorNumber>>16)&0xff ); spi_write_byte( (sectorNumber>>8)&0xff ); spi_write_byte( (sectorNumber)&0xff ); spi_write_byte( 0xff );
- r=spi_read_rbyte();
- if( r!=0x00 ) return FAILURE;
-
- // Await 0xfe to indicate BLOCK START
- r=spi_read_byte();
- timeout=16384;
- while( (r!=0xfe) && (timeout>0) ) {
- r=spi_read_byte();
+uint8_t spisdcard_read_block(uint32_t addr, uint8_t *buf) {
+ int i;
+ uint32_t timeout;
+ uint8_t r;
+
+ /* Send Read Block */
+ /* CMD17 */
+ spi_xfer(0xff);
+ spi_xfer(0x51);
+ spi_xfer((addr >> 24) & 0xff);
+ spi_xfer((addr >> 16) & 0xff);
+ spi_xfer((addr >> 8) & 0xff);
+ spi_xfer((addr >> 0) & 0xff);
+ spi_xfer(0xff);
+ /* R1, expects 0x00 that indicates the SDCard is processing */
+ r = spisdcard_wait_response();
+ if(r != 0x00)
+ return 0;
+
+ /* Do SPI Xfers on SDCard until 0xfe is received (block start) or timeout is expired */
+ r = spi_xfer(0xff);
+ timeout = 16384;
+ do {
+ r = spi_xfer(0xff);
timeout--;
- }
- if( r!=0xfe ) return FAILURE;
+ } while((r != 0xfe) && (timeout>0));
+ if(r != 0xfe)
+ return 0;
- // Read 512 bytes into storage
- for(n=0; n<512; n++)
- storage[n]=spi_read_byte();
+ /* Read the block from the SDCard and copy it to the buffer */
+ for(i=0; i<512; i++)
+ buf[i] = spi_xfer(0xff);
- // Read 8 dummy bytes
- for(n=0; n<8; n++)
- r=spi_read_byte();
+ /* Read the 8 dummy bytes */
+ for(i=0; i<8; i++)
+ r = spi_xfer(0xff);
- return SUCCESS;
+ return 1;
}
#endif