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

📄 sdcard.java

📁 java 编写的一个FAT16读写源代码 支持长文件名和子目录
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*---------------------------------------------------------------------------
 *  Copyright (C) 2008 Maxim Integrated Products, Inc., All Rights Reserved.
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a
 *  copy of this software and associated documentation files (the "Software"),
 *  to deal in the Software without restriction, including without limitation
 *  the rights to use, copy, modify, merge, publish, distribute, sublicense,
 *  and/or sell copies of the Software, and to permit persons to whom the
 *  Software is furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included
 *  in all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 *  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 *  MERCHANTABILITY,  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 *  IN NO EVENT SHALL MAXIM INTEGRATED PRODUCTS INC. BE LIABLE FOR ANY CLAIM,
 *  DAMAGES, OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 *  OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
 *  USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 *  Except as contained in this notice, the name of Maxim Integrated Products,
 *  Inc. shall not be used except as stated in the Maxim Integrated Products,
 *  Inc. Branding Policy.
 * ---------------------------------------------------------------------------
 */

package com.dalsemi.fs.fat;

import com.dalsemi.fs.fat.*;
import com.dalsemi.comm.*;
import com.dalsemi.system.*;
import java.util.*;

public class SDCard implements DiskInterface
{
    private static final byte CMD0_GO_IDLE_STATE            = 0x00;
    private static final byte CMD1_SEND_OPCOND              = 0x01;
    private static final byte CMD9_SEND_CSD                 = 0x09;
    private static final byte CMD10_SEND_CID                = 0x0a;
    private static final byte CMD12_STOP_TRANSMISSION       = 0x0b;
    private static final byte CMD13_SEND_STATUS             = 0x0c;
    private static final byte CMD16_SET_BLOCKLEN            = 0x10;
    private static final byte CMD17_READ_SINGLE_BLOCK       = 0x11;
    private static final byte CMD18_READ_MULTIPLE_BLOCK     = 0x12;
    private static final byte CMD24_WRITE_BLOCK             = 0x18;
    private static final byte CMD25_WRITE_MULTIPLE_BLOCK    = 0x19;
    private static final byte CMD27_PROGRAM_CSD             = 0x1b;
    private static final byte CMD28_SET_WRITE_PROT          = 0x1c;
    private static final byte CMD29_CLR_WRITE_PROT          = 0x1d;
    private static final byte CMD30_SEND_WRITE_PROT         = 0x1e;
    private static final byte CMD32_ERASE_WR_BLK_START_ADDR = 0x20;
    private static final byte CMD33_ERASE_WR_BLK_END_ADDR   = 0x21;
    private static final byte CMD38_ERASE                   = 0x26;
    private static final byte CMD55_APP_CMD                 = 0x37;
    private static final byte CMD56_GEN_CMD                 = 0x38;
    private static final byte CMD58_READ_OCR                = 0x3a;
    private static final byte CMD59_CRC_ON_OFF              = 0x3b;

    private static final byte ACMD13_SD_STATUS              = 0x0d;
    private static final byte ACMD22_SEND_NUM_WR_BLOCKS     = 0x16;
    private static final byte ACMD23_SET_WR_BLK_ERASE_COUNT = 0x17;
    private static final byte ACMD41_SEND_OP_COND           = 0x29;
    private static final byte ACMD42_SET_CLR_CARD_DETECT    = 0x2a;
    private static final byte ACMD51_SEND_SCR               = 0x33;

    private static final byte R1_NOERROR   = 0x00;
    private static final byte R1_IDLE      = 0x01;
    private static final byte R1_ERASE     = 0x02;
    private static final byte R1_ILLEGAL   = 0x04;
    private static final byte R1_CRC_ERR   = 0x08;
    private static final byte R1_ERASE_SEQ = 0x10;
    private static final byte R1_ADDR_ERR  = 0x20;
    private static final byte R1_PARAM_ERR = 0x40;
//    private static final byte R1_NO_RESPONSE = (byte)0xFF;

    private static final int CACHE_SIZE = 100;
    
    public static BitPort bp = new BitPort(BitPort.Port5Bit2); //Port 3.5 for 390

    private class CachedSector
    {
        byte cache[];
        boolean dirty = false;
        int address;

        CachedSector(int address)
        {
            cache = new byte[blockSize + 3];
            this.address = address;
            readblock(this);
        }

        boolean isSector(int address, int length)
        {
            return ((address >= this.address) && ((address + length) <= (this.address + blockSize)));
        }
    }

    private Vector cache;

    private boolean immediateWrite = false;

    private int blockSize;
    private int cardSize;

    private int startAddress = 0;

    private SPI spi = new SPI();

    private byte[] cmd = new byte[6];

    public SDCard() throws Exception
    {
        if(!flushSPI())
        {
            throw new Exception("Unable to communicate with SD Card");
        }

        int tries = 0;
        byte r1;
        do
        {
            if(tries++ == 10)
            {
                throw new Exception("Unable to connect to SD Card");
            }

            clearArgs();
            r1 = sendCommand(CMD0_GO_IDLE_STATE);

        } while(r1 != R1_IDLE);
        tries = 0;
        do
        {
            if(tries++ == 10)
            {
                throw new Exception("SD Card timed out");
            }

            clearArgs();
            r1 = sendCommand(CMD55_APP_CMD);
            if(r1 != R1_IDLE)
            {
                r1 = 1;
                continue;
            }

            clearArgs();
            r1 = sendCommand(ACMD41_SEND_OP_COND);

        } while(r1 != R1_NOERROR);

        clearArgs();
        cmd[4] = 0x01;
        r1 = sendCommand(CMD59_CRC_ON_OFF);
        if(r1 != R1_NOERROR)
        {
            throw new Exception("Error enabling CRC for SD Card");
        }

        getCSD();

        cache = new Vector(CACHE_SIZE);
    }

    private void clearArgs()
    {
        cmd[1] = 0;
        cmd[2] = 0;
        cmd[3] = 0;
        cmd[4] = 0;
    }

    private boolean flushSPI()
    {
        for(int i = 0; i < 100; i++)
        {
            com.dalsemi.system.ArrayUtils.arrayFill(cmd, 0, 5, (byte)0xFF);
            spi.xmit(cmd, 0, 5);
            int j;
            for(j = 0; j < 5; j++)
            {
                if(cmd[j] != (byte)0xFF)
                {
                    break;
                }
            }
            if(j == 5)
            {
                return true;
            }
        }

        return false;
    }

    private byte sendCommand(byte command) throws Exception
    {
        byte recv = sendSPI((byte)0xFF);
        cmd[0] = (byte)(0x40 | (command & 0x3F));
        cmd[5] = (byte)((crc7(cmd, 0, 5) << 1) | 0x01);
        spi.xmit(cmd, 0, 6);

        return receiveR1();
    }

    private byte receiveR1() throws Exception
    {
        int tries = 0;
        byte recv;

        do
        {
            if(tries++ > 100)
            {
                throw new Exception("Timed out waiting for R1 response");
            }

            recv = sendSPI((byte)0xFF);
        } while((recv & 0x80) != 0);

        return recv;
    }

    private void receiveData(byte[] b, int off, int len) throws Exception
    {
        byte recv = (byte)0xFF;
        int tries = 0;

        do
        {
            if(tries++ > 50)
            {
                throw new Exception("Timed out receiving data");
            }
            recv = sendSPI(recv);
        } while(recv == (byte)0xFF);

        if(recv != (byte)0xFE)
        {
            throw new Exception("Bad value read before receiving data");
        }

        com.dalsemi.system.ArrayUtils.arrayFill(b, off, off + len, (byte)0x0FF);
        spi.xmit(b, off, len);

        recv = sendSPI((byte)0xff);
        if(recv != (byte)0xff)
        {
            throw new Exception("Bad value read after receiving data");
        }
    }

    private static byte crc7(byte[] data, int offset, int len)
    {
        byte crc = 0;
        for(int i = 0; i < len; i++)
        {
            for(int x = 7; x >= 0; x--)
            {
                crc <<= 1;
                crc |= ((data[offset + i] >> x) & 1);
                if((crc & 0x80) == 0x80)
                {
                    crc ^= 0x89;
                }
            }
        }

        for(int x = 0; x < 7; x++)
        {
            crc <<= 1;
            if((crc & 0x80) == 0x80)
            {
                crc ^= 0x89;
            }
        }

        return crc;
    }

    private byte[] spiout = new byte[1];
    private byte sendSPI(byte in)
    {
         spiout[0] = in;
         spi.xmit(spiout, 0, 1);
         return spiout[0];
    }

    private byte[] csdData = new byte[18];
    private void getCSD() throws Exception
    {
        clearArgs();
        if(sendCommand(CMD9_SEND_CSD) != R1_NOERROR)
        {
            throw new Exception("Unable to read CSD");
        }

        receiveData(csdData, 0, 18);
        verifyCRC16(csdData, 0, 16, (short)((csdData[16] << 8) | (csdData[17] & 0x0FF)));
        verifyCRC7(csdData, 0, 15, (byte)(csdData[15] >> 1));

        /* Blocksize is easy to decode */
//        blockSize = 0x01 << (csdData[5] & 0x0f);
blockSize = 512;

        /* Cardsize is split over several bytes */
        cardSize = ((csdData[6] & 0x03) << 10) | ((csdData[7] & 0x0FF) << 2) | (csdData[8] & 0x0c0);

        /* Multiplier is also split over several bytes */
        byte multiplier = (byte)(((csdData[9] & 0x03) << 1) | ((csdData[10] & 0x0FF) >> 7));

        /* Compute final card size */
        cardSize <<= (multiplier + 2); /* Multiplier is 2^(m+2) */

        switch (blockSize)
        {
            case 512:
                cardSize >>= 11;
                break;
            case 1024:
                break;
            case 2048:
                cardSize <<= 9;
                break;
            default:
                throw new Exception("Unsupported block size");
        }

        cardSize *= 1048576;
    }

    private static void verifyCRC16(byte[] b, int off, int len, short expect) throws Exception
    {
        short crc = crc16(b, off, len);
        if((crc & 0x0FFFF) != (expect & 0x0FFFF))
        {
            throw new Exception("CRC16 check failed");
        }
    }

    private static void verifyCRC7(byte[] b, int off, int len, byte expect) throws Exception
    {
        if((crc7(b, off, len) & 0x07F) != (expect & 0x07F))
        {
            throw new Exception("CRC7 check failed");
        }
    }

    private static short crc16(byte[] data, int offset, int len)
    {
        short crc = 0;
        for(int i = 0; i < len; i++)
        {

⌨️ 快捷键说明

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