Changeset 1052 for trunk/modules/sdmmc


Ignore:
Timestamp:
Jun 21, 2017, 10:50:42 AM (7 years ago)
Author:
alain
Message:

few bugs

Location:
trunk/modules/sdmmc/caba/source
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/modules/sdmmc/caba/source/include/sdmmc.h

    r574 r1052  
    5555
    5656    // Registers
    57     int               spi_fsm;           // SPI state register
    58     int               spi_shiftreg;     // data shift in/out
    59     int               spi_bitcount;
    60     int               spi_clk;
    61     int               spi_mosi_previous; // sampled MOSI value
     57    int               spi_fsm;               // SPI state register
     58    int                   spi_shiftreg;      // data shift in/out
     59    int                   spi_bitcount;
     60    int                   spi_clk;
     61    int                   spi_mosi_previous; // sampled MOSI value
    6262
    63     uint8_t           command;
     63    uint8_t               command;
    6464    uint32_t          args;
    65     uint8_t           cmdcrc;
     65    uint8_t               cmdcrc;
     66
    6667    int               m_fd;              // File descriptor
    6768    uint64_t          m_device_size;     // Total number of blocks
    6869    const uint32_t    m_latency;         // device latency
    6970
    70     uint8_t           m_databuf[1 /* reponse */ + 1 /* data tocken */ + 512 /* data block */ + 2 /* CRC */ ];
    71     uint32_t          m_datalen_snd; // data size to be sent to host
    72     uint32_t          m_datalen_rcv; // data size expected from host
     71    uint8_t               m_databuf[1    /* reponse */ +
     72                                1    /* data tocken */ +
     73                                512  /* data block */ +
     74                                2    /* CRC */ ];
     75
     76    uint32_t          m_datalen_snd;     // data size to be sent to host
     77    uint32_t          m_datalen_rcv;     // data size expected from host
    7378    uint32_t          m_data_idx;
    74     bool              m_acmd; // next command will be acmd
    75     int               m_sdstate; // sdcard internal state
     79    bool                  m_acmd;            // next command will be acmd
     80    int                   m_sdstate;        // sdcard internal state
    7681
    7782    // sd states
    78     enum {
    79         SD_IDLE = 0,
    80         SD_READY = 1,
     83    enum
     84    {
     85            SD_IDLE = 0,
     86            SD_READY = 1,
    8187    };
    8288
     
    8894
    8995    //  Master FSM states
    90     enum {
     96    enum
     97    {
    9198    S_IDLE               = 0,
    9299    S_RECEIVE_CMD        = 1,
  • trunk/modules/sdmmc/caba/source/src/sdmmc.cpp

    r709 r1052  
    4646    {
    4747        spi_fsm  = S_IDLE;
    48         m_acmd     = false;     
    49         m_sdstate  = SD_IDLE;
     48        m_acmd     = false;     
     49        m_sdstate  = SD_IDLE;
    5050        return;
    5151    }
    52     if (p_spi_ss.read()) {
    53         if (spi_fsm != S_IDLE) {
    54                 std::cerr << name() << " deselect but not idle, state "
    55                 << std::dec << spi_fsm << " last cmd " << (int)command
    56                 << " args " << std::hex << args << std::dec
    57                 << " bitcount " << (int)spi_bitcount
    58                 << " idx " << m_data_idx << " len_snd " << m_datalen_snd
    59                 << " len_rcv " << m_datalen_rcv << std::endl;
    60         }
    61         spi_fsm  = S_IDLE;
    62         spi_clk = p_spi_clk;
    63         spi_mosi_previous = p_spi_mosi;
    64         return;
     52
     53    if (p_spi_ss.read())
     54    {
     55        if (spi_fsm != S_IDLE)
     56        {
     57                    std::cerr << name() << " deselect but not idle, state "
     58                      << std::dec << spi_fsm << " last cmd " << (int)command
     59                      << " args " << std::hex << args << std::dec
     60                      << " bitcount " << (int)spi_bitcount
     61                      << " idx " << m_data_idx << " len_snd " << m_datalen_snd
     62                      << " len_rcv " << m_datalen_rcv << std::endl;
     63            }
     64            spi_fsm  = S_IDLE;
     65            spi_clk = p_spi_clk;
     66            spi_mosi_previous = p_spi_mosi;
     67            return;
    6568    }
    6669
    67     switch(spi_fsm) {
    68     case S_IDLE:
    69         if (p_spi_clk.read() == 1 && spi_clk == 0) {
    70                 // rising edge
    71                 command = (command << 1) | spi_mosi_previous;
    72                 spi_bitcount = 6;
    73                 spi_fsm = S_RECEIVE_CMD;
    74         }
    75         break;
    76     case S_RECEIVE_CMD:
    77         if (p_spi_clk.read() == 1 && spi_clk == 0) {
    78                 // rising edge
    79                 command = (command << 1) | spi_mosi_previous;
    80                 if (spi_bitcount == 0) {
    81                         if ((command & 0x80) == 0) {
    82                                 spi_fsm = S_RECEIVE_ARGS_START;
    83                         } else {
     70    switch(spi_fsm)
     71    {
     72        case S_IDLE:
     73            if (p_spi_clk.read() == 1 && spi_clk == 0) // rising edge
     74        {
     75                    command = (command << 1) | spi_mosi_previous;
     76                    spi_bitcount = 6;
     77                    spi_fsm = S_RECEIVE_CMD;
     78            }
     79        break;
     80        case S_RECEIVE_CMD:
     81            if (p_spi_clk.read() == 1 && spi_clk == 0) // rising edge
     82        {
     83                    command = (command << 1) | spi_mosi_previous;
     84            if (spi_bitcount == 0)
     85            {
     86                if ((command & 0x80) == 0)
     87                {
     88                                    spi_fsm = S_RECEIVE_ARGS_START;
     89                            }
     90                else
     91                {
    8492#ifdef SOCLIB_MODULE_DEBUG0
    8593                                std::cout << name() << " S_RECEIVE_CMD " << std::hex << (int)command << std::endl;
    8694#endif
    87                                 spi_fsm = S_IDLE;
    88                         }
    89                 } else {
    90                     spi_bitcount = spi_bitcount - 1;
    91                 }
    92         }
    93         break;
    94     case S_RECEIVE_ARGS_START:
    95         if (p_spi_clk.read() == 1 && spi_clk == 0) {
    96                 // rising edge
    97                 args = (args << 1) | spi_mosi_previous;
    98                 spi_bitcount = 30;
    99                 spi_fsm = S_RECEIVE_ARGS;
    100         }
    101         break;
    102     case S_RECEIVE_ARGS:
    103         if (p_spi_clk.read() == 1 && spi_clk == 0) {
    104                 // rising edge
    105                 args = (args << 1) | spi_mosi_previous;
    106                 if (spi_bitcount == 0) {
    107                         spi_bitcount = 7;
    108                         spi_fsm = S_RECEIVE_CRC;
    109                 } else {
    110                     spi_bitcount = spi_bitcount - 1;
    111                 }
    112         }
    113         break;
    114     case S_RECEIVE_CRC:
    115         if (p_spi_clk.read() == 1 && spi_clk == 0) {
    116                 // rising edge
    117                 cmdcrc = (cmdcrc << 1) | spi_mosi_previous;
    118                 if (spi_bitcount == 0) {
    119                         handle_sdmmc_cmd(command, args);
    120                         spi_bitcount = 0; // SEND_DATA will reset it
    121                         spi_fsm = S_SEND_DATA;
    122                         m_data_idx = 0;
    123                 } else {
    124                         spi_bitcount = spi_bitcount - 1;
    125                 }
    126         }
    127         break;
     95                    spi_fsm = S_IDLE;
     96                }
     97                    }
     98            else
     99            {
     100                        spi_bitcount = spi_bitcount - 1;
     101                    }
     102            }
     103        break;
     104        case S_RECEIVE_ARGS_START:
     105            if (p_spi_clk.read() == 1 && spi_clk == 0) // rising edge
     106        {
     107                    args = (args << 1) | spi_mosi_previous;
     108                    spi_bitcount = 30;
     109                    spi_fsm = S_RECEIVE_ARGS;
     110            }
     111        break;
     112        case S_RECEIVE_ARGS:
     113            if (p_spi_clk.read() == 1 && spi_clk == 0) // rising edge
     114        {
     115                    args = (args << 1) | spi_mosi_previous;
     116                    if (spi_bitcount == 0)
     117            {
     118                            spi_bitcount = 7;
     119                            spi_fsm = S_RECEIVE_CRC;
     120                    }
     121            else
     122            {
     123                        spi_bitcount = spi_bitcount - 1;
     124                    }
     125        }
     126        break;
     127        case S_RECEIVE_CRC:
     128        if (p_spi_clk.read() == 1 && spi_clk == 0) // rising edge
     129        {
     130            cmdcrc = (cmdcrc << 1) | spi_mosi_previous;
     131                    if (spi_bitcount == 0)
     132            {
     133                            handle_sdmmc_cmd(command, args);
     134                            spi_bitcount = 0; // SEND_DATA will reset it
     135                            spi_fsm = S_SEND_DATA;
     136                            m_data_idx = 0;
     137            }
     138            else
     139            {
     140                            spi_bitcount = spi_bitcount - 1;
     141                    }
     142        }
     143        break;
    128144       
    129     case S_SEND_DATA:
    130         if (p_spi_clk.read() == 0 && spi_clk == 1) {
    131                 // falling edge
    132                 if (spi_bitcount == 0) {
    133                         if (m_data_idx != m_datalen_snd) {     
    134                                 spi_shiftreg = m_databuf[m_data_idx];
    135                                 spi_bitcount = 7;
    136                                 spi_fsm = S_SEND_DATA;
    137                                 m_data_idx++;
     145        case S_SEND_DATA:
     146            if (p_spi_clk.read() == 0 && spi_clk == 1) // falling edge
     147        {
     148                    if (spi_bitcount == 0)
     149            {
     150                    if (m_data_idx != m_datalen_snd)
     151                {       
     152                                    spi_shiftreg = m_databuf[m_data_idx];
     153                                    spi_bitcount = 7;
     154                                    spi_fsm = S_SEND_DATA;
     155                                    m_data_idx++;
    138156#ifdef SOCLIB_MODULE_DEBUG0
    139157                        std::cout << name() << " S_SEND_DATA " << std::dec << m_datalen_snd << " idx " << m_data_idx << " " << std::hex << (uint32_t)m_databuf[m_data_idx] << std::endl;
    140158#endif
    141                         } else if (m_datalen_rcv != 0) {
    142                                 spi_fsm = S_RECEIVE_DATA_WAIT;
    143                                 spi_bitcount = 7;
    144                                 m_data_idx = 0;
    145                         } else {
    146                                 spi_fsm = S_IDLE;
    147                         }
    148                 } else {
    149                         spi_bitcount = spi_bitcount - 1;
    150                         spi_shiftreg = spi_shiftreg << 1;
    151                 }
    152         }
    153         break;
    154     case S_RECEIVE_DATA_WAIT:
    155         if (p_spi_clk.read() == 1 && spi_clk == 0) {
    156             // rising edge
    157             uint8_t s_data;
    158             s_data = (m_databuf[0] << 1) | spi_mosi_previous;
    159             m_databuf[0] = s_data;
    160             if (spi_bitcount == 0) {
     159                }
     160                else if (m_datalen_rcv != 0)
     161                {
     162                                    spi_fsm = S_RECEIVE_DATA_WAIT;
     163                                    spi_bitcount = 7;
     164                                    m_data_idx = 0;
     165                            }
     166                else
     167                {
     168                    spi_fsm = S_IDLE;
     169                }
     170            }
     171            else
     172            {
     173                            spi_bitcount = spi_bitcount - 1;
     174                            spi_shiftreg = spi_shiftreg << 1;
     175                    }
     176        }
     177        break;
     178        /////////////////////////
     179        case S_RECEIVE_DATA_WAIT:
     180        if (p_spi_clk.read() == 1 && spi_clk == 0)  // rising edge
     181        {
     182                uint8_t s_data;
     183            s_data = (m_databuf[0] << 1) | spi_mosi_previous;
     184            m_databuf[0] = s_data;
     185            if (spi_bitcount == 0)
     186            {
    161187#ifdef SOCLIB_MODULE_DEBUG
    162         std::cout << name() << " S_RECEIVE_DATA_WAIT " << std::dec << (int)s_data << std::endl;
    163 #endif
    164                     spi_bitcount = 7;
    165                     if (s_data == 0xfe) { // data start token
    166                         spi_fsm = S_RECEIVE_DATA;
    167                         m_data_idx = 1;
    168                     } else {
     188std::cout << name() << " S_RECEIVE_DATA_WAIT " << std::dec << (int)s_data << std::endl;
     189#endif
     190                spi_bitcount = 7;
     191                if (s_data == 0xfe)  // data start token
     192                {
     193                                spi_fsm = S_RECEIVE_DATA;
     194                    m_data_idx = 1;
     195                }
     196                else
     197                {
    169198#ifdef SOCLIB_MODULE_DEBUG
    170                         std::cout << name() << " S_RECEIVE_DATA_WAIT " << std::hex << (int)s_data << std::endl;
    171 #endif
    172                         spi_fsm = S_RECEIVE_DATA_WAIT;
    173                 }
    174             } else {
    175                 spi_bitcount = spi_bitcount - 1;
    176             }
    177         }
    178         break;
    179         case S_RECEIVE_DATA:
    180             if (p_spi_clk.read() == 1 && spi_clk == 0) {
    181                 // rising edge
    182                 m_databuf[m_data_idx] = (m_databuf[m_data_idx] << 1) | spi_mosi_previous;
    183                 if (spi_bitcount == 0) {
    184                     m_data_idx++;
    185                     if (m_data_idx != m_datalen_rcv) {
    186                         spi_fsm = S_RECEIVE_DATA;
    187                         spi_bitcount = 7;
    188                     } else {
    189                         handle_sdmmc_write(command, args);
    190                         if (m_datalen_snd > 0) {
    191                             spi_bitcount = 0; // SEND_DATA will reset it
    192                             spi_fsm = S_SEND_DATA;
    193                             m_data_idx = 0;
    194                         } else {
    195                             spi_fsm = S_IDLE;
    196                         }
    197                     }
    198                 } else {
    199                         spi_bitcount = spi_bitcount - 1;
    200                 }
    201             }
     199std::cout << name() << " S_RECEIVE_DATA_WAIT " << std::hex << (int)s_data << std::endl;
     200#endif
     201                    spi_fsm = S_RECEIVE_DATA_WAIT;
     202                }
     203            }
     204            else
     205            {
     206                spi_bitcount = spi_bitcount - 1;
     207            }
     208        }
     209        break;
     210        ////////////////////
     211        case S_RECEIVE_DATA:
     212            if (p_spi_clk.read() == 1 && spi_clk == 0) // rising edge
     213        {
     214            m_databuf[m_data_idx] = (m_databuf[m_data_idx] << 1) | spi_mosi_previous;
     215            if (spi_bitcount == 0)
     216            {
     217                        m_data_idx++;
     218                        if (m_data_idx != m_datalen_rcv)
     219                {
     220                    spi_fsm = S_RECEIVE_DATA;
     221                    spi_bitcount = 7;
     222                }
     223                else
     224                {
     225                    handle_sdmmc_write(command, args);
     226                            if (m_datalen_snd > 0)
     227                    {
     228                                spi_bitcount = 0; // SEND_DATA will reset it
     229                                spi_fsm = S_SEND_DATA;
     230                                m_data_idx = 0;
     231                    }
     232                    else
     233                    {
     234                        spi_fsm = S_IDLE;
     235                    }
     236                }
     237            }
     238            else
     239            {
     240                spi_bitcount = spi_bitcount - 1;
     241            }
     242        }
     243        break;
     244    }  // end switch spi_fsm
     245
     246    //// now generate output signal
     247
     248    switch(spi_fsm)
     249    {
     250        case S_IDLE:
     251            p_spi_miso = !p_spi_ss.read();
     252        break;
     253
     254        case S_SEND_DATA:
     255            p_spi_miso = (spi_shiftreg & 0x80) != 0;
    202256            break;
     257
     258        default:
     259            p_spi_miso = !p_spi_ss.read();
     260        break;
    203261    }
    204262
    205 //// now genrate output signal
    206 
    207     switch(spi_fsm) {
    208     case S_IDLE:
    209         p_spi_miso = !p_spi_ss.read();
    210         break;
    211     case S_SEND_DATA:
    212         p_spi_miso = (spi_shiftreg & 0x80) != 0;
    213         break;
    214     default:
    215         p_spi_miso = !p_spi_ss.read();
    216         break;
    217     }
     263    //// sample inputs
    218264    spi_clk = p_spi_clk.read();
    219265    spi_mosi_previous = p_spi_mosi;
     266
    220267} // end GenMealy()
    221268
    222269
    223 //////////////////////
     270////////////////////////////////////////////////////////
    224271void SdMMC::handle_sdmmc_cmd(uint8_t cmd, uint32_t data)
    225272{
    226273        m_datalen_rcv = 0;
    227         m_databuf[0] = 0x04; // illegal command
    228         m_datalen_snd = 1;
     274        m_databuf[0] = 0x04;    // default value : illegal command
     275        m_datalen_snd = 1;      // default value : 1 byte
    229276
    230277        if (m_sdstate == SD_IDLE)
    231278                m_databuf[0] |= 0x01; // idle
    232279
    233         if ((cmd & 0x40) == 0) {
     280        if ((cmd & 0x40) == 0)
     281    {
    234282                //illegal command
    235283                return;
    236284        }
    237285        cmd &= 0x3f;
    238         if (m_acmd) {
     286
     287    if (m_acmd)
     288    {
    239289#ifdef SOCLIB_MODULE_DEBUG0
    240         std::cout << name() << " new acmd " << std::dec << (int)cmd << " args " << std::hex << data << " crc " << (int)cmdcrc << std::endl;
     290std::cout << name() << " new acmd " << std::dec << (int)cmd << " args " << std::hex << data << " crc " << (int)cmdcrc << std::endl;
    241291#endif
    242292            m_acmd = false;
    243             switch (cmd) {
    244             case 41:
    245                 m_databuf[0] = 0x0; // card ready
    246                 m_datalen_snd = 1;
    247                 m_sdstate = SD_READY;
    248                 break;
    249             case 51:
    250                 // send SCR
    251                 m_databuf[ 0] = (m_sdstate == SD_IDLE) ? 0x1 : 0x0; // R1
    252                 m_databuf[ 1] = 0xfe; // data token
    253                 m_databuf[ 2] = 0x00; // SCR_STRUCTURE / SD_SPEC
    254                 m_databuf[ 3] = 0x05; // DATA_STAT_AFTER_ERASE, SD_SECURITY, SD_BUS_WIDTHS
    255                 m_databuf[ 4] = 0;    // SD_SPEC3, EX_SECURITY, SD_SPEC4
    256                 m_databuf[ 5] = 0;    // CMD_SUPPORT
    257                 m_databuf[ 6] = 0;    // vendor specific
    258                 m_databuf[ 7] = 0;    // vendor specific
    259                 m_databuf[ 8] = 0;    // vendor specific
    260                 m_databuf[ 9] = 0;    // vendor specific
    261                 m_databuf[10] = 0x0;  // CRC16
    262                 m_databuf[11] = 0x0;  // CRC16
    263                 m_datalen_snd = 12;
    264                 break;
    265             default:
    266                 std::cout << name() << " unknown acmd " << std::dec
    267                     << (int)cmd << std::endl;
    268                 break; // return illegal command
     293            switch (cmd)
     294        {
     295            case 41:      // ACD41 : Send OP_COND
     296                    m_databuf[0] = 0x0; // card ready
     297                    m_datalen_snd = 1;
     298                    m_sdstate = SD_READY;
     299                    break;
     300                case 51:   // send SCR
     301            m_databuf[ 0] = (m_sdstate == SD_IDLE) ? 0x1 : 0x0; // R1
     302            m_databuf[ 1] = 0xfe; // data token
     303            m_databuf[ 2] = 0x00; // SCR_STRUCTURE / SD_SPEC
     304            m_databuf[ 3] = 0x05; // DATA_STAT_AFTER_ERASE, SD_SECURITY, SD_BUS_WIDTHS
     305            m_databuf[ 4] = 0;    // SD_SPEC3, EX_SECURITY, SD_SPEC4
     306            m_databuf[ 5] = 0;    // CMD_SUPPORT
     307            m_databuf[ 6] = 0;    // vendor specific
     308                    m_databuf[ 7] = 0;    // vendor specific
     309            m_databuf[ 8] = 0;    // vendor specific
     310            m_databuf[ 9] = 0;    // vendor specific
     311            m_databuf[10] = 0x0;  // CRC16
     312            m_databuf[11] = 0x0;  // CRC16
     313            m_datalen_snd = 12;
     314                    break;
     315                default:
     316                    std::cout << name() << " unknown acmd " << std::dec
     317                              << (int)cmd << std::endl;
     318                    break; // return illegal command
    269319            }
    270         } else {
     320        }
     321    else
     322    {
    271323#ifdef SOCLIB_MODULE_DEBUG0
    272         std::cout << name() << " new cmd " << std::dec << (int)cmd << " args " << std::hex << data << " crc " << (int)cmdcrc << std::endl;
    273 #endif
    274             switch (cmd) {
    275             case 0:
    276                 m_databuf[0] = 0x1;
    277                 m_datalen_snd = 1;
    278                 m_sdstate = SD_IDLE;
    279                 break;
    280             case 8:
    281                 // reply with illegal command for now
    282                 break;
    283             case 9:
    284               {
    285                 // send CSD
    286                 // we use a block len of 1024
    287                 uint32_t csize = ((m_device_size + (512 * 1024) - 1) / (512 * 1024)) - 1;
    288                 m_databuf[ 0]  = (m_sdstate == SD_IDLE) ? 0x1 : 0x0; // R1
    289                 m_databuf[ 1]  = 0xfe; // data token
    290                 m_databuf[ 2]  = 0x00; // CSD_STRUCTURE
    291                 m_databuf[ 3]  = 0xe;  // TAAC
    292                 m_databuf[ 4]  = 0;    // NSAC
    293                 m_databuf[ 5]  = 0x32; // TRAN_SPEED
    294                 m_databuf[ 6]  = 0x5b; // CCC_H
    295                 m_databuf[ 7]  = 0x5a; // CCC_L + READ_BL_LEN
    296                 m_databuf[ 8]  = 0x80; // READ_BL_PARTIAL, R/W_BLK_MISALIGN, DSR_IMP
    297                 m_databuf[ 8] |= (csize >> 10) & 0x03; // CSIZE[12-11]
    298                 m_databuf[ 9]  = (csize >>  2) & 0xff; // CSIZE[10-2]
    299                 m_databuf[10]  = (csize <<  6) & 0xc0; // CSIZE[1-0]
    300                 m_databuf[10] |= 0;    // R_CURR_MIN, R_CURR_MAX
    301                 m_databuf[11]  = 0x3;  // W_CURR_MIN, W_CURR_MAX, CSIZE_MULT[2-1];
    302                 m_databuf[12]  = 0xff; // CSIZE_MULT[1], ERASE_BLK_EN, ERASE_SECTOR_SIZE[6-1]
    303                 m_databuf[13]  = 0x80; // ERASE_SECTOR_SIZE[0]. WP_GRP_SIZE
    304                 m_databuf[14]  = 0x0a; // WP_GRP_ENABLE, R2W_FACTOR, WRITE_BL_LEN[2-3]
    305                 m_databuf[15]  = 0x40; // WRITE_BL_LEN[0-1], WR_BL_PARTIAL
    306                 m_databuf[16]  = 0;    // FILE_FORMAT
    307                 m_databuf[17]  = 0x1;  // CRC7
    308                 m_databuf[18]  = 0x0;  // CRC16
    309                 m_databuf[19]  = 0x0;  // CRC16
    310                 m_datalen_snd  = 20;
    311                 break;
    312               }
    313             case 10:
    314                 // send CID
    315                 m_databuf[ 0] = (m_sdstate == SD_IDLE) ? 0x1 : 0x0; // R1
    316                 m_databuf[ 1] = 0xfe; // data token
    317                 m_databuf[ 2] = 0xda; // MID
    318                 m_databuf[ 3] = 'P';  // OID
    319                 m_databuf[ 4] = '6';  // OID
    320                 m_databuf[ 5] = 's';  // PNM
    321                 m_databuf[ 6] = 'o';  // PNM
    322                 m_databuf[ 7] = 'c';  // PNM
    323                 m_databuf[ 8] = 's';  // PNM
    324                 m_databuf[ 9] = 'd';  // PNM
    325                 m_databuf[10] = 0x01; // PRV
    326                 m_databuf[11] = 0xde; // PSN
    327                 m_databuf[12] = 0xad; // PSN
    328                 m_databuf[13] = 0xbe; // PSN
    329                 m_databuf[14] = 0xef; // PSN
    330                 m_databuf[15] = 10;   // MDT
    331                 m_databuf[16] = 13;   // MDT
    332                 m_databuf[17] = 0x1;  // CRC7
    333                 m_databuf[18] = 0x0;  // CRC16
    334                 m_databuf[19] = 0x0;  // CRC16
    335                 m_datalen_snd = 20;
    336                 break;
    337             case 16:
    338                 // set block size
    339                 if (m_sdstate != SD_IDLE && data == 512) {
    340                         m_databuf[0] = 0x00;
    341                         m_datalen_snd = 1;
    342                 } // else illegal command
    343                 break;
    344             case 17:
    345               {
    346                 int ret;
    347                 // read data block
    348                 if (m_sdstate == SD_IDLE) {
    349                         // return illegal command
    350                         return;
    351                 }
    352                 if (data >= m_device_size) {
    353                         std::cerr << name() << " read: request " << data
    354                             << " past end of file " << m_device_size << std::endl;
    355                         m_databuf[0] = 0x00; // R1 OK
    356                         m_databuf[1] = 0x08; // error tocken "out of range"
    357                         m_datalen_snd = 2;
    358                         return;
    359                 }
    360                 do {
    361                         if (lseek(m_fd, data, SEEK_SET) < 0) {
    362                                 std::cerr << name() << " lseek: " <<
    363                                   strerror(errno) << std::endl;
    364                                 m_databuf[0] = 0x00; // R1 OK
    365                                 m_databuf[1] = 0x02; // error tocken "CC err"
    366                                 m_datalen_snd = 2;
    367                                 return;
    368                         }
    369                         ret = read(m_fd, &m_databuf[2], 512);
    370                 } while (ret < 0 && errno == EINTR);
    371                 if (ret < 0) {
    372                         std::cerr << name() << " read: " <<
    373                           strerror(errno) << std::endl;
    374                         m_databuf[0] = 0x00; // R1 OK
    375                         m_databuf[1] = 0x04; // error tocken "card ECC failed"
    376                         m_datalen_snd = 2;
    377                         return;
    378                 }
    379                 m_databuf[514] = m_databuf[515] = 0; // XXX CRC
    380                 m_databuf[0] = 0x0; // R1
    381                 m_databuf[1] = 0xfe; // start block tocken
    382                 m_datalen_snd = 516;
    383                 break;
    384               }
    385             case 24:
    386               {
    387                 // write data block
    388                 if (m_sdstate == SD_IDLE) {
    389                         // return illegal command
    390                         return;
    391                 }
     324std::cout << name() << " new cmd " << std::dec << (int)cmd << " args " << std::hex << data << " crc " << (int)cmdcrc << std::endl;
     325#endif
     326            switch (cmd)
     327        {
     328            ///////
     329            case 0:       // CMD0
     330                m_databuf[0] = 0x1;
     331                        m_datalen_snd = 1;
     332                        m_sdstate = SD_IDLE;
     333                break;
     334            ///////
     335                case 8:       // CMD8
     336            // reply with illegal command for now
     337                    break;
     338            ///////
     339            case 9:       // CMD9 : send CSD
     340                {
     341                // we use a block len of 1024
     342                uint32_t csize = ((m_device_size + (512 * 1024) - 1) / (512 * 1024)) - 1;
     343                m_databuf[ 0]  = (m_sdstate == SD_IDLE) ? 0x1 : 0x0; // R1
     344                m_databuf[ 1]  = 0xfe; // data token
     345                m_databuf[ 2]  = 0x00; // CSD_STRUCTURE
     346                m_databuf[ 3]  = 0xe;  // TAAC
     347                m_databuf[ 4]  = 0;    // NSAC
     348                m_databuf[ 5]  = 0x32; // TRAN_SPEED
     349                m_databuf[ 6]  = 0x5b; // CCC_H
     350                m_databuf[ 7]  = 0x5a; // CCC_L + READ_BL_LEN
     351                m_databuf[ 8]  = 0x80; // READ_BL_PARTIAL, R/W_BLK_MISALIGN, DSR_IMP
     352                m_databuf[ 8] |= (csize >> 10) & 0x03; // CSIZE[12-11]
     353                m_databuf[ 9]  = (csize >>  2) & 0xff; // CSIZE[10-2]
     354                m_databuf[10]  = (csize <<  6) & 0xc0; // CSIZE[1-0]
     355                m_databuf[10] |= 0;    // R_CURR_MIN, R_CURR_MAX
     356                m_databuf[11]  = 0x3;  // W_CURR_MIN, W_CURR_MAX, CSIZE_MULT[2-1];
     357                m_databuf[12]  = 0xff; // CSIZE_MULT[1], ERASE_BLK_EN, ERASE_SECTOR_SIZE[6-1]
     358                m_databuf[13]  = 0x80; // ERASE_SECTOR_SIZE[0]. WP_GRP_SIZE
     359                m_databuf[14]  = 0x0a; // WP_GRP_ENABLE, R2W_FACTOR, WRITE_BL_LEN[2-3]
     360                m_databuf[15]  = 0x40; // WRITE_BL_LEN[0-1], WR_BL_PARTIAL
     361                m_databuf[16]  = 0;    // FILE_FORMAT
     362                m_databuf[17]  = 0x1;  // CRC7
     363                m_databuf[18]  = 0x0;  // CRC16
     364                m_databuf[19]  = 0x0;  // CRC16
     365                m_datalen_snd  = 20;
     366                }
     367            break;
     368            ////////
     369                case 10:       // CMD10 : send CID
     370                m_databuf[ 0] = (m_sdstate == SD_IDLE) ? 0x1 : 0x0; // R1
     371                m_databuf[ 1] = 0xfe; // data token
     372                m_databuf[ 2] = 0xda; // MID
     373                m_databuf[ 3] = 'P';  // OID
     374                m_databuf[ 4] = '6';  // OID
     375                m_databuf[ 5] = 's';  // PNM
     376                m_databuf[ 6] = 'o';  // PNM
     377                m_databuf[ 7] = 'c';  // PNM
     378                m_databuf[ 8] = 's';  // PNM
     379                m_databuf[ 9] = 'd';  // PNM
     380                m_databuf[10] = 0x01; // PRV
     381                m_databuf[11] = 0xde; // PSN
     382                m_databuf[12] = 0xad; // PSN
     383                m_databuf[13] = 0xbe; // PSN
     384                m_databuf[14] = 0xef; // PSN
     385                m_databuf[15] = 10;   // MDT
     386                m_databuf[16] = 13;   // MDT
     387                m_databuf[17] = 0x1;  // CRC7
     388                m_databuf[18] = 0x0;  // CRC16
     389                m_databuf[19] = 0x0;  // CRC16
     390                m_datalen_snd = 20;
     391            break;
     392            ////////
     393            case 16:        // CMD16 : set block size
     394                    if (m_sdstate != SD_IDLE && data == 512)
     395            {
     396                            m_databuf[0] = 0x00;
     397                            m_datalen_snd = 1;
     398                    } // else illegal command
     399                    break;
     400            ////////
     401                case 17:        // CMD17 : read data block
     402            {
     403                        int ret;
     404                        if (m_sdstate == SD_IDLE) // return illegal command
     405                {
     406                                return;
     407                        }
     408                        if (data >= m_device_size) // return "out of range"
     409                {
     410                                std::cerr << name() << " read: request " << data
     411                                          << " past end of file " << m_device_size << std::endl;
     412                                m_databuf[0] = 0x00; // R1 OK
     413                                m_databuf[1] = 0x08; // error tocken "out of range"
     414                                m_datalen_snd = 2;
     415                                return;
     416                        }
     417                do
     418                {
     419                    if (lseek(m_fd, data, SEEK_SET) < 0)
     420                    {
     421                                        std::cerr << name() << " lseek: " <<
     422                                        strerror(errno) << std::endl;
     423                                        m_databuf[0] = 0x00; // R1 OK
     424                        m_databuf[1] = 0x02; // error tocken "CC err"
     425                        m_datalen_snd = 2;
     426                        return;
     427                    }
     428                                ret = read(m_fd, &m_databuf[2], 512);
     429                } while (ret < 0 && errno == EINTR);
     430                if (ret < 0)
     431                {
     432                    std::cerr << name() << " read: " << strerror(errno) << std::endl;
     433                    m_databuf[0] = 0x00; // R1 OK
     434                    m_databuf[1] = 0x04; // error tocken "card ECC failed"
     435                    m_datalen_snd = 2;
     436                    return;
     437                }
     438                m_databuf[514] = m_databuf[515] = 0; // XXX CRC
     439                m_databuf[0] = 0x0; // R1
     440                m_databuf[1] = 0xfe; // start block tocken
     441                m_datalen_snd = 516;
     442            }
     443            break;
     444            ////////
     445            case 24:         // CMD 24 : write data block
     446                {
     447                        if (m_sdstate == SD_IDLE)  // return illegal command
     448                {
     449                    return;
     450                }
    392451#ifdef SOCLIB_MODULE_DEBUG
    393452        std::cout << name() << " new cmd write " << std::dec << (int)cmd << " args " << std::hex << data << std::endl;
    394453#endif
    395                 m_databuf[0] = 0x0; // R1
    396                 m_datalen_snd = 1;
    397                 m_datalen_rcv = 512 + 2 + 1; // data + tocken + CRC
    398                 break;
    399               }
    400             case 55:
    401                 // app-specific command follow
    402                 m_acmd = true;
    403                 m_databuf[0] = (m_sdstate == SD_IDLE) ? 0x1 : 0x0;
    404                 m_datalen_snd = 1;
    405                 break;
    406             case 58:
    407                 // send OCR
    408                 m_databuf[4] = (m_sdstate == SD_IDLE) ? 0x1 : 0x0; // R1
    409                 m_databuf[3] = 0x80; // power up complete, SDSC
    410                 m_databuf[2] = 0xff; // all voltages supported
    411                 m_databuf[1] = 0x00;
    412                 m_databuf[0] = 0x00;
    413                 m_datalen_snd = 5;
    414                 break;
    415             default:
    416                 std::cout << name() << " unknown cmd " << std::dec
    417                     << (int)cmd << std::endl;
    418                 break; // return illegal command
     454                m_databuf[0] = 0x0; // R1
     455                m_datalen_snd = 1;
     456                m_datalen_rcv = 512 + 2 + 1; // data + tocken + CRC
     457                }
     458                    break;
     459            ////////
     460                case 55:          // CMD55 : app-specific command follow
     461            m_acmd = true;
     462            m_databuf[0] = (m_sdstate == SD_IDLE) ? 0x1 : 0x0;
     463            m_datalen_snd = 1;
     464            break;
     465            ////////
     466            case 58:         // CMD 58 : send OCR
     467                    m_databuf[4] = (m_sdstate == SD_IDLE) ? 0x1 : 0x0; // R1
     468                    m_databuf[3] = 0x80; // power up complete, SDSC
     469                    m_databuf[2] = 0xff; // all voltages supported
     470                    m_databuf[1] = 0x00;
     471                    m_databuf[0] = 0x00;
     472                    m_datalen_snd = 5;
     473            break;
     474            ////////
     475            default:         // return illegal command
     476                        std::cout << name() << " unknown cmd " << std::dec << (int)cmd << std::endl;
     477            break;
    419478            }
    420479        }
    421 }
    422 
     480}  // end  handle_sdmmc_cmd()
     481
     482///////////////////////////////////////////////////////////
    423483void SdMMC::handle_sdmmc_write(uint8_t cmd, uint32_t data)
    424484{
     
    428488        std::cout << name() << " cmd write " << std::dec << (int)cmd << " args " << std::hex << data << std::endl;
    429489#endif
    430         switch(cmd) {
    431             case 24:
    432               {
    433                 int ret;
    434                 // write data block
    435                 assert(m_sdstate != SD_IDLE && "can't write in idle state");
    436                 if (data >= m_device_size) {
    437                         std::cerr << name() << " write: request " << data
    438                             << " past end of file " << m_device_size << std::endl;
    439                         m_databuf[0] = 0xd; // write error
    440                         m_datalen_snd = 1;
    441                         return;
    442                 }
    443                 do {
    444                         if (lseek(m_fd, data, SEEK_SET) < 0) {
    445                                 std::cerr << name() << " lseek: " <<
    446                                   strerror(errno) << std::endl;
    447                                 m_databuf[0] = 0xd; // write error
    448                                 m_datalen_snd = 1;
    449                                 return;
    450                         }
    451                         ret = write(m_fd, &m_databuf[1], 512);
    452                 } while (ret < 0 && errno == EINTR);
    453                 if (ret < 0) {
    454                         std::cerr << name() << " write: " <<
    455                           strerror(errno) << std::endl;
    456                         m_databuf[0] = 0xd; // write error
    457                         m_datalen_snd = 1;
    458                         return;
    459                 }
    460                 m_databuf[0] = 0x5; // write complete
    461                 m_databuf[1] = 0x0; // busy
    462                 m_datalen_snd = 2;
     490        switch(cmd)
     491    {
     492            case 24:     // CMD24 : write data block
     493            {
     494            int ret;
     495            assert(m_sdstate != SD_IDLE && "can't write in idle state");
     496                    if (data >= m_device_size)
     497            {
     498                std::cerr << name() << " write: request " << data
     499                          << " past end of file " << m_device_size << std::endl;
     500                m_databuf[0] = 0xd; // write error
     501                m_datalen_snd = 1;
     502                return;
     503            }
     504            do
     505            {
     506                if (lseek(m_fd, data, SEEK_SET) < 0)
     507                {
     508                    std::cerr << name() << " lseek: " << strerror(errno) << std::endl;
     509                    m_databuf[0] = 0xd; // write error
     510                    m_datalen_snd = 1;
     511                    return;
     512                }
     513                ret = write(m_fd, &m_databuf[1], 512);
     514            }
     515            while (ret < 0 && errno == EINTR);
     516            if (ret < 0)
     517            {
     518                std::cerr << name() << " write: " << strerror(errno) << std::endl;
     519                m_databuf[0] = 0xd; // write error
     520                m_datalen_snd = 1;
     521                return;
     522            }
     523            m_databuf[0] = 0x5; // write complete
     524            m_databuf[1] = 0x0; // busy
     525            m_datalen_snd = 2;
     526            }
    463527                break;
    464               }
    465528            default:
    466                 std::cerr << name() << " unkown write cmd " << std::dec <<
    467                     (int)cmd << std::endl;
    468                 m_databuf[0] = 0xd; // write error;
    469                 m_datalen_snd = 1;
     529        {
     530                    std::cerr << name() << " unkown write cmd " << std::dec << (int)cmd << std::endl;
     531            m_databuf[0] = 0xd; // write error;
     532            m_datalen_snd = 1;
     533        }
    470534        }
    471535        return;
    472536}
    473537
    474 //////////////////////////////////////////////////////////////////////////////
     538//////////////////////////////////////////////////////////////
    475539SdMMC::SdMMC( sc_core::sc_module_name              name,
    476                                 const std::string                    &filename,
    477                                 const uint32_t                       latency)
     540              const std::string                    &filename,
     541              const uint32_t                       latency)
    478542
    479543: caba::BaseModule(name),
     
    516580        const char* spi_str[] =
    517581    {
    518                 "S_IDLE",
    519                 "S_RECEIVE_CMD",
    520                 "S_RECEIVE_ARGS_START",
    521                 "S_RECEIVE_ARGS",
    522                 "S_RECEIVE_CRC",
    523                 "S_RECEIVE_DATA_START",
    524                 "S_RECEIVE_DATA",
    525                 "S_SEND_DATA",
    526                 "S_NOP",
     582        "S_IDLE",
     583        "S_RECEIVE_CMD",
     584        "S_RECEIVE_ARGS_START",
     585        "S_RECEIVE_ARGS",
     586        "S_RECEIVE_CRC",
     587        "S_RECEIVE_DATA_START",
     588        "S_RECEIVE_DATA",
     589        "S_SEND_DATA",
     590        "S_NOP",
    527591        };
    528592        if (spi_clk != p_spi_clk.read()) {
Note: See TracChangeset for help on using the changeset viewer.