Esempio n. 1
0
/**
 * \ingroup sd_raw
 * Writes a continuous data stream obtained from a callback function.
 *
 * This function starts writing at the specified offset. To obtain the
 * next bytes to write, it calls the callback function. The callback fills the
 * provided data buffer and returns the number of bytes it has put into the buffer.
 *
 * By returning zero, the callback may stop writing.
 *
 * \param[in] offset Offset where to start writing.
 * \param[in] buffer Pointer to a buffer which is used for the callback function.
 * \param[in] length Number of bytes to write in total. May be zero for endless writes.
 * \param[in] callback The function used to obtain the bytes to write.
 * \param[in] p An opaque pointer directly passed to the callback function.
 * \returns 0 on failure, 1 on success
 * \see sd_raw_read_interval, sd_raw_write, sd_raw_read
 */
uint8_t sd_raw_write_interval(offset_t offset, uint8_t* buffer, uintptr_t length, sd_raw_write_interval_handler_t callback, void* p)
{
#if SD_RAW_SAVE_RAM
    #error "SD_RAW_WRITE_SUPPORT is not supported together with SD_RAW_SAVE_RAM"
#endif

    if(!buffer || !callback)
        return 0;

    uint8_t endless = (length == 0);
    while(endless || length > 0)
    {
        uint16_t bytes_to_write = callback(buffer, offset, p);
        if(!bytes_to_write)
            break;
        if(!endless && bytes_to_write > length)
            return 0;

        /* as writing is always buffered, we directly
         * hand over the request to sd_raw_write()
         */
        if(!sd_raw_write(offset, buffer, bytes_to_write))
            return 0;

        offset += bytes_to_write;
        length -= bytes_to_write;
    }

    return 1;
}
Esempio n. 2
0
/**
 * \ingroup sd_raw
 * Writes a continuous data stream obtained from a callback function.
 *
 * This function starts writing at the specified offset. To obtain the
 * next bytes to write, it calls the callback function. The callback fills the
 * provided data buffer and returns the number of bytes it has put into the buffer.
 *
 * By returning zero, the callback may stop writing.
 *
 * \param[in] offset Offset where to start writing.
 * \param[in] buffer Pointer to a buffer which is used for the callback function.
 * \param[in] length Number of bytes to write in total. May be zero for endless writes.
 * \param[in] callback The function used to obtain the bytes to write.
 * \param[in] p An opaque pointer directly passed to the callback function.
 * \returns 0 on failure, 1 on success
 * \see sd_raw_read_interval, sd_raw_write, sd_raw_read
 */
uint8_t sd_raw_write_interval(offset_t offset, uint8_t* buffer, uintptr_t length, sd_raw_write_interval_handler_t callback, void* p)
{
  if(!buffer || !callback)
    return 0;

  uint8_t endless = (length == 0);
  while(endless || length > 0)
  {
    uint16_t bytes_to_write = callback(buffer, offset, p);
    if(!bytes_to_write)
      break;
    if(!endless && bytes_to_write > length)
      return 0;

    /* as writing is always buffered, we directly
     * hand over the request to sd_raw_write()
     */
    if(!sd_raw_write(offset, buffer, bytes_to_write))
      return 0;

    offset += bytes_to_write;
    length -= bytes_to_write;
  }

  return 1;
}
Esempio n. 3
0
/**
 * \ingroup sd_raw
 * Writes the write buffer's content to the card.
 *
 * \note When write buffering is enabled, you should
 *       call this function before disconnecting the
 *       card to ensure all remaining data has been
 *       written.
 *
 * \returns 0 on failure, 1 on success.
 * \see sd_raw_write
 */
