⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sd_raw.c

📁 This project provides a general purpose library which implements read and write support for MMC, SD
💻 C
📖 第 1 页 / 共 2 页
字号:
            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;}/** * \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(offset_t offset, uint8_t* buffer, uintptr_t interval, uintptr_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_SDHC        if(sd_raw_send_command(CMD_READ_SINGLE_BLOCK, (sd_raw_card_type & (1 << SD_RAW_SPEC_SDHC) ? offset / 512 : offset - block_offset)))#else        if(sd_raw_send_command(CMD_READ_SINGLE_BLOCK, offset - block_offset))#endif        {            unselect_card();            return 0;        }        /* wait for data block (start byte 0xfe) */        while(sd_raw_rec_byte() != 0xfe);        /* read up to the data of interest */        for(uint16_t i = 0; i < block_offset; ++i)            sd_raw_rec_byte();        /* read interval bytes of data and execute the callback */        do        {            if(read_length < interval || length < interval)                break;            buffer_cur = buffer;            for(uint16_t i = 0; i < interval; ++i)                *buffer_cur++ = sd_raw_rec_byte();            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)            sd_raw_rec_byte();                /* read crc16 */        sd_raw_rec_byte();        sd_raw_rec_byte();        if(length < interval)            break;        offset = offset - block_offset + 512;    } while(!finished);        /* deaddress card */    unselect_card();    /* let card some time to finish */    sd_raw_rec_byte();    return 1;#endif}#if DOXYGEN || SD_RAW_WRITE_SUPPORT/** * \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(offset_t offset, const uint8_t* buffer, uintptr_t length){    if(sd_raw_locked())        return 0;    offset_t block_address;    uint16_t block_offset;    uint16_t write_length;    while(length > 0)    {        /* determine byte count to write at once */        block_offset = offset & 0x01ff;        block_address = offset - block_offset;        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(!sd_raw_sync())                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        }        /* address card */        select_card();        /* send single block request */#if SD_RAW_SDHC        if(sd_raw_send_command(CMD_WRITE_SINGLE_BLOCK, (sd_raw_card_type & (1 << SD_RAW_SPEC_SDHC) ? block_address / 512 : block_address)))#else        if(sd_raw_send_command(CMD_WRITE_SINGLE_BLOCK, block_address))#endif        {            unselect_card();            return 0;        }        /* send start byte */        sd_raw_send_byte(0xfe);        /* write byte block */        uint8_t* cache = raw_block;        for(uint16_t 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();        buffer += write_length;        offset += write_length;        length -= write_length;#if SD_RAW_WRITE_BUFFERING        raw_block_written = 1;#endif    }    return 1;}#endif#if DOXYGEN || SD_RAW_WRITE_SUPPORT/** * \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;}#endif#if DOXYGEN || SD_RAW_WRITE_SUPPORT/** * \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;}#endif/** * \ingroup sd_raw * Reads informational data from the card. * * This function reads and returns the card's registers * containing manufacturing and status information. * * \note: The information retrieved by this function is *        not required in any way to operate on the card, *        but it might be nice to display some of the data *        to the user. * * \param[in] info A pointer to the structure into which to save the information. * \returns 0 on failure, 1 on success. */uint8_t sd_raw_get_info(struct sd_raw_info* info){    if(!info || !sd_raw_available())        return 0;    memset(info, 0, sizeof(*info));    select_card();    /* read cid register */    if(sd_raw_send_command(CMD_SEND_CID, 0))    {        unselect_card();        return 0;    }    while(sd_raw_rec_byte() != 0xfe);    for(uint8_t i = 0; i < 18; ++i)    {        uint8_t b = sd_raw_rec_byte();        switch(i)        {            case 0:                info->manufacturer = b;                break;            case 1:            case 2:                info->oem[i - 1] = b;                break;            case 3:            case 4:            case 5:            case 6:            case 7:                info->product[i - 3] = b;                break;            case 8:                info->revision = b;                break;            case 9:            case 10:            case 11:            case 12:                info->serial |= (uint32_t) b << ((12 - i) * 8);                break;            case 13:                info->manufacturing_year = b << 4;                break;            case 14:                info->manufacturing_year |= b >> 4;                info->manufacturing_month = b & 0x0f;                break;        }    }    /* read csd register */    uint8_t csd_read_bl_len = 0;    uint8_t csd_c_size_mult = 0;#if SD_RAW_SDHC    uint16_t csd_c_size = 0;#else    uint32_t csd_c_size = 0;#endif    if(sd_raw_send_command(CMD_SEND_CSD, 0))    {        unselect_card();        return 0;    }    while(sd_raw_rec_byte() != 0xfe);    for(uint8_t i = 0; i < 18; ++i)    {        uint8_t b = sd_raw_rec_byte();        if(i == 14)        {            if(b & 0x40)                info->flag_copy = 1;            if(b & 0x20)                info->flag_write_protect = 1;            if(b & 0x10)                info->flag_write_protect_temp = 1;            info->format = (b & 0x0c) >> 2;        }        else        {#if SD_RAW_SDHC            if(sd_raw_card_type & (1 << SD_RAW_SPEC_2))            {                switch(i)                {                    case 7:                        b &= 0x3f;                    case 8:                    case 9:                        csd_c_size <<= 8;                        csd_c_size |= b;                        break;                }                if(i == 9)                {                    ++csd_c_size;                    info->capacity = (offset_t) csd_c_size * 512 * 1024;                }            }            else#endif            {                switch(i)                {                    case 5:                        csd_read_bl_len = b & 0x0f;                        break;                    case 6:                        csd_c_size = b & 0x03;                        csd_c_size <<= 8;                        break;                    case 7:                        csd_c_size |= b;                        csd_c_size <<= 2;                        break;                    case 8:                        csd_c_size |= b >> 6;                        ++csd_c_size;                        break;                    case 9:                        csd_c_size_mult = b & 0x03;                        csd_c_size_mult <<= 1;                        break;                    case 10:                        csd_c_size_mult |= b >> 7;                        info->capacity = (uint32_t) csd_c_size << (csd_c_size_mult + csd_read_bl_len + 2);                        break;                }            }        }    }    unselect_card();    return 1;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -