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

📄 sd_mmc_spi.c

📁 SD卡调试所用的资料
💻 C
📖 第 1 页 / 共 2 页
字号:
            SD_MMC_ReadWrite_Byte(0xff);

            /* deaddress card */
            SD_MMC_SPI_DESELECT();

            /* let card some time to finish */
            SD_MMC_ReadWrite_Byte(0xff);
        }
#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
 */
u8 SD_Raw_Read_Interval(u32 offset, u8* buffer, u16 interval, u16 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
    //这两个次序很重要 begin SD_MMC_Send_Command之后再SD_MMC_SPI_SELECT


    u16 block_offset;
    u16 read_length;
    u8* buffer_cur;
    u8 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_MMC_Send_Command(CMD_READ_SINGLE_BLOCK, offset & 0xfffffe00))
        {
            unSD_MMC_SPI_SELECT();
            return 0;
        }
        /* address card */
        SD_MMC_SPI_SELECT();

        /* wait for data block (start byte 0xfe) */
        while(SD_MMC_ReadWrite_Byte(0xff) != 0xfe);

        /* read up to the data of interest */
        for(u16 i = 0; i < block_offset; ++i)
            SD_MMC_ReadWrite_Byte(0xff);

        /* read interval bytes of data and execute the callback */
        do
        {
            if(read_length < interval || length < interval)
                break;

            buffer_cur = buffer;
            for(u16 i = 0; i < interval; ++i)
                *buffer_cur++ = SD_MMC_ReadWrite_Byte(0xff);

            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_MMC_ReadWrite_Byte(0xff);

        /* read crc16 */
        SD_MMC_ReadWrite_Byte(0xff);
        SD_MMC_ReadWrite_Byte(0xff);

        if(length < interval)
            break;

        offset = (offset & 0xfffffe00) + 512;

    } while(!finished);

    /* deaddress card */
    unSD_MMC_SPI_SELECT();

    /* let card some time to finish */
    SD_MMC_ReadWrite_Byte(0xff);

    return 1;
#endif
}

/**
 * \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
 */

u8 SD_Raw_Write(u32 offset, const u8* buffer, u16 length)
{
#if SD_RAW_WRITE_SUPPORT

//    if(get_pin_locked())
//        return 0;

    u32 block_address;
    u16 block_offset;
    u16 write_length;
    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;

        //次序很重要
        /* send single block request */
        if(SD_MMC_Send_Command(CMD_WRITE_SINGLE_BLOCK, block_address))
        {
            SD_MMC_SPI_DESELECT();
            return 0;
        }
        /* address card */
        SD_MMC_SPI_SELECT();

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

        /* write byte block */
        u8* cache = raw_block;
        for(u16 i = 0; i < 512; ++i)
            SD_MMC_ReadWrite_Byte(*cache++);

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

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

        /* deaddress card */
        SD_MMC_SPI_DESELECT();

        length -= write_length;
        offset += write_length;

#if SD_RAW_WRITE_BUFFERING
        raw_block_written = 1;
#endif
    }

    return 1;
#else
    return 0;
#endif
}

/**
 * \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
 */
u8 SD_Raw_Write_Interval(u32 offset, u8* buffer, u16 length, sd_raw_write_interval_handler_t callback, void* p)
{
#if SD_RAW_WRITE_SUPPORT

#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;

    u8 endless = (length == 0);
    while(endless || length > 0)
    {
        u16 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;

#else
    return 0;
#endif
}

/**
 * \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
 */
u8 SD_Raw_Sync()
{
#if SD_RAW_WRITE_SUPPORT
  #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;
  #endif
  return 1;
#else
  return 0;
#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.
 */
u8 SD_Raw_Get_Info(struct sd_raw_info* info)
{
    if(!info || !SD_Raw_Available())
    {
        USART_SendByte(USART1,'A');
        return 0;
    }

    memset(info, 0, sizeof(*info));


    //some clock need
    SD_MMC_ReadWrite_Byte(0xff);
    SD_MMC_ReadWrite_Byte(0xff);
    SD_MMC_ReadWrite_Byte(0xff);
    /* read cid register */
    if(SD_MMC_Send_Command(CMD_SEND_CID, 0))
    {
        USART_SendByte(USART1,'B');
        SD_MMC_SPI_DESELECT();
        return 0;
    }
    SD_MMC_SPI_SELECT();

    while(SD_MMC_ReadWrite_Byte(0xff) != 0xfe);
    for(u8 i = 0; i < 18; ++i)
    {
        u8 b = SD_MMC_ReadWrite_Byte(0xff);

        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 |= (u32) 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 */
    u8 csd_read_bl_len = 0;
    u8 csd_c_size_mult = 0;
    u16 csd_c_size = 0;
    //some clock need
    SD_MMC_ReadWrite_Byte(0xff);
    SD_MMC_ReadWrite_Byte(0xff);
    SD_MMC_ReadWrite_Byte(0xff);
    //modified by york
    SD_MMC_SPI_DESELECT();
    if(SD_MMC_Send_Command(CMD_SEND_CSD, 0))
    {
        USART_SendByte(USART1,'C');
        SD_MMC_SPI_DESELECT();
        return 0;
    }
    SD_MMC_SPI_SELECT();
    //modified by york

    while(SD_MMC_ReadWrite_Byte(0xff) != 0xfe);
    for(u8 i = 0; i < 18; ++i)
    {
        u8 b = SD_MMC_ReadWrite_Byte(0xff);

        switch(i)
        {
            case 5:
                csd_read_bl_len = b & 0x0f;
                break;
            case 6:
                csd_c_size = (u16) (b & 0x03) << 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) << 1;
                break;
            case 10:
                csd_c_size_mult |= b >> 7;

                info->capacity = (u32) csd_c_size << (csd_c_size_mult + csd_read_bl_len + 2);

                break;
            case 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;
                break;
        }
    }

    SD_MMC_SPI_DESELECT();
    USART_SendByte(USART1,'D');
    return 1;
}

⌨️ 快捷键说明

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