uint8_t sd_raw_sync()
{
#if SD_RAW_WRITE_BUFFERING
    if(raw_block_written)
        return 1;
    if(!sd_raw_write(raw_block_address, raw_block, sizeof(raw_block)))
        return 0;
    raw_block_written = 1;
#endif
    return 1;
}
Esempio n. 4
0
/**
 * \ingroup sd_raw
 * Writes raw data to the card.
 *
 * \note If write buffering is enabled, you might have to
 *       call sd_raw_sync() before disconnecting the card
 *       to ensure all remaining data has been written.
 *
 * \param[in] offset The offset where to start writing.
 * \param[in] buffer The buffer containing the data to be written.
 * \param[in] length The number of bytes to write.
 * \returns 0 on failure, 1 on success.
 * \see sd_raw_write_interval, sd_raw_read, sd_raw_read_interval
 */
uint8_t sd_raw_write(uint32_t offset, const uint8_t* buffer, uint16_t length)
{
#if SD_RAW_WRITE_SUPPORT

    if(get_pin_locked())
        return 0;

    uint32_t block_address;
    uint16_t block_offset;
    uint16_t write_length;
    uint16_t i;

    while(length > 0)
    {
        /* determine byte count to write at once */
        block_address = offset & 0xfffffe00;
        block_offset = offset & 0x01ff;
        write_length = 512 - block_offset; /* write up to block border */
        if(write_length > length)
            write_length = length;
        
        /* Merge the data to write with the content of the block.
         * Use the cached block if available.
         */
        if(block_address != raw_block_address)
        {
#if SD_RAW_WRITE_BUFFERING
            if(!raw_block_written)
            {
                if(!sd_raw_write(raw_block_address, raw_block, sizeof(raw_block)))
                    return 0;
            }
#endif

            if(block_offset || write_length < 512)
            {
                if(!sd_raw_read(block_address, raw_block, sizeof(raw_block)))
                    return 0;
            }
            raw_block_address = block_address;
        }

        if(buffer != raw_block)
        {
            memcpy(raw_block + block_offset, buffer, write_length);

#if SD_RAW_WRITE_BUFFERING
            raw_block_written = 0;

            if(length == write_length)
                return 1;
#endif
        }

        buffer += write_length;

        /* address card */
        select_card();

        /* send single block request */
        if(sd_raw_send_command_r1(CMD_WRITE_SINGLE_BLOCK, block_address))
        {
            unselect_card();
            return 0;
        }

        /* send start byte */
        sd_raw_send_byte(0xfe);

        /* write byte block */
        uint8_t* cache = raw_block;
        for(i = 0; i < 512; ++i)
            sd_raw_send_byte(*cache++);

        /* write dummy crc16 */
        sd_raw_send_byte(0xff);
        sd_raw_send_byte(0xff);

        /* wait while card is busy */
        while(sd_raw_rec_byte() != 0xff);
        sd_raw_rec_byte();

        /* deaddress card */
        unselect_card();

        length -= write_length;
        offset += write_length;

#if SD_RAW_WRITE_BUFFERING
        raw_block_written = 1;
#endif
    }
    
    return 1;
#else
    return 0;
#endif
}
Esempio n. 5
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;
    uint16_t i;

    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(!raw_block_written)
            {
                if(!sd_raw_write(raw_block_address, raw_block, sizeof(raw_block)))
                    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();
                return 0;
            }

            /* wait for data block (start byte 0xfe) */

    i = 0;
    while(sd_raw_rec_byte() != 0xfe) {
      i++;
      if (i == 0) {
	unselect_card();
	return 0;
      }
    }

#if SD_RAW_SAVE_RAM
            /* read byte block */
            uint16_t read_to = block_offset + read_length;
            for(i = 0; i < 512; ++i)
            {
                uint8_t b = sd_raw_rec_byte();
                if(i >= block_offset && i < read_to)
                    *buffer++ = b;
            }
#else
            /* read byte block */
            uint8_t* cache = raw_block;
            for(i = 0; i < 512; ++i)
                *cache++ = sd_raw_rec_byte();
            raw_block_address = block_address;

            memcpy(buffer, raw_block + block_offset, read_length);
            buffer += read_length;
#endif
            
            /* read crc16 */
            sd_raw_rec_byte();
            sd_raw_rec_byte();
            
            /* deaddress card */
            unselect_card();

            /* let card some time to finish */
            sd_raw_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;
}