Ignore:
Timestamp:
Oct 22, 2013, 10:46:43 PM (11 years ago)
Author:
bouyer
Message:

Implement single block write

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

Legend:

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

    r552 r555  
    8585
    8686    void handle_sdmmc_cmd(uint8_t, uint32_t);
    87     void handle_sdmmc_write();
     87    void handle_sdmmc_write(uint8_t, uint32_t);
    8888
    8989    //  Master FSM states
     
    9494    S_RECEIVE_ARGS       = 3,
    9595    S_RECEIVE_CRC        = 4,
    96     S_RECEIVE_DATA       = 5,
    97     S_RECEIVE_DATA_END   = 6,
     96    S_RECEIVE_DATA_WAIT  = 5,
     97    S_RECEIVE_DATA       = 6,
    9898    S_SEND_DATA          = 7,
    99     S_NOP                = 8,
    10099    };
    101100
  • trunk/modules/sdmmc/caba/source/src/sdmmc.cpp

    r552 r555  
    1 /* -*- c++ -*-
     1/*
     2 -*- c++ -*-
    23 *
    34 * SOCLIB_LGPL_HEADER_BEGIN
     
    4950    }
    5051    if (p_spi_ss.read()) {
     52        if (r_spi_fsm != S_IDLE) {
     53                std::cerr << name() << " deselect but not idle, state "
     54                << std::dec << r_spi_fsm << " last cmd " << (int)r_command
     55                << " args " << std::hex << r_args << std::dec
     56                << " bitcount " << (int)r_spi_bitcount.read()
     57                << " idx " << m_data_idx << " len_snd " << m_datalen_snd
     58                << " len_rcv " << m_datalen_rcv << std::endl;
     59        }
    5160        r_spi_fsm  = S_IDLE;
    5261        return;
     
    7382                                r_spi_fsm = S_RECEIVE_ARGS_START;
    7483                        } else {
    75 #ifdef SOCLIB_MODULE_DEBUG
     84#ifdef SOCLIB_MODULE_DEBUG0
    7685                                std::cout << name() << " S_RECEIVE_CMD " << std::hex << ((int)((r_command << 1) | p_spi_mosi) & 0xff) << std::endl;
    7786#endif
     
    125134                                r_spi_fsm = S_SEND_DATA;
    126135                                m_data_idx++;
    127 #ifdef SOCLIB_MODULE_DEBUG
     136#ifdef SOCLIB_MODULE_DEBUG0
    128137                        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;
    129138#endif
    130139                        } else if (m_datalen_rcv != 0) {
    131                                 r_spi_fsm = S_RECEIVE_DATA;
     140                                r_spi_fsm = S_RECEIVE_DATA_WAIT;
    132141                                r_spi_bitcount = 7;
    133142                                m_data_idx = 0;
     
    141150        }
    142151        break;
     152    case S_RECEIVE_DATA_WAIT:
     153        if (p_spi_clk.read() == 1 && r_spi_clk.read() == 0) {
     154            uint8_t s_data;
     155            // rising edge
     156            s_data = (m_databuf[0] << 1) | p_spi_mosi;
     157            m_databuf[0] = s_data;
     158            r_spi_bitcount = r_spi_bitcount - 1;
     159            if (r_spi_bitcount == 0) {
     160#ifdef SOCLIB_MODULE_DEBUG
     161        std::cout << name() << " S_RECEIVE_DATA_WAIT " << std::dec << (int)s_data << std::endl;
     162#endif
     163                    r_spi_bitcount = 7;
     164                    if (s_data == 0xfe) { // data start token
     165                        r_spi_fsm = S_RECEIVE_DATA;
     166                        m_data_idx = 1;
     167                    } else {
     168#ifdef SOCLIB_MODULE_DEBUG
     169                        std::cout << name() << " S_RECEIVE_DATA_WAIT " << std::hex << (int)s_data << std::endl;
     170#endif
     171                        r_spi_fsm = S_RECEIVE_DATA_WAIT;
     172                }
     173            }
     174        }
     175        break;
     176        case S_RECEIVE_DATA:
     177            if (p_spi_clk.read() == 1 && r_spi_clk.read() == 0) {
     178                // rising edge
     179                m_databuf[m_data_idx] = (m_databuf[m_data_idx] << 1) | p_spi_mosi;
     180                if (r_spi_bitcount == 0) {
     181                    m_data_idx++;
     182                    if (m_data_idx != m_datalen_rcv) {
     183                        r_spi_fsm = S_RECEIVE_DATA;
     184                        r_spi_bitcount = 7;
     185                    } else {
     186                        handle_sdmmc_write(r_command.read(), r_args.read());
     187                        if (m_datalen_snd > 0) {
     188                            r_spi_bitcount = 0; // SEND_DATA will reset it
     189                            r_spi_fsm = S_SEND_DATA;
     190                            m_data_idx = 0;
     191                        } else {
     192                            r_spi_fsm = S_IDLE;
     193                        }
     194                    }
     195                } else {
     196                        r_spi_bitcount = r_spi_bitcount - 1;
     197                }
     198            }
     199            break;
    143200    }
    144201}  // end transition
     
    177234        cmd &= 0x3f;
    178235        if (m_acmd) {
    179 #ifdef SOCLIB_MODULE_DEBUG
     236#ifdef SOCLIB_MODULE_DEBUG0
    180237        std::cout << name() << " new acmd " << std::dec << (int)cmd << " args " << std::hex << data << " crc " << (int)r_cmdcrc << std::endl;
    181238#endif
     
    209266            }
    210267        } else {
    211 #ifdef SOCLIB_MODULE_DEBUG
     268#ifdef SOCLIB_MODULE_DEBUG0
    212269        std::cout << name() << " new cmd " << std::dec << (int)cmd << " args " << std::hex << data << " crc " << (int)r_cmdcrc << std::endl;
    213270#endif
     
    323380                break;
    324381              }
     382            case 24:
     383              {
     384                // write data block
     385                if (m_sdstate == SD_IDLE) {
     386                        // return illegal command
     387                        return;
     388                }
     389#ifdef SOCLIB_MODULE_DEBUG
     390        std::cout << name() << " new cmd write " << std::dec << (int)cmd << " args " << std::hex << data << std::endl;
     391#endif
     392                m_databuf[0] = 0x0; // R1
     393                m_datalen_snd = 1;
     394                m_datalen_rcv = 512 + 2 + 1; // data + tocken + CRC
     395                break;
     396              }
    325397            case 55:
    326398                // app-specific command follow
     
    346418}
    347419
    348 void SdMMC::handle_sdmmc_write()
    349 {
     420void SdMMC::handle_sdmmc_write(uint8_t cmd, uint32_t data)
     421{
     422        m_datalen_rcv = 0;
     423        cmd &= 0x3f;
     424#ifdef SOCLIB_MODULE_DEBUG
     425        std::cout << name() << " cmd write " << std::dec << (int)cmd << " args " << std::hex << data << std::endl;
     426#endif
     427        switch(cmd) {
     428            case 24:
     429              {
     430                int ret;
     431                // write data block
     432                assert(m_sdstate != SD_IDLE && "can't write in idle state");
     433                if (data >= m_device_size) {
     434                        std::cerr << name() << " write: request " << data
     435                            << " past end of file " << m_device_size << std::endl;
     436                        m_databuf[0] = 0xd; // write error
     437                        m_datalen_snd = 1;
     438                        return;
     439                }
     440                do {
     441                        if (lseek(m_fd, data, SEEK_SET) < 0) {
     442                                std::cerr << name() << " lseek: " <<
     443                                  strerror(errno) << std::endl;
     444                                m_databuf[0] = 0xd; // write error
     445                                m_datalen_snd = 1;
     446                                return;
     447                        }
     448                        ret = write(m_fd, &m_databuf[1], 512);
     449                } while (ret < 0 && errno == EINTR);
     450                if (ret < 0) {
     451                        std::cerr << name() << " write: " <<
     452                          strerror(errno) << std::endl;
     453                        m_databuf[0] = 0xd; // write error
     454                        m_datalen_snd = 1;
     455                        return;
     456                }
     457                m_databuf[0] = 0x5; // write complete
     458                m_databuf[1] = 0x0; // busy
     459                m_datalen_snd = 2;
     460                break;
     461              }
     462            default:
     463                std::cerr << name() << " unkown write cmd " << std::dec <<
     464                    (int)cmd << std::endl;
     465                m_databuf[0] = 0xd; // write error;
     466                m_datalen_snd = 1;
     467        }
    350468        return;
    351469}
     
    401519                "S_RECEIVE_ARGS",
    402520                "S_RECEIVE_CRC",
     521                "S_RECEIVE_DATA_START",
    403522                "S_RECEIVE_DATA",
    404                 "S_RECEIVE_DATA_END",
    405523                "S_SEND_DATA",
    406524                "S_NOP",
Note: See TracChangeset for help on using the changeset viewer.