/** Perform MMC block write from diskSect */ unsigned char WritePhysicalSector() { unsigned char c; //RED_LED = LED_ON; sectorAddress.l = sectorAddress.l * 2; //convert to bytes (combined with 8bit shift) c=MmcCommand(0x40 | 24, sectorAddress.b.b2, sectorAddress.b.b1, sectorAddress.b.b0, 0); sectorAddress.l = sectorAddress.l >> 1; //convert back to blocks //ConsolePutChar('w'); //ConsolePutHex8(c); if (c!=0x00) return (c); //Error - MMC did not go to write mode /* while (c!=0x00) { //wait for BUSY token, if you get 0x01(idle), it's an ERROR! c = SPIGetChar(); ConsolePutHex8(c); } */ dataBufPtr = diskSect.raw.buf; SPIPutCharWithoutWaiting(0xFE); SPIWait(); for (c=0;c<128;c++){ SPIPutCharWithoutWaiting(*dataBufPtr++); SPIWait(); SPIPutCharWithoutWaiting(*dataBufPtr++); SPIWait(); SPIPutCharWithoutWaiting(*dataBufPtr++); SPIWait(); SPIPutCharWithoutWaiting(*dataBufPtr++); SPIWait(); } //ConsolePutChar('-'); c = SPIGetChar(); //crc 1st byte (sends 0xff) c = SPIGetChar(); //crc 2nd byte (sends 0xff) c = SPIGetChar(); //ConsolePutHex8(c); //This prints xxx00101, (usually e5) when data ok // while (SPIGetChar()!=0xff) //busy wait moved to mmcCommand // ; // Wait until MMC not busy. SPI8Clocks(16); DeselectMSD(); SPI8Clocks(16); RED_LED_OFF(); return 0; }
void SPIShiftIn_sector (const uint8_t addr[], const uint8_t blocking) { SPIWait(); g_mailbox = SPI_FUNC_READ_SECTOR; SPIWait(); g_mailbox = (uint32_t) addr; if (blocking) SPIWait(); }
// Function definitions uint8_t SPIStart (const uint32_t mosi, const uint32_t miso, const uint32_t sclk, const uint32_t frequency, const spimode_t mode, const spibitmode_t bitmode) { uint8_t err; const char str[11] = "SPIStart()"; #ifdef SPI_DEBUG_PARAMS // Ensure all pin-mask parameters have exactly 1 set bit if (1 != PropWareCountBits(mosi)) SPIError(SPI_INVALID_PIN_MASK); if (1 != PropWareCountBits(miso)) SPIError(SPI_INVALID_PIN_MASK); if (1 != PropWareCountBits(sclk)) SPIError(SPI_INVALID_PIN_MASK); // Check clock frequency if (SPI_MAX_CLOCK <= frequency) SPIError(SPI_INVALID_FREQ); if (SPI_MODES <= mode) SPIError(SPI_INVALID_MODE); if (SPI_LSB_FIRST != bitmode && SPI_MSB_FIRST != bitmode) SPIError(SPI_INVALID_BITMODE); #endif // If cog already started, do not start another if (!SPIIsRunning()) { // Start GAS cog // Set the mailbox to 0 (anything other than -1) so that we know when // the SPI cog has started g_mailbox = 0; g_spiCog = _SPIStartCog((void *) &g_mailbox); if (!SPIIsRunning()) SPIError(SPI_COG_NOT_STARTED); // Pass in all parameters PROPWARE_SPI_SAFETY_CHECK_STR(SPIWait(), str); g_mailbox = mosi; PROPWARE_SPI_SAFETY_CHECK_STR(SPIWait(), str); g_mailbox = PropWareGetPinNum(mosi); PROPWARE_SPI_SAFETY_CHECK_STR(SPIWait(), str); g_mailbox = miso; PROPWARE_SPI_SAFETY_CHECK_STR(SPIWait(), str); g_mailbox = PropWareGetPinNum(miso); PROPWARE_SPI_SAFETY_CHECK_STR(SPIWait(), str); g_mailbox = sclk; } PROPWARE_SPI_SAFETY_CHECK_STR(SPISetMode(mode), str); PROPWARE_SPI_SAFETY_CHECK_STR(SPISetBitMode(bitmode), str); PROPWARE_SPI_SAFETY_CHECK_STR(SPISetClock(frequency), str); return 0; }
void SPIShiftOut_fast (uint8_t bits, uint32_t value) { // NOTE: No debugging within this function to allow for fastest possible // execution time // Wait to ensure the SPI cog is in its idle state SPIWait(); // Call GAS function g_mailbox = SPI_FUNC_SEND_FAST | (bits << SPI_BITS_OFFSET); SPIWait(); // Pass parameter in; Bit 31 is cleared to indicate data is being sent. Without this limitation, who's to say the value being passed is not -1? g_mailbox = value & (~BIT_31); }
uint8_t SPIShiftIn (const uint8_t bits, void *data, const size_t bytes) { uint8_t err; const char str[13] = "SPIShiftIn()"; // Check for errors #ifdef SPI_DEBUG_PARAMS if (!SPIIsRunning()) SPIError(SPI_MODULE_NOT_RUNNING); if (SPI_MAX_PAR_BITS < bits) SPIError(SPI_TOO_MANY_BITS); if ((4 == bytes && ((uint32_t) data) % 4) || (2 == bytes && ((uint32_t) data) % 2)) SPIError(SPI_ADDR_MISALIGN); #endif // Ensure SPI module is not busy PROPWARE_SPI_SAFETY_CHECK_STR(SPIWait(), str); // Call GAS function g_mailbox = SPI_FUNC_READ | (bits << SPI_BITS_OFFSET); // Read in parameter PROPWARE_SPI_SAFETY_CHECK_STR(SPIReadPar(data, bytes), str); return 0; }
uint8_t SPIShiftOut (uint8_t bits, uint32_t value) { uint8_t err; char str[14] = "SPIShiftOut()"; #ifdef SPI_DEBUG_PARAMS // Check for errors if (!SPIIsRunning()) SPIError(SPI_MODULE_NOT_RUNNING); if (SPI_MAX_PAR_BITS < bits) SPIError(SPI_TOO_MANY_BITS); #endif // Wait to ensure the SPI cog is in its idle state PROPWARE_SPI_SAFETY_CHECK_STR(SPIWait(), str); // Call GAS function g_mailbox = SPI_FUNC_SEND | (bits << SPI_BITS_OFFSET); PROPWARE_SPI_SAFETY_CHECK_STR( SPIWaitSpecific(SPI_FUNC_SEND | (bits << SPI_BITS_OFFSET)), str); // Pass parameter in; Bit 31 is cleared to indicate data is being sent. Without this limitation, who's to say the value being passed is not -1? g_mailbox = value & (~BIT_31); return 0; }
unsigned char SPIGetChar() { unsigned char data = 0; SPDR =0xFF; SPIWait(); data = SPDR; return data; }
uint8_t SPISetBitMode (const uint8_t bitmode) { uint8_t err; char str[16] = "SPISetBitMode()"; if (!SPIIsRunning()) SPIError(SPI_MODULE_NOT_RUNNING); #ifdef SPI_DEBUG_PARAMS if (SPI_LSB_FIRST != bitmode && SPI_MSB_FIRST != bitmode) SPIError(SPI_INVALID_BITMODE); #endif PROPWARE_SPI_SAFETY_CHECK_STR(SPIWait(), str); g_mailbox = SPI_FUNC_SET_BITMODE; PROPWARE_SPI_SAFETY_CHECK_STR(SPIWait(), str); g_mailbox = bitmode; return 0; }
uint8_t SPISetMode (const uint8_t mode) { uint8_t err; char str[14] = "SPISetMode()"; if (!SPIIsRunning()) SPIError(SPI_MODULE_NOT_RUNNING); #ifdef SPI_DEBUG_PARAMS if (SPI_MODES <= mode) SPIError(SPI_INVALID_MODE); #endif // Wait for SPI cog to go idle PROPWARE_SPI_SAFETY_CHECK_STR(SPIWait(), str); g_mailbox = SPI_FUNC_SET_MODE; PROPWARE_SPI_SAFETY_CHECK_STR(SPIWait(), str); g_mailbox = mode; return 0; }
void SPIShiftIn_fast (const uint8_t bits, void *data, const uint8_t bytes) { uint8_t *par8; uint16_t *par16; uint32_t *par32; // Wait until idle state, then send function and mode bits SPIWait(); g_mailbox = SPI_FUNC_READ_FAST | (bits << SPI_BITS_OFFSET); // Wait for a value to be written while ((uint32_t) -1 == g_mailbox) waitcnt(SPI_TIMEOUT_WIGGLE_ROOM + CNT); // Determine if output variable is char, short or long and write data to that location switch (bytes) { case 1: par8 = data; *par8 = g_mailbox; break; case 2: par16 = data; *par16 = g_mailbox; break; case 4: par32 = data; *par32 = g_mailbox; break; default: #ifdef SPI_DEBUG SPIError(SPI_INVALID_BYTE_SIZE); #else return; #endif break; } // Signal that value is saved and GAS cog can continue execution g_mailbox = -1; }
uint8_t SPIGetClock (uint32_t *frequency) { uint8_t err; char str[14] = "SPIGetClock()"; #ifdef SPI_DEBUG_PARAMS // Check for errors if (!SPIIsRunning()) SPIError(SPI_MODULE_NOT_RUNNING); #endif // Wait to ensure the SPI cog is in its idle state PROPWARE_SPI_SAFETY_CHECK_STR(SPIWait(), str); // Call GAS function g_mailbox = SPI_FUNC_GET_FREQ; PROPWARE_SPI_SAFETY_CHECK_STR(SPIWaitSpecific(SPI_FUNC_GET_FREQ), str); SPIReadPar(frequency, sizeof(*frequency)); *frequency = CLKFREQ / *frequency; return 0; }
uint8_t SPISetClock (const uint32_t frequency) { uint8_t err; char str[14] = "SPISetClock()"; if (!SPIIsRunning()) SPIError(SPI_MODULE_NOT_RUNNING); #ifdef SPI_DEBUG_PARAMS if (SPI_MAX_CLOCK <= frequency) SPIError(SPI_INVALID_FREQ); #endif // Wait for SPI cog to go idle PROPWARE_SPI_SAFETY_CHECK_STR(SPIWait(), str); // Prepare cog for clock frequency change g_mailbox = SPI_FUNC_SET_FREQ; // Wait for the ready command PROPWARE_SPI_SAFETY_CHECK_STR(SPIWaitSpecific(SPI_FUNC_SET_FREQ), str); // Send new frequency g_mailbox = CLKFREQ / frequency; return 0; }
/** Do one MMC command and return the MMC SPI R1 response. * Returns 0xff in case of timeout (relies on weak pull-up on the MISO pin). * Note that the parameter bytes are * used for temporary storage after they are written out. */ unsigned char MmcCommand(unsigned char c1, unsigned char c2, unsigned char c3, unsigned char c4, unsigned char c5){ volatile unsigned int i; volatile unsigned char temp; /* Note: c1, c2 are used for temporary variables after use! */ // Provide clock edges before and after asserting MMC CS DeselectMSD(); SPI8Clocks(8); SelectMSD(); //while(1) SPI8Clocks(8); i=0; // If card still seems to be busy, give it some time... // changed 12/2005 to give quite a lot of time. //while ((temp = MMC_ReadByte() !=0xff) && (++i<20000)); do { SPDR =0xFF; SPIWait(); temp = SPDR; //temp = MMC_ReadByte(); ++i; }while(temp != 0xff && i<2000); //read agin to ensure MISO == 0xFF, this is very important //while ((temp = MMC_ReadByte() !=0xff) && (++i<20000)); do { SPDR =0xFF; SPIWait(); temp = SPDR; //temp = MMC_ReadByte(); ++i; }while(temp != 0xff && i<2000); //read agin to ensure MISO == 0xFF , this is very important //while ((temp = MMC_ReadByte() !=0xff) && (++i<20000)); do { SPDR =0xFF; SPIWait(); temp = SPDR; //temp = MMC_ReadByte(); ++i; }while(temp != 0xff && i<2000); //Serial.println("test 1"); // The bus should be stable high now /// if ((i=SPI_RESULT_BYTE) != 0xff){ //temp = MMC_ReadByte(); SPDR =0xFF; SPIWait(); temp = SPDR; if ( temp != 0xff){ //Serial.print("\r\nUnexpected busy signal from MMC. "); //Serial.print(i,HEX); //Serial.print("\r\nGet data = "); //Serial.print(temp,HEX); DeselectMSD(); //DelayMs(1000); return 0x81; //MMC unexpectedly Busy } // Send the MMC command /*MSPIPutCharWithoutWaiting(c1); MMC_WriteByte(c2); MMC_WriteByte(c3); MMC_WriteByte(c4); MMC_WriteByte(c5); MMC_WriteByte(0x95); // Valid CRC for init, then don't care MSPIWait();*/ SPDR =c1; SPIWait(); SPDR =c2; SPIWait(); SPDR =c3; SPIWait(); SPDR =c4; SPIWait(); SPDR =c5; SPIWait(); SPDR =0x95; SPIWait(); //delay(100); /* Now ok to use c1..c5 as temporaries (dirty but kool) */ { i=100; do { SPDR =0xFF; SPIWait(); temp = SPDR; //temp = MMC_ReadByte(); i--; }while((i--)&&(temp&0x80)); //while((i--)&&((temp=MMC_ReadByte())&0x80)); //wait for R1 or timeout } return temp; //return the R1 response }