Add large FIFO for SD card responses, can now read the OCR, CSD and CID

This commit is contained in:
meepingsnesroms
2019-02-23 11:17:30 -08:00
parent 1662655786
commit 42852dc331
9 changed files with 160 additions and 113 deletions

View File

@@ -146,7 +146,8 @@ HEADERS += \
../../src/armv5/types.h \
../../src/armv5/icache.h \
../../src/armv5.h \
../../src/expansionHardware.h
../../src/expansionHardware.h \
../../src/sdCardAccessors.c.h
FORMS += \
mainwindow.ui \

View File

@@ -111,7 +111,7 @@ static uint32_t makePalmString(const char* str){
uint32_t strLength = strlen(str) + 1;
uint32_t strData = sandboxCallGuestFunction(false, 0x00000000, MemPtrNew, "p(l)", strLength);
if(strData != 0){
if(strData){
uint32_t count;
for(count = 0; count < strLength; count++)
@@ -122,7 +122,7 @@ static uint32_t makePalmString(const char* str){
}
static char* makeNativeString(uint32_t address){
if(address != 0){
if(address){
int16_t strLength = sandboxCallGuestFunction(false, 0x00000000, StrLen, "w(p)", address) + 1;
char* nativeStr = malloc(strLength);
int16_t count;

View File

@@ -376,10 +376,6 @@ bool emulatorSaveState(buffer_t buffer){
offset += sizeof(uint64_t);
writeStateValue8(buffer.data + offset, palmSdCard.commandBitsRemaining);
offset += sizeof(uint8_t);
writeStateValue8(buffer.data + offset, palmSdCard.response);
offset += sizeof(uint8_t);
writeStateValue64(buffer.data + offset, palmSdCard.responseState);
offset += sizeof(uint64_t);
writeStateValue8(buffer.data + offset, palmSdCard.allowInvalidCrc);
offset += sizeof(uint8_t);
writeStateValue8(buffer.data + offset, palmSdCard.chipSelect);
@@ -557,10 +553,6 @@ bool emulatorLoadState(buffer_t buffer){
offset += sizeof(uint64_t);
palmSdCard.commandBitsRemaining = readStateValue8(buffer.data + offset);
offset += sizeof(uint8_t);
palmSdCard.response = readStateValue8(buffer.data + offset);
offset += sizeof(uint8_t);
palmSdCard.responseState = readStateValue64(buffer.data + offset);
offset += sizeof(uint64_t);
palmSdCard.allowInvalidCrc = readStateValue8(buffer.data + offset);
offset += sizeof(uint8_t);
palmSdCard.chipSelect = readStateValue8(buffer.data + offset);

View File

@@ -39,6 +39,22 @@ void frontendHandleDebugPrint();
static void debugLog(char* str, ...){};
#endif
//config options
#define EMU_FPS 60
#define EMU_SYSCLK_PRECISION 2000000//the amount of cycles to run before adding SYSCLKs, higher = faster, higher values may skip timer events and lower audio accuracy
#define EMU_CPU_PERCENT_WAITING 0.30//account for wait states when reading memory, tested with SysInfo.prc
#define AUDIO_SAMPLE_RATE 48000
#define AUDIO_CLOCK_RATE 235929600//smallest amount of time a second can be split into:(2.0 * (14.0 * (255 + 1.0) + 15 + 1.0)) * 32768 == 235929600, used to convert the variable timing of SYSCLK and CLK32 to a fixed location in the current frame 0<->AUDIO_END_OF_FRAME
#define AUDIO_SPEAKER_RANGE 0x6000//prevent hitting the top or bottom of the speaker when switching direction rapidly
#define SD_CARD_RESPONSE_FIFO_SIZE 10000
#define SD_CARD_NCR_BYTES 1
#define SAVE_STATE_VERSION 0
//system constants
#define CRYSTAL_FREQUENCY 32768
#define AUDIO_SAMPLES_PER_FRAME (AUDIO_SAMPLE_RATE / EMU_FPS)
#define AUDIO_END_OF_FRAME (AUDIO_CLOCK_RATE / EMU_FPS)
//emu errors
enum{
EMU_ERROR_NONE = 0,
@@ -88,9 +104,10 @@ typedef struct{
typedef struct{
uint64_t command;
uint8_t commandBitsRemaining;
uint8_t response;
uint64_t responseState;//this can contain many different types of data depending on the response type
uint8_t responseWaitBitsRemaining;//not in savestates yet!!
uint8_t responseFifo[SD_CARD_RESPONSE_FIFO_SIZE];//not in savestates yet!!
uint16_t responseReadPosition;//not in savestates yet!!
int8_t responseReadPositionBit;//not in savestates yet!!
uint16_t responseWritePosition;//not in savestates yet!!
bool commandIsAcmd;//not in savestates yet!!
bool allowInvalidCrc;
bool chipSelect;
@@ -118,20 +135,6 @@ typedef struct{
//uint32_t cmd;//one time use, has no variable
}emu_reg_t;
//config options
#define EMU_FPS 60
#define EMU_SYSCLK_PRECISION 2000000//the amount of cycles to run before adding SYSCLKs, higher = faster, higher values may skip timer events and lower audio accuracy
#define EMU_CPU_PERCENT_WAITING 0.30//account for wait states when reading memory, tested with SysInfo.prc
#define AUDIO_SAMPLE_RATE 48000
#define AUDIO_CLOCK_RATE 235929600//smallest amount of time a second can be split into:(2.0 * (14.0 * (255 + 1.0) + 15 + 1.0)) * 32768 == 235929600, used to convert the variable timing of SYSCLK and CLK32 to a fixed location in the current frame 0<->AUDIO_END_OF_FRAME
#define AUDIO_SPEAKER_RANGE 0x6000//prevent hitting the top or bottom of the speaker when switching direction rapidly
#define SAVE_STATE_VERSION 0
//system constants
#define CRYSTAL_FREQUENCY 32768
#define AUDIO_SAMPLES_PER_FRAME (AUDIO_SAMPLE_RATE / EMU_FPS)
#define AUDIO_END_OF_FRAME (AUDIO_CLOCK_RATE / EMU_FPS)
//emulator data, some are GUI interface variables, some should be left alone
extern uint8_t* palmRam;//access allowed to read save RAM without allocating a giant buffer, but endianness must be taken into account
extern uint8_t* palmRom;//dont touch

View File

@@ -43,7 +43,6 @@ static uint16_t spi1RxFifoRead(void){
if(spi1RxFifoEntrys() > 0)
spi1RxReadPosition = (spi1RxReadPosition + 1) % 9;
spi1RxOverflowed = false;
return spi1RxFifo[spi1RxReadPosition];
}

View File

@@ -175,8 +175,9 @@
* operations.
*/
#define M68K_USE_64_BIT OPT_OFF
//it seems MASK_OUT_ABOVE_32 is has to be called on every 32 bit operation when using this option,
//possibly even making the speed worse than with just 32 bits
/* It seems MASK_OUT_ABOVE_32 is has to be called on every 32 bit operation when using this option,
* possibly even making the speed worse than with just 32 bits.
*/
/* Set to your compiler's static inline keyword to enable it, or

View File

@@ -1,46 +1,38 @@
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include "emulator.h"
#include "specs/sdCardCommandSpec.h"
enum{
SD_CARD_RESPONSE_NOTHING = 0,
SD_CARD_RESPONSE_SHIFT_OUT,
SD_CARD_RESPONSE_READ_BLOCK
};
static const uint8_t sdCardCrc7Table[256] = {
0x00,0x09,0x12,0x1B,0x24,0x2D,0x36,0x3F,0x48,0x41,0x5A,0x53,0x6C,0x65,0x7E,
0x77,0x19,0x10,0x0B,0x02,0x3D,0x34,0x2F,0x26,0x51,0x58,0x43,0x4A,0x75,0x7C,
0x67,0x6E,0x32,0x3B,0x20,0x29,0x16,0x1F,0x04,0x0D,0x7A,0x73,0x68,0x61,0x5E,
0x57,0x4C,0x45,0x2B,0x22,0x39,0x30,0x0F,0x06,0x1D,0x14,0x63,0x6A,0x71,0x78,
0x47,0x4E,0x55,0x5C,0x64,0x6D,0x76,0x7F,0x40,0x49,0x52,0x5B,0x2C,0x25,0x3E,
0x37,0x08,0x01,0x1A,0x13,0x7D,0x74,0x6F,0x66,0x59,0x50,0x4B,0x42,0x35,0x3C,
0x27,0x2E,0x11,0x18,0x03,0x0A,0x56,0x5F,0x44,0x4D,0x72,0x7B,0x60,0x69,0x1E,
0x17,0x0C,0x05,0x3A,0x33,0x28,0x21,0x4F,0x46,0x5D,0x54,0x6B,0x62,0x79,0x70,
0x07,0x0E,0x15,0x1C,0x23,0x2A,0x31,0x38,0x41,0x48,0x53,0x5A,0x65,0x6C,0x77,
0x7E,0x09,0x00,0x1B,0x12,0x2D,0x24,0x3F,0x36,0x58,0x51,0x4A,0x43,0x7C,0x75,
0x6E,0x67,0x10,0x19,0x02,0x0B,0x34,0x3D,0x26,0x2F,0x73,0x7A,0x61,0x68,0x57,
0x5E,0x45,0x4C,0x3B,0x32,0x29,0x20,0x1F,0x16,0x0D,0x04,0x6A,0x63,0x78,0x71,
0x4E,0x47,0x5C,0x55,0x22,0x2B,0x30,0x39,0x06,0x0F,0x14,0x1D,0x25,0x2C,0x37,
0x3E,0x01,0x08,0x13,0x1A,0x6D,0x64,0x7F,0x76,0x49,0x40,0x5B,0x52,0x3C,0x35,
0x2E,0x27,0x18,0x11,0x0A,0x03,0x74,0x7D,0x66,0x6F,0x50,0x59,0x42,0x4B,0x17,
0x1E,0x05,0x0C,0x33,0x3A,0x21,0x28,0x5F,0x56,0x4D,0x44,0x7B,0x72,0x69,0x60,
0x0E,0x07,0x1C,0x15,0x2A,0x23,0x38,0x31,0x46,0x4F,0x54,0x5D,0x62,0x6B,0x70,
0x79
0x00,0x09,0x12,0x1B,0x24,0x2D,0x36,0x3F,0x48,0x41,0x5A,0x53,0x6C,0x65,0x7E,0x77,
0x19,0x10,0x0B,0x02,0x3D,0x34,0x2F,0x26,0x51,0x58,0x43,0x4A,0x75,0x7C,0x67,0x6E,
0x32,0x3B,0x20,0x29,0x16,0x1F,0x04,0x0D,0x7A,0x73,0x68,0x61,0x5E,0x57,0x4C,0x45,
0x2B,0x22,0x39,0x30,0x0F,0x06,0x1D,0x14,0x63,0x6A,0x71,0x78,0x47,0x4E,0x55,0x5C,
0x64,0x6D,0x76,0x7F,0x40,0x49,0x52,0x5B,0x2C,0x25,0x3E,0x37,0x08,0x01,0x1A,0x13,
0x7D,0x74,0x6F,0x66,0x59,0x50,0x4B,0x42,0x35,0x3C,0x27,0x2E,0x11,0x18,0x03,0x0A,
0x56,0x5F,0x44,0x4D,0x72,0x7B,0x60,0x69,0x1E,0x17,0x0C,0x05,0x3A,0x33,0x28,0x21,
0x4F,0x46,0x5D,0x54,0x6B,0x62,0x79,0x70,0x07,0x0E,0x15,0x1C,0x23,0x2A,0x31,0x38,
0x41,0x48,0x53,0x5A,0x65,0x6C,0x77,0x7E,0x09,0x00,0x1B,0x12,0x2D,0x24,0x3F,0x36,
0x58,0x51,0x4A,0x43,0x7C,0x75,0x6E,0x67,0x10,0x19,0x02,0x0B,0x34,0x3D,0x26,0x2F,
0x73,0x7A,0x61,0x68,0x57,0x5E,0x45,0x4C,0x3B,0x32,0x29,0x20,0x1F,0x16,0x0D,0x04,
0x6A,0x63,0x78,0x71,0x4E,0x47,0x5C,0x55,0x22,0x2B,0x30,0x39,0x06,0x0F,0x14,0x1D,
0x25,0x2C,0x37,0x3E,0x01,0x08,0x13,0x1A,0x6D,0x64,0x7F,0x76,0x49,0x40,0x5B,0x52,
0x3C,0x35,0x2E,0x27,0x18,0x11,0x0A,0x03,0x74,0x7D,0x66,0x6F,0x50,0x59,0x42,0x4B,
0x17,0x1E,0x05,0x0C,0x33,0x3A,0x21,0x28,0x5F,0x56,0x4D,0x44,0x7B,0x72,0x69,0x60,
0x0E,0x07,0x1C,0x15,0x2A,0x23,0x38,0x31,0x46,0x4F,0x54,0x5D,0x62,0x6B,0x70,0x79
};
static const uint64_t sdCardCsd[2] = {0x0000000000000000, 0x0000000000000000};
static const uint64_t sdCardCid[2] = {0x0000000000000000, 0x0000000000000000};
static const uint8_t sdCardCsd[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
static const uint8_t sdCardCid[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
static uint32_t sdCardGetOcr(){
return !palmSdCard.inIdleState << 31/*power up status*/ | 0 << 30/*card capacity status*/ | 0x01FF8000/*supported voltages*/;
static uint32_t sdCardGetOcr(void){
return palmSdCard.inIdleState << 31/*power up status*/ | 0 << 30/*card capacity status*/ | 0x01FF8000/*supported voltages*/;
}
static void sdCardCmdStart(){
static void sdCardCmdStart(void){
palmSdCard.command = UINT64_C(0x0000000000000000);
palmSdCard.commandBitsRemaining = 48;
palmSdCard.receivingCommand = true;
@@ -50,7 +42,8 @@ static bool sdCardCmdIsCrcValid(uint8_t command, uint32_t argument, uint8_t crc)
#if !defined(EMU_NO_SAFETY)
uint8_t commandCrc = 0;
command |= 0x40;//add the 01 command starting sequence, not actually part of the command but its counted in the checksum
//add the 01 command starting sequence, not actually part of the command but its counted in the checksum
command |= 0x40;
commandCrc = sdCardCrc7Table[(commandCrc << 1) ^ command];
commandCrc = sdCardCrc7Table[(commandCrc << 1) ^ (argument >> 24 & 0xFF)];
@@ -65,27 +58,15 @@ static bool sdCardCmdIsCrcValid(uint8_t command, uint32_t argument, uint8_t crc)
return true;
}
static void sdCardDoResponseR1(uint8_t r1){
palmSdCard.response = SD_CARD_RESPONSE_SHIFT_OUT;
palmSdCard.responseState = (uint64_t)r1 << 56;
palmSdCard.responseState |= UINT64_C(1) << 55;//add shift termination bit
palmSdCard.responseWaitBitsRemaining = 8;//needs to be at least 8 for MMC
}
static void sdCardDoResponseR3(uint8_t r1){
palmSdCard.response = SD_CARD_RESPONSE_SHIFT_OUT;
palmSdCard.responseState = (uint64_t)r1 << 56;
palmSdCard.responseState |= (uint64_t)sdCardGetOcr() << 24;
palmSdCard.responseState |= UINT64_C(1) << 23;//add shift termination bit
palmSdCard.responseWaitBitsRemaining = 8;//needs to be at least 8 for MMC
}
#include "sdCardAccessors.c.h"
void sdCardReset(void){
palmSdCard.command = UINT64_C(0x0000000000000000);
palmSdCard.commandBitsRemaining = 48;
palmSdCard.responseState = 0;
palmSdCard.response = SD_CARD_RESPONSE_NOTHING;
palmSdCard.responseWaitBitsRemaining = 0;
memset(palmSdCard.responseFifo, 0x00, SD_CARD_RESPONSE_FIFO_SIZE);
palmSdCard.responseReadPosition = 0;
palmSdCard.responseWritePosition = 0;
palmSdCard.responseReadPositionBit = 7;
palmSdCard.commandIsAcmd = false;
palmSdCard.allowInvalidCrc = false;
palmSdCard.chipSelect = false;
@@ -96,7 +77,7 @@ void sdCardReset(void){
void sdCardSetChipSelect(bool value){
if(value != palmSdCard.chipSelect){
//debugLog("SD card chip select set to:%s\n", value ? "true" : "false");
printf("C%s", value ? "T" : "F");
//printf("C%s", value ? "T" : "F");
//commands start when chip select goes from high to low
if(value == false)
@@ -107,33 +88,11 @@ void sdCardSetChipSelect(bool value){
}
bool sdCardExchangeBit(bool bit){
bool sdCardOutputValue = true;//default output value is true, if an action is ongoing it will be set to the data provided by that action
bool outputValue = true;//default output value is true, if an action is ongoing it will be set to the data provided by that action
//make sure SD is actually plugged in and chip select is low
if(palmSdCard.flashChip.data && !palmSdCard.chipSelect){
//idle wait for NCR
if(palmSdCard.responseWaitBitsRemaining == 0){
//process current exchange, needs to happen before command is proccessed because command response starts the next bit after the command is processed
switch(palmSdCard.response){
case SD_CARD_RESPONSE_NOTHING:
break;
case SD_CARD_RESPONSE_SHIFT_OUT:
//debugLog("SD shift out state:0x%016lX\n", palmSdCard.responseState);
sdCardOutputValue = !!(palmSdCard.responseState & UINT64_C(0x8000000000000000));
palmSdCard.responseState <<= 1;
if(palmSdCard.responseState == UINT64_C(0x8000000000000000))
palmSdCard.response = SD_CARD_RESPONSE_NOTHING;
break;
default:
debugLog("SD exchange:%d\n", palmSdCard.response);
break;
}
}
else{
palmSdCard.responseWaitBitsRemaining--;
}
outputValue = sdCardResponseFifoReadBit();
//route received bit as command or data
if(palmSdCard.receivingCommand){
@@ -170,9 +129,7 @@ bool sdCardExchangeBit(bool bit){
uint8_t command = palmSdCard.command >> 40 & 0x3F;
uint32_t argument = palmSdCard.command >> 8 & 0xFFFFFFFF;
uint8_t crc = palmSdCard.command >> 1 & 0x7F;
//command finished, wait for next chip select toggle to start the next
palmSdCard.receivingCommand = false;
bool commandWantsData = false;
debugLog("SD command: isAcmd:%d, cmd:%d, arg:0x%08X, CRC:0x%02X\n", palmSdCard.commandIsAcmd, command, argument, crc);
@@ -187,19 +144,33 @@ bool sdCardExchangeBit(bool bit){
break;
case SEND_OP_COND:
//after this is run the SD card is initialized
palmSdCard.inIdleState = false;
sdCardDoResponseR1(palmSdCard.inIdleState);
break;
case READ_OCR:
sdCardDoResponseR3(palmSdCard.inIdleState);
sdCardDoResponseR3R7(palmSdCard.inIdleState, sdCardGetOcr());
break;
case SEND_CSD:
sdCardDoResponseR1(palmSdCard.inIdleState);
if(!palmSdCard.inIdleState){
sdCardDoResponseDelay(1);
sdCardDoResponseDataPacket(DATA_TOKEN_DEFAULT, sdCardCsd, 16);
}
break;
case SEND_CID:
sdCardDoResponseR1(palmSdCard.inIdleState);
if(!palmSdCard.inIdleState){
sdCardDoResponseDelay(1);
sdCardDoResponseDataPacket(DATA_TOKEN_DEFAULT, sdCardCid, 16);
}
break;
case APP_CMD:
printf("A");
debugLog("SD response state: waitBits:%d, responseType:%d, stateBits:0x%016lX\n", palmSdCard.responseWaitBitsRemaining, palmSdCard.response, palmSdCard.responseState);
palmSdCard.commandIsAcmd = true;
sdCardCmdStart();
sdCardDoResponseR1(palmSdCard.inIdleState);
break;
@@ -213,7 +184,7 @@ bool sdCardExchangeBit(bool bit){
//ACMD command
switch(command){
case APP_SEND_OP_COND:
//after this is run the SD card is fully initialized
//after this is run the SD card is initialized
palmSdCard.inIdleState = false;
sdCardDoResponseR1(palmSdCard.inIdleState);
break;
@@ -233,6 +204,12 @@ bool sdCardExchangeBit(bool bit){
debugLog("SD invalid CRC\n");
sdCardDoResponseR1(COMMAND_CRC_ERROR | palmSdCard.inIdleState);
}
//start next command if previous doesnt take any data
if(commandWantsData)
palmSdCard.receivingCommand = false;
else
sdCardCmdStart();
}
}
else{
@@ -243,5 +220,5 @@ bool sdCardExchangeBit(bool bit){
}
}
return sdCardOutputValue;
return outputValue;
}

69
src/sdCardAccessors.c.h Normal file
View File

@@ -0,0 +1,69 @@
//FIFO accessors
static uint16_t sdCardResponseFifoByteEntrys(void){
//check for wraparound
if(palmSdCard.responseWritePosition <palmSdCard.responseReadPosition)
return palmSdCard.responseWritePosition + SD_CARD_RESPONSE_FIFO_SIZE - palmSdCard.responseReadPosition;
return palmSdCard.responseWritePosition - palmSdCard.responseReadPosition;
}
static bool sdCardResponseFifoReadBit(void){
if(sdCardResponseFifoByteEntrys() > 0){
bool bit = !!(palmSdCard.responseFifo[palmSdCard.responseReadPosition] & 1 << palmSdCard.responseReadPositionBit);
palmSdCard.responseReadPositionBit--;
if(palmSdCard.responseReadPositionBit < 0){
palmSdCard.responseReadPositionBit = 7;
palmSdCard.responseReadPosition = (palmSdCard.responseReadPosition + 1) % SD_CARD_RESPONSE_FIFO_SIZE;
}
return bit;
}
return true;
}
static void sdCardResponseFifoWriteByte(uint8_t value){
if(sdCardResponseFifoByteEntrys() < SD_CARD_RESPONSE_FIFO_SIZE - 1){
palmSdCard.responseFifo[palmSdCard.responseWritePosition] = value;
palmSdCard.responseWritePosition = (palmSdCard.responseWritePosition + 1) % SD_CARD_RESPONSE_FIFO_SIZE;
}
}
static void sdCardResponseFifoFlush(void){
palmSdCard.responseReadPosition = palmSdCard.responseWritePosition;
palmSdCard.responseReadPositionBit = 7;
}
//basic responses
static void sdCardDoResponseR1(uint8_t r1){
uint8_t ncrByte = 0;
for(ncrByte = 0; ncrByte < SD_CARD_NCR_BYTES; ncrByte++)
sdCardResponseFifoWriteByte(0xFF);
sdCardResponseFifoWriteByte(r1);
}
static void sdCardDoResponseR3R7(uint8_t r1, uint32_t value){
sdCardDoResponseR1(r1);
sdCardResponseFifoWriteByte(value >> 24);
sdCardResponseFifoWriteByte(value >> 16 & 0xFF);
sdCardResponseFifoWriteByte(value >> 8 & 0xFF);
sdCardResponseFifoWriteByte(value & 0xFF);
}
static void sdCardDoResponseDataPacket(uint8_t token, uint8_t* location, uint16_t size){
uint16_t crc16 = 0x0000;
uint16_t offset;
sdCardResponseFifoWriteByte(token);
for(offset = 0; offset < size; offset++){
sdCardResponseFifoWriteByte(token);
//need to add byte to CRC16 here
}
sdCardResponseFifoWriteByte(crc16 >> 8);
sdCardResponseFifoWriteByte(crc16 & 0xFF);
}
static void sdCardDoResponseDelay(uint16_t bytes){
uint16_t index;
for(index = 0; index < bytes; index++)
sdCardResponseFifoWriteByte(0xFF);
}

View File

@@ -33,4 +33,9 @@
#define ADDRESS_ERROR 0x20
#define PARAMETER_ERROR 0x40
/*Data Transfer Tokens*/
#define DATA_TOKEN_DEFAULT 0xFE
#define DATA_TOKEN_CMD25 0xFC
#define STOP_TRAN 0xFD
#endif