//Write MMC/SD sector int mmc_writesector(uint32_t lba, uint8_t *buffer) { uint16_t i; // send write command and logical sector address mmc_send_command(24,(lba>>7) & 0xffff, (lba<<9) & 0xffff); spi_byte(0xfe); //Send data token for (i=0;i<512;i++) //Send sector data spi_byte(*buffer++); spi_byte(0xff); //Send dummy 16-bit checksum spi_byte(0xff); if ((mmc_get() & 0x0f) != 0x05) { //Receive response token mmc_clock_and_release(); return -1; //Write error } while (spi_byte(0xff) == 0x00) { //Wait for the card to finish writing, this can take //a very long time, i.e. several hundred milliseconds } mmc_clock_and_release(); //Cleanup return 0; //Return success }
/*************************************************************************** Declaration : void write_rf_reg(char address,char data_byte) Description : Writes one byte of data to the RF register address ***************************************************************************/ void write_rf_reg(char address,char data_byte) { ENABLE_RF_SPI; spi_byte(W_REG|address); spi_byte(data_byte); DISABLE_RF_SPI; }
void nrf_cmd(uint8_t cmd, uint8_t data) { cbi(NRF_PORT, PIN_nCS); spi_byte(cmd); spi_byte(data); sbi(NRF_PORT, PIN_nCS); //Deselect chip }
/** Init MMC/SD card. Initialize I/O ports for the MMC/SD interface and send init commands to the MMC/SD card \return 0 on success, other values on error */ uint8_t mmc_init(void) { //Run configure_spi() to setup the SPI port before initializing MMC. int i; for(i=0;i<10;i++) // send 8 clocks while card power stabilizes spi_byte(0xff); mmc_send_command(0,0,0); // send CMD0 - reset card if (mmc_get() != 1) // if no valid response code { mmc_clock_and_release(); return 1; // card cannot be detected } // // send CMD1 until we get a 0 back, indicating card is done initializing // i = 0xffff; // max timeout while ((spi_byte(0xff) != 0) && (--i)) // wait for it { mmc_send_command(1,0,0); // send CMD1 - activate card init } mmc_clock_and_release(); // clean up if (i == 0) // if we timed out above return 2; // return failure code return 0; }
// ***************************************************************************** // @fn spi_string // @brief Write a string through SPI // @param unsigned char* TxData String to send // @param unsigned char* RxData Reception buffer // @param unsigned int length Length of the string // @return none // ***************************************************************************** void spi_string(unsigned char* TxData, unsigned char* RxData, unsigned int length) { uint16_t i = 0; if( RxData != NULL && TxData != NULL ) // two way transmition { while( i < length ) { RxData[i] = spi_byte( TxData[i] ); i++; } } else if( RxData == NULL && TxData != NULL ) // send only { while( i < length ) { spi_byte( TxData[i] ); i++; } } else if( RxData != NULL && TxData == NULL ) // recieve only { while( i < length ) { RxData[i] = spi_byte( 0 ); i++; } } }
// ***************************************************************************** // @fn spi_string // @brief Write a string through SPI // @param unsigned char* TxData String to send // @param unsigned char* RxData Reception buffer // @param unsigned int length Length of the string // @return none // ***************************************************************************** void spi_string(unsigned char* TxData, unsigned char* RxData, unsigned int length) { #ifdef SPI_USE_DMA spiDmaTransfer( (uint8_t*) TxData, (uint8_t*) RxData, length ); sleepUntilDmaDone(); #else uint16_t i = 0; if( RxData != NULL && TxData != NULL ) // two way transmition { while( i < length ) { RxData[i] = spi_byte( TxData[i] ); i++; } } else if( RxData == NULL && TxData != NULL ) // send only { while( i < length ) { spi_byte( TxData[i] ); i++; } } else if( RxData != NULL && TxData == NULL ) // recieve only { while( i < length ) { RxData[i] = spi_byte( 0 ); i++; } } #endif }
static void busy_wait() { spi_start_transaction(IO_SPI_FLASH); spi_byte(IO_SPI_FLASH, SPI_CMD_RDSR); do {} while (spi_byte(IO_SPI_FLASH, SPI_CMD_RDSR) & 1); }
void nrf_cmd(uint8_t cmd, uint8_t data) { RF1_WriteRegister(cmd, data); #if 0 cbi(PORTB, PIN_nCS); spi_byte(cmd); spi_byte(data); sbi(PORTB, PIN_nCS); //Deselect chip #endif }
/** * Send dummys * * Send 10 dummy bytes to card * */ void sd_send_dummys(void) { uint8_t i; for(i=0; i < 9; i++) spi_byte(0xff,0); spi_byte(0xff,1); }
/*************************************************************************** Declaration : void write_rf_data(char inst,char *data_ptr,char nbr_of_bytes) Description : Writes the instruction and the number of bytes of data. ***************************************************************************/ void write_rf_data(char inst,char *data_ptr,char nbr_of_bytes) { int i; ENABLE_RF_SPI; spi_byte(inst); for(i=0; i<nbr_of_bytes;i++) spi_byte(*data_ptr++); DISABLE_RF_SPI; }
static void flash_erase_sectors(int start, int cnt) { int addr, sum, i; addr = start * (FLASH_BLOCKLEN / 256); for (; cnt > 0; cnt--, addr += (FLASH_BLOCKLEN / 256)) { /* Skip already blank sectors */ spi_start_transaction(IO_SPI_FLASH); spi_byte(IO_SPI_FLASH, SPI_CMD_FASTRD); spi_byte(IO_SPI_FLASH, addr >> 8); spi_byte(IO_SPI_FLASH, addr); spi_byte(IO_SPI_FLASH, 0); spi_byte(IO_SPI_FLASH, 0); /* dummy byte, ignored */ for (i = 0, sum = 0xff; i < FLASH_BLOCKLEN; i++) sum &= spi_byte(IO_SPI_FLASH, 0); if (sum == 0xff) continue; /* Write enable */ spi_start_transaction(IO_SPI_FLASH); spi_byte(IO_SPI_FLASH, SPI_CMD_WREN); spi_start_transaction(IO_SPI_FLASH); spi_byte(IO_SPI_FLASH, SPI_CMD_ERSEC); spi_byte(IO_SPI_FLASH, addr >> 8); spi_byte(IO_SPI_FLASH, addr); spi_byte(IO_SPI_FLASH, 0); busy_wait(); } }
static void flash_read_block(char *buf, uint32_t addr, uint32_t len) { spi_start_transaction(IO_SPI_FLASH); spi_byte(IO_SPI_FLASH, 0x0b); /* High-speed read */ spi_byte(IO_SPI_FLASH, addr >> 16); spi_byte(IO_SPI_FLASH, addr >> 8); spi_byte(IO_SPI_FLASH, addr); spi_byte(IO_SPI_FLASH, 0xff); /* dummy byte, ignored */ spi_block_in(IO_SPI_FLASH, buf, len); }
void accel_reg_write16(uint8_t reg, uint16_t value) { #if 1 spi_byte(0, ACCEL_REG_WRITE | ACCEL_REG_MULTI | (reg & ACCEL_REG_MASK), 0); spi_byte(0, value & 0xff, 0); spi_byte(0, (value >> 8) & 0xff, 1); #else spi_byte(0, (reg & ACCEL_REG_MASK), 0); spi_byte(0, value & 0xff, 1); spi_byte(0, ((reg + 1) & ACCEL_REG_MASK), 0); spi_byte(0, (value >> 8) & 0xff, 1); #endif }
/* Initialize a mmc/sd card */ uint8_t mmc_init(void) { int i; // setup I/O ports PORTB &= ~((1 << MMC_SCK) | (1 << MMC_MOSI)); PORTB |= (1 << MMC_MISO); DDRB |= (1<<MMC_SCK) | (1<<MMC_MOSI); PORTB |= (1 << MMC_CS); DDRB |= (1 << MMC_CS); SPCR = (1<<MSTR)|(1<<SPE)|2; // enable SPI interface SPSR = 0; // set/disable double speed for(i=0;i<10;i++) // send 80 clocks spi_byte(0xff); mmc_send_command(GO_IDLE_STATE,0); // reset card if (mmc_get() != 1) // error if bad/no response code { mmc_release(); return 1; } // wait for initialization to finish (gets a 0 back) i = 0xffff; while ((spi_byte(0xff) != 0) && (--i)) { mmc_send_command(SEND_OP_COND,0); // init card } if (!i) return 2; // timed out above mmc_send_command(SET_BLOCK_LEN, 512); //set block size to 512 mmc_release(); // increase SPI clock to (Fosc/2) SPCR &= ~3; SPSR = 1; return 0; }
void nrf_simplebyte(uint8_t cmd) { RF1_Write(cmd); #if 0 cbi(PORTB, PIN_nCS); spi_byte(cmd); sbi(PORTB, PIN_nCS); #endif }
void nrf_manybytes(uint8_t* data, uint8_t len){ #if 0 cbi(PORTB, PIN_nCS); do { spi_byte(*data++); } while(--len); sbi(PORTB, PIN_nCS); #endif }
/* final clocks and deassert SS line */ void mmc_release(void) { uint8_t i; // at least 8 final clocks for(i=0;i<10;i++) spi_byte(0xff); CS_DEASSERT; }
/** Finish Clocking and Release card. Send 10 clocks to the MMC/SD card and release the CS line */ void mmc_clock_and_release(void) { uint8_t i; // SD cards require at least 8 final clocks for(i=0;i<10;i++) spi_byte(0xff); SPI_PORT |= (1 << MMC_CS); // release CS }
void nrf_manybytes(uint8_t* data, uint8_t len){ cbi(NRF_PORT, PIN_nCS); do{ spi_byte(*data++); }while(--len); sbi(NRF_PORT, PIN_nCS); }
/** Get Datatoken. Wait for and return a data token from the MMC/SD card \return The received token or 0xFF if timeout */ uint8_t mmc_datatoken(void) { uint16_t i = 0xffff; uint8_t b = 0xff; while ((b != 0xfe) && (--i)) { b = spi_byte(0xff); } return b; }
/** * Get data token * * Get card data response tokens * \return Data token * */ uint8_t sd_get_datatoken(void) { uint32_t tmout = timeval + 1000; // 1 second timeout uint8_t b = 0xff; while ((b != SD_STARTBLOCK_READ) && (timeval < tmout)) { b = spi_byte(0xff,0); } return b; }
/** * Get response * * Get card response tokens * \return Response token * */ uint8_t sd_get_response(void) { uint32_t tmout = timeval + 1000; // 1 second timeout uint8_t b = 0xff; while ((b == 0xff) && (timeval < tmout)) { b = spi_byte(0xff,0); //TRACE_SD("x"); } return b; }
/** Get Token. Wait for and return a non-ff token from the MMC/SD card \return The received token or 0xFF if timeout */ uint8_t mmc_get(void) { uint16_t i = 0xffff; uint8_t b = 0xff; while ((b == 0xff) && (--i)) { b = spi_byte(0xff); } return b; }
void spi_string(char *bytes, uint8_t len) { uint8_t cnt; for (cnt = 0; cnt < len; cnt++) { spi_byte((uint8_t) bytes[cnt]); } // rising edge storage clock _delay_ms(10); PORT_SPI |= STCP; _delay_ms(10); PORT_SPI &= ~STCP; }
/** * SD command * * Send SD command to SD card * \param cmd Card command * \param arg Argument * */ void sd_command(uint8_t cmd, uint32_t arg) { //TRACE_SD("SDCMD[%d]",cmd); spi_byte(0xff,0); // dummy byte spi_byte(cmd | 0x40,0); // send command spi_byte(arg>>24,0); // send argument spi_byte(arg>>16,0); spi_byte(arg>>8,0); spi_byte(arg,0); switch(cmd) { case SD_GO_IDLE_STATE: spi_byte(0x95,1); // CRC for CMD0 break; /* * CRC for CMD8 always enabled see: * Physical Layer Simplified Specification Version 2.00 * chapter 7.2.2 Bus Transfer Protection */ case SD_SEND_IF_COND: spi_byte(0x87,1); // CRC for CMD8, argument 0x000001AA, see sd_init break; default: spi_byte(0xFF,1); // send dummy CRC for all other commands } }
/* write a single 512 byte sector to the SD card */ unsigned int mmc_writesector(uint32_t lba, uint8_t *buffer) { uint16_t i; uint8_t r; CS_ASSERT; // send command and sector mmc_send_command(WRITE_SINGLE_BLOCK, lba<<9); mmc_datatoken(); // get response spi_byte(0xfe); // send start block token for (i=0;i<512;i++) // write sector data spi_byte(*buffer++); spi_byte(0xff); // ignore checksum spi_byte(0xff); // ignore checksum r = spi_byte(0xff); // check for error if ((r & 0x1f) != 0x05) return r; // wait for SD card to complete writing and become idle i = 0xffff; while (!spi_byte(0xff) && --i) ; // wait for card to finish writing mmc_release(); // cleanup if (!i) return -1; // timeout error return 0; }
/* reads a single 512 bytes sector from the SD card */ int mmc_readsector(uint32_t lba, uint8_t *buffer) { uint16_t i; // send command and sector mmc_send_command(READ_SINGLE_BLOCK, lba<<9); if (mmc_datatoken() != 0xfe) // wait for start of block token { mmc_release(); // error return -1; } for (i=0;i<512;i++) *buffer++ = spi_byte(0xff); // read data spi_byte(0xff); // ignore checksum spi_byte(0xff); // ignore checksum mmc_release(); return 0; }
/** Read MMC/SD sector. Read a single 512 byte sector from the MMC/SD card \param lba Logical sectornumber to read \param buffer Pointer to buffer for received data \return 0 on success, -1 on error */ int mmc_readsector(uint32_t lba, uint8_t *buffer) { uint16_t i; // send read command and logical sector address mmc_send_command(17,(lba>>7) & 0xffff, (lba<<9) & 0xffff); if (mmc_datatoken() != 0xfe) // if no valid token { mmc_clock_and_release(); // cleanup and return -1; // return error code } for (i=0;i<512;i++) // read sector data *buffer++ = spi_byte(0xff); spi_byte(0xff); // ignore dummy checksum spi_byte(0xff); // ignore dummy checksum mmc_clock_and_release(); // cleanup return 0; // return success }
int main( void ) { spi_init(); uint8_t i; while (1) { for (i = 0; i < 10; i++) { spi_byte(time[i]); // rising edge storage clock PORT_SPI |= STCP; PORT_SPI &= ~STCP; _delay_ms(1); } } return 0; }
/* sends a command with parameters to the sd card */ void mmc_send_command(uint8_t command, uint32_t param) { union u32convert r; r.value = param; CS_ASSERT; spi_byte(0xff); spi_byte(command | 0x40); // send command spi_byte(r.bytes.byte4); // send parameter, one byte at a time spi_byte(r.bytes.byte3); spi_byte(r.bytes.byte2); spi_byte(r.bytes.byte1); spi_byte(0x95); // CRC for first command, after that ignore spi_byte(0xff); // ignore return }