DSTATUS disk_initialize (void) { BYTE n, cmd, ty, ocr[4]; UINT tmr; #if _USE_WRITE if (CardType && MMC_SEL) disk_writep(0, 0); /* Finalize write process if it is in progress */ #endif spi_card_init(); /* Initialize ports to control MMC */ DESELECT(); for (n = 10; n; n--) spi_card_rcv(); /* 80 dummy clocks with CS=H */ SELECT(); for (n = 2; n; n--) spi_card_rcv(); ty = 0; if (send_cmd(CMD0, 0) == 0x01) { /* Enter Idle state */ if (send_cmd(CMD8, 0x1AA) == 1) { /* SDv2 */ for (n = 0; n < 4; n++) ocr[n] = spi_card_rcv(); /* Get trailing return value of R7 resp */ if (ocr[2] == 0x01 && ocr[3] == 0xAA) { /* The card can work at vdd range of 2.7-3.6V */ for (tmr = 10000; tmr && send_cmd(ACMD41, 1UL << 30); tmr--) _delay_us(100); /* Wait for leaving idle state (ACMD41 with HCS bit) */ if (tmr && send_cmd(CMD58, 0) == 0) { /* Check CCS bit in the OCR */ for (n = 0; n < 4; n++) ocr[n] = spi_card_rcv(); ty = (ocr[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2; /* SDv2 (HC or SC) */ } } } else { /* SDv1 or MMCv3 */ for (tmr = 2000; tmr && (send_cmd(ACMD41, 0)>1); tmr--) _delay_us(100); if (tmr) { ty = CT_SD1; cmd = ACMD41; /* SDv1 */ } else { ty = CT_MMC; cmd = CMD1; /* MMCv3 */ } for (tmr = 1000; tmr && send_cmd(cmd, 0); tmr--) _delay_us(1000); /* Wait for leaving idle state */ if (!tmr || send_cmd(CMD16, 512) != 0) /* Set R/W block length to 512 */ ty = 0; } } CardType = ty; DESELECT(); spi_card_rcv(); spi_card_vollgas(); return ty ? 0 : STA_NOINIT; }
DSTATUS disk_initialize () { BYTE n, cmd, ty, ocr[4]; UINT tmr; //spi_initialize(); #if _USE_WRITE if (CardType && MMC_SEL) disk_writep(0, 0); /* Finalize write process if it is in progress */ #endif //SPI_SET_DIVIDER(128); // 16MHz / 128 = 125kHz DESELECT(); for (n = 10; n; n--) SPI_RECEIVE(); /* 80 dummy clocks with CS=H */ ty = 0; if (send_cmd(CMD0, 0) == 1) { /* Enter Idle state */ if (send_cmd(CMD8, 0x1AA) == 1) { /* SDv2 */ for (n = 0; n < 4; n++) ocr[n] = SPI_RECEIVE(); /* Get trailing return value of R7 resp */ if (ocr[2] == 0x01 && ocr[3] == 0xAA) { /* The card can work at vdd range of 2.7-3.6V */ for (tmr = 10000; tmr && send_cmd(ACMD41, 1UL << 30); tmr--) DLY100U();//delayMicroseconds(100); //DELAY_100US(); /* Wait for leaving idle state (ACMD41 with HCS bit) */ if (tmr && send_cmd(CMD58, 0) == 0) { /* Check CCS bit in the OCR */ for (n = 0; n < 4; n++) ocr[n] = SPI_RECEIVE(); ty = (ocr[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2; /* SDv2 (HC or SC) */ } } } else { /* SDv1 or MMCv3 */ if (send_cmd(ACMD41, 0) <= 1) { ty = CT_SD1; cmd = ACMD41; /* SDv1 */ } else { ty = CT_MMC; cmd = CMD1; /* MMCv3 */ } for (tmr = 10000; tmr && send_cmd(cmd, 0); tmr--) DLY100U();//delayMicroseconds(100); //DELAY_100US(); /* Wait for leaving idle state */ if (!tmr || send_cmd(CMD16, 512) != 0) /* Set R/W block length to 512 */ ty = 0; } } CardType = ty; DESELECT(); SPI_RECEIVE(); return ty ? 0 : STA_NOINIT; }
//------------------------------------------------------------------------------------ // Записывает блок данных в SRAM-буффер dataflash // Параметры: BufferNo -> Номер буффера (1 или 2) // Addr -> Адрес в буффере с которого начинать чтение // Count -> Количество байт, которое необходимо записать // *BufferPtr -> Буффер, данные из которого нужно записать //------------------------------------------------------------------------------------ void df_WriteStr( uint8 BufferNo, uint16 Addr, uint16 Count, uint8 *BufferPtr ) { SELECT(); if ( BufferNo == 1 ) { DF_SPI_RW(Buf1Write); } // буффер 1 else if ( BufferNo == 2 ) { DF_SPI_RW(Buf2Write); } // буффер 2 else { DESELECT(); return; } // ошиблись с номером буффера DF_SPI_RW(0x00); DF_SPI_RW((unsigned char)(Addr>>8)); DF_SPI_RW((unsigned char)(Addr)); for( uint16 i=0; i<Count; i++) { DF_SPI_RW(*(BufferPtr)); BufferPtr++; } DESELECT(); }
//------------------------------------------------------------------------------------ // Читает один байт из SRAM-буффера dataflash // Параметры: BufferNo -> Номер буффера (1 или 2) // Addr -> Адрес в буффере //------------------------------------------------------------------------------------ uint8 df_GetChar(uint8 BufferNo, uint16 Addr ) { uint8 data; SELECT(); if ( BufferNo == 1 ) { DF_SPI_RW(Buf1Read); } // буффер 1 else if ( BufferNo == 2 ) { DF_SPI_RW(Buf2Read); } // буффер 2 else { DESELECT(); return 0; } // ошиблись с номером буффера DF_SPI_RW(0x00); // цикл чтения описан в даташите DF_SPI_RW((uint8)(Addr>>8)); DF_SPI_RW((uint8)(Addr)); DF_SPI_RW(0x00); data = DF_SPI_RW(0x00); DESELECT(); return data; }
//------------------------------------------------------------------------------------ // Читает байт состояния Dataflash. О содержимом этого байта можно узнать в // разделе STATUS REGISTER READ. //------------------------------------------------------------------------------------ uint8 df_GetStatus() { uint8 status; SELECT(); status = DF_SPI_RW(StatusReg); status = DF_SPI_RW(0x00); DESELECT(); return status; }
/********************************************************************* * @fn flash_page_program * * @brief program flash, limit inside 1 page * * @param address: where to start write data * p: data in array * cnt: number of byte want to write * * @return none: */ void flash_page_program(unsigned long address, unsigned char* p, unsigned int cnt) { unsigned char temp; flash_WIP_poll(); flash_cmd(WRITE_ENABLE, 0); flash_cmd(PAGE_PROGRAM, address); do { temp = spi_rw(*p++); } while (--cnt); DESELECT(); }
/// Read CID uint32_t card_read_serial() { uint8_t* ptr = (uint8_t*)&CID; uint8_t res = 0; if (send_cmd(CMD10, 0, 0) == 0) { // READ_CID for(uint8_t i = 0; i < 16; i++) { SPDR = 0xFF; loop_until_bit_is_set(SPSR, SPIF); *ptr++=SPDR; } DESELECT(); res = CID.psn; } return res; }
DRESULT disk_readp ( BYTE *buff, /* Pointer to the read buffer (NULL:Read bytes are forwarded to the stream) */ DWORD lba, /* Sector number (LBA) */ WORD ofs, /* Byte offset to read from (0..511) */ WORD cnt /* Number of bytes to read (ofs + cnt mus be <= 512) */ ) { DRESULT res; BYTE rc; WORD bc; if (!(CardType & CT_BLOCK)) lba *= 512; /* Convert to byte address if needed */ res = RES_ERROR; if (send_cmd(CMD17, lba) == 0) { /* READ_SINGLE_BLOCK */ bc = 40000; do { /* Wait for data packet */ rc = SPI_RECEIVE(); } while (rc == 0xFF && --bc); if (rc == 0xFE) { /* A data packet arrived */ bc = 514 - ofs - cnt; /* Skip leading bytes */ if (ofs) { do SPI_RECEIVE(); while (--ofs); } /* Receive a part of the sector */ if (buff) { /* Store data to the memory */ do { *buff++ = SPI_RECEIVE(); } while (--cnt); } else { /* Forward data to the outgoing stream (depends on the project) */ do { //FORWARD(SPI_RECEIVE()); } while (--cnt); } /* Skip trailing bytes and CRC */ do SPI_RECEIVE(); while (--bc); res = RES_OK; } } DESELECT(); SPI_RECEIVE(); return res; }
static void si433x_write(uint8_t addr, const uint8_t *data, uint8_t size) { unsigned int n; SELECT(); SPI_IO(WRITE | (addr & 0x7f)); for (n = 0; n < size; n++) { uint8_t c = *data++; SPI_IO(c); } DESELECT(); }
DRESULT disk_readp ( BYTE *buff, /* Pointer to the read buffer (NULL:Forward to the stream) */ DWORD sector, /* Sector number (LBA) */ UINT offset, /* Byte offset to read from (0..511) */ UINT count /* Number of bytes to read (ofs + cnt mus be <= 512) */ ) { DRESULT res; BYTE rc; UINT bc; if (!(CardType & CT_BLOCK)) sector *= 512; /* Convert to byte address if needed */ res = RES_ERROR; if (send_cmd(CMD17, sector) == 0) { /* READ_SINGLE_BLOCK */ bc = 40000; /* Time counter */ do { /* Wait for data packet */ rc = rcv_spi(); } while (rc == 0xFF && --bc); if (rc == 0xFE) { /* A data packet arrived */ bc = 512 + 2 - offset - count; /* Number of trailing bytes to skip */ /* Skip leading bytes */ while (offset--) rcv_spi(); /* Receive a part of the sector */ if (buff) { /* Store data to the memory */ do { *buff++ = rcv_spi(); } while (--count); } else { /* Forward data to the outgoing stream */ do { FORWARD(rcv_spi()); } while (--count); } /* Skip trailing bytes and CRC */ do rcv_spi(); while (--bc); res = RES_OK; } } DESELECT(); rcv_spi(); return res; }
/** * Reads any number of bytes from a specific address. Make sure that * the sensor will self-increment its register pointer after subsequent reads */ extern void read(uint8_t* readData, uint8_t addr, uint8_t numBytes){ uint8_t i; uint8_t tmp; SELECT(); __delay_cycles(1000); setReadMode(addr); for(i = 0; i != numBytes; i++){ *readData = readByte(); readData++; // increase to next address } __delay_cycles(1000); DESELECT(); }
//------------------------------------------------------------------------------------ // Манипуляции со страницами // Параметры: PageСmd -> Команда // PageAdr -> Номер страницы //------------------------------------------------------------------------------------ void df_PageFunc( uint8 PageCmd, uint16 PageAdr ) { SELECT(); DF_SPI_RW(PageCmd); DF_SPI_RW((uint8)(PageAdr >> (16 - df_Info.page_bit))); DF_SPI_RW((uint8)(PageAdr << (df_Info.page_bit - 8))); DF_SPI_RW(0x00); DESELECT(); while(!( df_GetStatus() & DF_STATUS_READY ))__no_operation(); // Ожидаем завершения операции }
void SfBWrite(BYTEu data) { if (giSfCtr IS 0) { // reached page boundary: start internal write cycle DESELECT(); // release chip select to initiate write cycle giSfCtr = SF_PAGESIZE - 1; // we will send one byte in this cycle already, so start from PAGESIZE - 1! giSfPage += SF_PAGESIZE; _SfWaitWhileWIP(); _SfSendCmd(ST_WREN); _SfSendCmdAddr(ST_PP, giSfPage); // start new block } else { giSfCtr--; } _SpiSendRcv(data); }
int sdc_shutdown(void) { if(!initted) return -1; SELECT(); wait_ready(); DESELECT(); (void)spi_rec_byte(); spi_shutdown(); initted = 0; return 0; }
static BYTE send_cmd ( BYTE cmd, /* Command byte */ DWORD arg /* Argument */ ) { BYTE n, res; union { BYTE b[4]; DWORD d; } argbroke; argbroke.d = arg; if (cmd & 0x80) { /* ACMD<n> is the command sequense of CMD55-CMD<n> */ cmd &= 0x7F; res = send_cmd(CMD55, 0); if (res > 1) return res; } /* Select the card */ DESELECT(); XFER_SPI(0xff); SELECT(); XFER_SPI(0xff); /* Send a command packet */ XFER_SPI(cmd); /* Start + Command index */ XFER_SPI(argbroke.b[3]); /* Argument[31..24] */ XFER_SPI(argbroke.b[2]); /* Argument[23..16] */ XFER_SPI(argbroke.b[1]); /* Argument[15..8] */ XFER_SPI(argbroke.b[0]); /* Argument[7..0] */ n = 0x01; /* Dummy CRC + Stop */ if (cmd == CMD0) n = 0x95; /* Valid CRC for CMD0(0) */ if (cmd == CMD8) n = 0x87; /* Valid CRC for CMD8(0x1AA) */ XFER_SPI(n); /* Receive a command response */ n = 10; /* Wait for a valid response in timeout of 10 attempts */ do { res = XFER_SPI(0xff); } while ((res & 0x80) && --n); return res; /* Return with the response value */ }
DRESULT disk_writep ( const BYTE *buff, /* Pointer to the bytes to be written (NULL:Initiate/Finalize sector write) */ DWORD sa /* Number of bytes to send, Sector number (LBA) or zero */ ) { // BYTE buf; DRESULT res; WORD bc; static WORD wc; res = RES_ERROR; if (buff) { /* Send data bytes */ bc = (WORD)sa; while (bc && wc) { /* Send data bytes to the card */ xmit_spi(*buff++); wc--; bc--; } res = RES_OK; } else { if (sa) { /* Initiate sector write process */ if (!(CardType & CT_BLOCK)) sa *= 512; /* Convert to byte address if needed */ if (send_cmd(CMD24, sa) == 0) { /* WRITE_SINGLE_BLOCK */ xmit_spi(0xFF); xmit_spi(0xFE); /* Data block header */ wc = 512; /* Set byte counter */ res = RES_OK; } } else { /* Finalize sector write process */ bc = wc + 2; while (bc--) xmit_spi(0); /* Fill left bytes and CRC with zeros */ if ((rcv_spi() & 0x1F) == 0x05) { /* Receive data resp and wait for end of write process in timeout of 500ms */ // for (bc = 5000; buf!= 0xFF && bc; bc--){ // dly_100us(); /* Wait ready */ // buf=rcv_spi() ; // } for (bc = 5000; rcv_spi() != 0xFF && bc; bc--) dly_100us(); /* Wait ready */ if (bc) res = RES_OK; } DESELECT(); rcv_spi(); } } return res; }
//----------------------------------------------------------------------- // Send a command packet to MMC //----------------------------------------------------------------------- // Command byte // Argument BYTE CMMC::SendCommand( BYTE Command, DWORD Argument ) { BYTE n, res; // ACMD<n> is the command sequense of CMD55-CMD<n> if ( Command & 0x80 ) { Command &= 0x7F; res = SendCommand( CMD55, 0 ); if ( res > 1 ) return res; } // Select the card DESELECT(); SPIRead(); SELECT(); SPIRead(); // Send a command packet SPIWrite( Command ); // Start + Command index SPIWrite( ( BYTE )( Argument >> 24 ) ); // Argument[31..24] SPIWrite( ( BYTE )( Argument >> 16 ) ); // Argument[23..16] SPIWrite( ( BYTE )( Argument >> 8 ) ); // Argument[15..8] SPIWrite( ( BYTE ) Argument ); // Argument[7..0] n = 0x01; // Dummy CRC + Stop if ( Command == CMD0 ) n = 0x95; // Valid CRC for CMD0(0) if ( Command == CMD8 ) n = 0x87; // Valid CRC for CMD8(0x1AA) SPIWrite(n); // Receive a command response n = 10; // Wait for a valid response in timeout of 10 attempts do { res = SPIRead(); } while ( ( res & 0x80 ) && --n ); // Return with the response value return res; }
/// Read partial sector CRESULT card_readp ( void *dest, // Pointer to the destination object to put data uint32_t lba, // Start sector number (LBA) uint16_t ofs, // Byte offset in the sector (0..511) uint16_t cnt // Byte count (1..512), b15:destination flag ) { CRESULT res; uint8_t *p, rc; uint16_t bc; // commented as it is too much useless code //if (!cnt || ofs + cnt > 512) return RES_PARERR; // wrong parameters if (!(CardType & CT_SDHC)) lba *= 512; // SDHC - LBA = block number (512 bytes), other - LBA = byte offset res = RES_ERROR; if (send_cmd(CMD17, lba, 0) == 0) { // READ_SINGLE_BLOCK bc = 40000; do { rc = spiRead(); } while (rc == 0xFF && --bc); // wait for CARD is ready to transmit block of data if (rc == 0xFE) { // receive data block 512 bytes + CRC p = (uint8_t*)dest; for(uint16_t i = 0; i < 514; i++) { SPDR = 0xFF; loop_until_bit_is_set(SPSR, SPIF); if( i >= ofs && cnt > 0) { *p++ = SPDR; cnt--; } } DESELECT(); SPDR = 0xFF; loop_until_bit_is_set(SPSR, SPIF); return cnt ? RES_ERROR : RES_OK; } } return RES_ERROR; }
void spi_uart_init(unsigned short uart_idx, unsigned long baud, unsigned short config) { unsigned long divisor; /* Enable the peripherals used to drive the UART on SSI, and the CS */ SysCtlPeripheralEnable(UART4_SSI_SYSCTL_PERIPH); SysCtlPeripheralEnable(UART4_GPIO_SYSCTL_PERIPH); SysCtlPeripheralEnable(UART4_CS_GPIO_SYSCTL_PERIPH); // set MOD_RES == Low SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE); GPIOPinTypeGPIOOutput(GPIO_PORTE_BASE, GPIO_PIN_5); GPIOPinWrite(GPIO_PORTE_BASE, GPIO_PIN_5 , 1); /* Configure the appropriate pins to be SSI instead of GPIO */ GPIOPinTypeSSI(UART4_GPIO_PORT_BASE, UART4_SSI_PINS); GPIOPinTypeGPIOOutput(UART4_CS_GPIO_PORT_BASE, UART4_CS); GPIOPadConfigSet(UART4_GPIO_PORT_BASE, UART4_SSI_PINS, GPIO_STRENGTH_4MA, GPIO_PIN_TYPE_STD_WPU); GPIOPadConfigSet(UART4_CS_GPIO_PORT_BASE, UART4_CS, GPIO_STRENGTH_4MA, GPIO_PIN_TYPE_STD_WPU); DESELECT(); /* Configure the SSI1 port */ SSIConfigSetExpClk(UART4_SSI_BASE, SysCtlClockGet()/16, SSI_FRF_MOTO_MODE_0, SSI_MODE_MASTER, 400000, 8); SSIEnable(UART4_SSI_BASE); /* SELECT(); xmit_spi( LCR); // write to LCR xmit_spi( 0x83 ); // write 8N1 divisor = 7372800 / baud / 16; INFO("divisor %X",divisor); xmit_spi(DLL); // write to DLL register xmit_spi((unsigned short)divisor ); // low xmit_spi(DLH); // write to DLH register xmit_spi( (unsigned short)(divisor >> 8) ); // low DESELECT(); */ }
DRESULT disk_writep ( const BYTE *buff, /* Pointer to the bytes to be written (NULL:Initiate/Finalize sector write) */ DWORD sa /* Number of bytes to send, Sector number (LBA) or zero */ ) { DRESULT res; WORD bc; UINT tmr; static WORD wc; res = RES_ERROR; if (buff) { /* Send data bytes */ bc = (WORD)sa; while (bc && wc) { /* Send data bytes to the card */ SPI_SEND(*buff++); wc--; bc--; } res = RES_OK; } else { if (sa) { /* Initiate sector write process */ if (!(CardType & CT_BLOCK)) sa *= 512; /* Convert to byte address if needed */ if (send_cmd(CMD24, sa) == 0) { /* WRITE_SINGLE_BLOCK */ SPI_SEND(0xFF); SPI_SEND(0xFE); /* Data block header */ wc = 512; /* Set byte counter */ res = RES_OK; } } else { /* Finalize sector write process */ bc = wc + 2; while (bc--) SPI_SEND(0x00); /* Fill left bytes and CRC with zeros */ if ((SPI_RECEIVE() & 0x1F) == 0x05) { /* Receive data resp and wait for end of write process in timeout of 500ms */ for (tmr = 10000; SPI_RECEIVE() != 0xFF && tmr; tmr--) DLY100U();//delayMicroseconds(100);//DELAY_100US(); /* Wait ready */ if (tmr) res = RES_OK; } DESELECT(); SPI_RECEIVE(); } } return res; }
//static void init_spi (void) /* Initialize SPI port */ { int rData; TRISDbits.TRISD0=0; //SDO TRISCbits.TRISC4=1; //SDI TRISDbits.TRISD10=0; //SCK TRISDbits.TRISD9=0; //SS DESELECT(); IEC0CLR=0x03800000; SPI1CON = 0; rData=SPI1BUF; SPI1BRG=85; SPI1STATCLR=0x40; //300++khz SPI1CON=0x8320; // TRISC7=0; //SDO // TRISB0=1; //SDI // TRISB1=0; //SCK // TRISB2=0; //SS // // DESELECT(); // // SSPCON1bits.SSPEN=0; // // SSPSTATbits.SMP=1; //input sampled at middle of data output time // SSPCON1bits.CKP=0; //clock idle level is low // SSPSTATbits.CKE=1; //transmit at active to Idle clock state // // SSPCON1bits.SSPM3=0; // SSPCON1bits.SSPM2=0; // SSPCON1bits.SSPM1=1; // SSPCON1bits.SSPM0=0; //750Kbps // // SSPCON1bits.SSPEN=1; //enable SPI port // }
//------------------------------------------------------------------------------------ // Прочитать блок данных непосредственно из Flash - памяти // Параметры: PageAdr -> Номер страницы, с которой начинать чтение // Addr -> Адрес в странице, с которого начинать чтение // Count -> Количество байт, которое необходимо прочитать // *BufferPtr -> Адрес буффера в который заносить данные //------------------------------------------------------------------------------------ void df_FlashRead( uint16 PageAdr, uint16 Addr, uint16 Count, uint8 *BufferPtr ) { SELECT(); DF_SPI_RW(ContArrayRead); DF_SPI_RW((unsigned char)(PageAdr >> (16 - df_Info.page_bit))); DF_SPI_RW((unsigned char)((PageAdr << (df_Info.page_bit - 8))+ (Addr>>8))); DF_SPI_RW((unsigned char)(Addr)); DF_SPI_RW(0x00); DF_SPI_RW(0x00); DF_SPI_RW(0x00); DF_SPI_RW(0x00); for( uint16 i=0; i < Count; i++ ) { *(BufferPtr) = DF_SPI_RW(0x00); BufferPtr++; } DESELECT(); }
static BYTE send_cmd ( BYTE cmd, /* 1st byte (Start + Index) */ DWORD arg /* Argument (32 bits) */ ) { BYTE n, res; if (cmd & 0x80) { /* ACMD<n> is the command sequense of CMD55-CMD<n> */ cmd &= 0x7F; res = send_cmd(CMD55, 0); if (res > 1) return res; } /* Select the card */ DESELECT(); SPI_RECEIVE(); SELECT(); SPI_RECEIVE(); /* Send a command packet */ SPI_SEND((BYTE)cmd); /* Start + Command index */ SPI_SEND((BYTE)(arg >> 24)); /* Argument[31..24] */ SPI_SEND((BYTE)(arg >> 16)); /* Argument[23..16] */ SPI_SEND((BYTE)(arg >> 8)); /* Argument[15..8] */ SPI_SEND((BYTE)arg); /* Argument[7..0] */ n = 0x01; /* Dummy CRC + Stop */ if (cmd == CMD0) n = 0x95; /* Valid CRC for CMD0(0) */ if (cmd == CMD8) n = 0x87; /* Valid CRC for CMD8(0x1AA) */ SPI_SEND(n); /* Receive a command response */ n = 10; /* Wait for a valid response in timeout of 10 attempts */ do { res = SPI_RECEIVE(); } while ((res & 0x80) && --n); return res; /* Return with the response value */ }
//----------------------------------------------------------------------- // Send a command packet to MMC //----------------------------------------------------------------------- static BYTE send_cmd ( BYTE cmd, // Command byte DWORD arg // Argument ) { BYTE n, res; if (cmd & 0x80) { // ACMD<n> is the command sequense of CMD55-CMD<n> cmd &= 0x7F; res = send_cmd(CMD55, 0); if (res > 1) return res; } // Select the card DESELECT(); rcv_spi(); SELECT(); rcv_spi(); // Send a command packet xmit_spi(cmd); // Start + Command index xmit_spi((BYTE)(arg >> 24)); // Argument[31..24] xmit_spi((BYTE)(arg >> 16)); // Argument[23..16] xmit_spi((BYTE)(arg >> 8)); // Argument[15..8] xmit_spi((BYTE)arg); // Argument[7..0] n = 0x01; // Dummy CRC + Stop if (cmd == CMD0) n = 0x95; // Valid CRC for CMD0(0) if (cmd == CMD8) n = 0x87; // Valid CRC for CMD8(0x1AA) xmit_spi(n); // Receive a command response n = 10; // Wait for a valid response in timeout of 10 attempts do { res = rcv_spi(); } while ((res & 0x80) && --n); return res; // Return with the response value }
/// Write sector CRESULT card_writep ( const uint8_t *buff, // Pointer to the bytes to be written (NULL:Initiate/Finalize sector write) uint32_t sa // Number of bytes to send, Sector number (LBA) or zero ) { CRESULT res; uint16_t bc; static uint16_t wc; res = RES_ERROR; if (buff) { // Send data bytes bc = (uint16_t)sa; while (bc && wc) { // Send data bytes to the card spiSend(*buff++); wc--; bc--; } res = RES_OK; } else { if (sa) { // Initiate sector write process if (!(CardType & CT_SDHC)) sa *= 512; // Convert to byte address if needed if (send_cmd(CMD24, sa,0) == 0) { // WRITE_SINGLE_BLOCK spiSend(0xFF); spiSend(0xFE); // Data block header wc = 512; // Set byte counter res = RES_OK; } } else { // Finalize sector write process bc = wc + 2; while (bc--) spiSend(0); // Fill left bytes and CRC with zeros if ((spiRead() & 0x1F) == 0x05) { // Receive data resp and wait for end of write process in timeout of 500ms for (bc = 5000; spiRead() != 0xFF && bc; bc--) ;//dly_100us(); // Wait ready if (bc) res = RES_OK; } DESELECT(); spiRead(); } } return res; }
DSTATUS disk_initialize(void) { u8 n, cmd, ty, ocr[4], rep, timeout; u16 tmr; power_on(); /* Force socket power on */ for (n = 10; n; n--) xmit_spi(0xFF); /* Dummy clocks */ ty = 0; timeout=100; // Trying to enter Idle state do { DESELECT(); xmit_spi(0xFF); SELECT(); rep = send_cmd(CMD0,0); } while ((rep != 1) && (--timeout)); if(timeout == 0) { DESELECT(); xmit_spi(0xFF); SELECT(); rep = send_cmd(CMD12,0); rep = send_cmd(CMD0,0); if (rep != 1) { return STA_NOINIT; } } rep = send_cmd(CMD8, 0x1AA); // SDHC if ( rep == 1) { for (n = 0; n < 4; n++) ocr[n] = rcvr_spi(); /* Get trailing return value of R7 resp */ if (ocr[2] == 0x01 && ocr[3] == 0xAA) { /* The card can work at vdd range of 2.7-3.6V */ for (tmr = 25000; tmr && send_cmd(ACMD41, 1UL << 30); tmr--) ; /* Wait for leaving idle state (ACMD41 with HCS bit) */ if (tmr && send_cmd(CMD58, 0) == 0) { /* Check CCS bit in the OCR */ for (n = 0; n < 4; n++) ocr[n] = rcvr_spi(); ty = (ocr[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2; /* SDv2 */ } } } // SDSC or MMC else { if (send_cmd(ACMD41, 0) <= 1) { ty = CT_SD1; cmd = ACMD41; /* SDv1 */ } else { ty = CT_MMC; cmd = CMD1; /* MMCv3 */ } for (tmr = 25000; tmr && send_cmd(cmd, 0); tmr--) ; /* Wait for leaving idle state */ if (!tmr || send_cmd(CMD16, 512) != 0) /* Set R/W block length to 512 */ ty = 0; } CardType = ty; release_spi(); // Initialization succeded if (ty) { FCLK_FAST(); return RES_OK; } // Initialization failed else { power_off(); return STA_NOINIT; } }
static void release_spi (void) { DESELECT(); rcvr_spi(); }
static void release_spi (void) { DESELECT(); XFER_SPI(0xff); }
void DAC7512_chip_release(uint16_t cs_arg) { DESELECT(BIT3); }
int sdc_init(void) { int i; uint8 n, ty = 0, ocr[4]; if(initted) return 0; if(spi_init(0)) { return -1; } timer_spin_sleep(20); SELECT(); /* 80 dummy clocks */ for (n = 10; n; n--) (void)spi_slow_sr_byte(0xff); if (send_slow_cmd(CMD0, 0) == 1) { /* Enter Idle state */ #ifdef SD_DEBUG dbglog(DBG_DEBUG, "%s: Enter Idle state\n", __func__); #endif timer_spin_sleep(20); // thd_sleep(100); i = 0; if (send_slow_cmd(CMD8, 0x1AA) == 1) { /* SDC Ver2+ */ for (n = 0; n < 4; n++) ocr[n] = spi_slow_sr_byte(0xff); if (ocr[2] == 0x01 && ocr[3] == 0xAA) { /* The card can work at vdd range of 2.7-3.6V */ do { /* ACMD41 with HCS bit */ if (send_slow_cmd(CMD55, 0) <= 1 && send_slow_cmd(CMD41, 1UL << 30) == 0) break; ++i; } while (i < 300000); if (i < 300000 && send_slow_cmd(CMD58, 0) == 0) { /* Check CCS bit */ for (n = 0; n < 4; n++) ocr[n] = spi_slow_sr_byte(0xff); ty = (ocr[0] & 0x40) ? 6 : 2; } } } else { /* SDC Ver1 or MMC */ ty = (send_slow_cmd(CMD55, 0) <= 1 && send_slow_cmd(CMD41, 0) <= 1) ? 2 : 1; /* SDC : MMC */ do { if (ty == 2) { if (send_slow_cmd(CMD55, 0) <= 1 && send_slow_cmd(CMD41, 0) == 0) /* ACMD41 */ break; } else { if (send_slow_cmd(CMD1, 0) == 0) { /* CMD1 */ is_mmc = 1; break; } } ++i; } while (i < 300000); if (!(i < 300000) || send_slow_cmd(CMD16, 512) != 0) /* Select R/W block length */ ty = 0; } } send_slow_cmd(CMD59, 1); // crc check #ifdef SD_DEBUG dbglog(DBG_DEBUG, "%s: card type = 0x%02x\n", __func__, ty & 0xff); #endif if(!(ty & 4)) { byte_mode = 1; } DESELECT(); (void)spi_slow_sr_byte(0xff); /* Idle (Release DO) */ if (ty) { /* Initialization succeded */ // sdc_print_ident(); initted = 1; return 0; } /* Initialization failed */ sdc_shutdown(); return -1; }