Exemple #1
0
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 */
}
Exemple #2
0
/**
 * \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
}
Exemple #3
0
/**
 * \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;
}