static int read_data ( uint8 *buff, /* Data buffer to store received data */ size_t len /* Byte count (must be even number) */ ) { uint8 token; int i, old; uint16 crc, crc2; i = 0; do { /* Wait for data packet in timeout of 100ms */ token = spi_rec_byte(); ++i; } while ((token == 0xFF) && i < READ_RETRIES); if(token != 0xFE) { #ifdef SD_DEBUG dbglog(DBG_DEBUG, "%s: not valid data token: %02x\n", __func__, token); #endif return -1; /* If not valid data token, return with error */ } // dcache_alloc_range((uint32)buff, len); old = irq_disable(); spi_rec_data(buff, len); crc = (uint16)spi_rec_byte() << 8; crc |= (uint16)spi_rec_byte(); irq_restore(old); crc2 = net_crc16ccitt(buff, len, 0); // dcache_purge_range((uint32)buff, len); if(crc != crc2) { errno = EIO; return -1; } return 0; /* Return with success */ }
/** * \ingroup sd_raw * Continuously reads units of \c interval bytes and calls a callback function. * * This function starts reading at the specified offset. Every \c interval bytes, * it calls the callback function with the associated data buffer. * * By returning zero, the callback may stop reading. * * \note Within the callback function, you can not start another read or * write operation. * \note This function only works if the following conditions are met: * - (offset - (offset % 512)) % interval == 0 * - length % interval == 0 * * \param[in] offset Offset from which to start reading. * \param[in] buffer Pointer to a buffer which is at least interval bytes in size. * \param[in] interval Number of bytes to read before calling the callback function. * \param[in] length Number of bytes to read altogether. * \param[in] callback The function to call every interval bytes. * \param[in] p An opaque pointer directly passed to the callback function. * \returns 0 on failure, 1 on success * \see sd_raw_write_interval, sd_raw_read, sd_raw_write */ uint8_t sd_raw_read_interval(uint32_t offset, uint8_t* buffer, uint16_t interval, uint16_t length, sd_raw_read_interval_handler_t callback, void* p) { if(!buffer || interval == 0 || length < interval || !callback) return 0; #if !SD_RAW_SAVE_RAM while(length >= interval) { /* as reading is now buffered, we directly * hand over the request to sd_raw_read() */ if(!sd_raw_read(offset, buffer, interval)) return 0; if(!callback(buffer, offset, p)) break; offset += interval; length -= interval; } return 1; #else /* address card */ select_card(); uint16_t block_offset; uint16_t read_length; uint8_t* buffer_cur; uint8_t finished = 0; do { /* determine byte count to read at once */ block_offset = offset & 0x01ff; read_length = 512 - block_offset; /* send single block request */ if(sd_raw_send_command_r1(CMD_READ_SINGLE_BLOCK, offset & 0xfffffe00)) { unselect_card(); spi_rec_byte(); return 0; } /* wait for data block (start byte 0xfe) */ uint16_t i; for(i = 0; i < 0x1fff; ++i) { if(spi_rec_byte() == 0xfe) break; } if(i >= 0x1fff) { unselect_card(); spi_rec_byte(); return 0; } /* read up to the data of interest */ for(uint16_t i = 0; i < block_offset; ++i) spi_rec_byte(); /* read interval bytes of data and execute the callback */ do { if(read_length < interval || length < interval) break; spi_rec_data(buffer, interval); if(!callback(buffer, offset + (512 - read_length), p)) { finished = 1; break; } read_length -= interval; length -= interval; } while(read_length > 0 && length > 0); /* read rest of data block */ while(read_length-- > 0) spi_rec_byte(); /* read crc16 */ spi_rec_byte(); spi_rec_byte(); if(length < interval) break; offset = (offset & 0xfffffe00) + 512; } while(!finished); /* deaddress card */ unselect_card(); spi_rec_byte(); return 1; #endif }
/** * \ingroup sd_raw * Reads raw data from the card. * * \param[in] offset The offset from which to read. * \param[out] buffer The buffer into which to write the data. * \param[in] length The number of bytes to read. * \returns 0 on failure, 1 on success. * \see sd_raw_read_interval, sd_raw_write, sd_raw_write_interval */ uint8_t sd_raw_read(uint32_t offset, uint8_t* buffer, uint16_t length) { uint32_t block_address; uint16_t block_offset; uint16_t read_length; while(length > 0) { /* determine byte count to read at once */ block_address = offset & 0xfffffe00; block_offset = offset & 0x01ff; read_length = 512 - block_offset; /* read up to block border */ if(read_length > length) read_length = length; #if !SD_RAW_SAVE_RAM /* check if the requested data is cached */ if(block_address != raw_block_address) #endif { #if SD_RAW_WRITE_BUFFERING if(!sd_raw_sync()) return 0; #endif /* address card */ select_card(); /* send single block request */ if(sd_raw_send_command_r1(CMD_READ_SINGLE_BLOCK, block_address)) { unselect_card(); spi_rec_byte(); return 0; } /* wait for data block (start byte 0xfe) */ uint16_t i; for(i = 0; i < 0x1fff; ++i) { if(spi_rec_byte() == 0xfe) break; } if(i >= 0x1fff) { unselect_card(); spi_rec_byte(); return 0; } #if SD_RAW_SAVE_RAM /* read byte block */ uint16_t read_to = block_offset + read_length; for(uint16_t i = 0; i < 512; ++i) { uint8_t b = spi_rec_byte(); if(i >= block_offset && i < read_to) *buffer++ = b; } #else /* read byte block */ spi_rec_data(raw_block, 512); raw_block_address = block_address; memcpy(buffer, raw_block + block_offset, read_length); buffer += read_length; #endif /* read crc16 */ spi_rec_byte(); spi_rec_byte(); /* deaddress card */ unselect_card(); spi_rec_byte(); } #if !SD_RAW_SAVE_RAM else { /* use cached data */ memcpy(buffer, raw_block + block_offset, read_length); buffer += read_length; } #endif length -= read_length; offset += read_length; } return 1; }