Changeset 1052 for trunk/modules/sdmmc/caba/source
- Timestamp:
- Jun 21, 2017, 10:50:42 AM (7 years ago)
- Location:
- trunk/modules/sdmmc/caba/source
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/modules/sdmmc/caba/source/include/sdmmc.h
r574 r1052 55 55 56 56 // Registers 57 int spi_fsm; // SPI state register58 int spi_shiftreg;// data shift in/out59 int spi_bitcount;60 int spi_clk;61 int spi_mosi_previous; // sampled MOSI value57 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 62 62 63 uint8_t command;63 uint8_t command; 64 64 uint32_t args; 65 uint8_t cmdcrc; 65 uint8_t cmdcrc; 66 66 67 int m_fd; // File descriptor 67 68 uint64_t m_device_size; // Total number of blocks 68 69 const uint32_t m_latency; // device latency 69 70 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 73 78 uint32_t m_data_idx; 74 bool m_acmd;// next command will be acmd75 int m_sdstate;// sdcard internal state79 bool m_acmd; // next command will be acmd 80 int m_sdstate; // sdcard internal state 76 81 77 82 // sd states 78 enum { 79 SD_IDLE = 0, 80 SD_READY = 1, 83 enum 84 { 85 SD_IDLE = 0, 86 SD_READY = 1, 81 87 }; 82 88 … … 88 94 89 95 // Master FSM states 90 enum { 96 enum 97 { 91 98 S_IDLE = 0, 92 99 S_RECEIVE_CMD = 1, -
trunk/modules/sdmmc/caba/source/src/sdmmc.cpp
r709 r1052 46 46 { 47 47 spi_fsm = S_IDLE; 48 49 48 m_acmd = false; 49 m_sdstate = SD_IDLE; 50 50 return; 51 51 } 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; 65 68 } 66 69 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 { 84 92 #ifdef SOCLIB_MODULE_DEBUG0 85 93 std::cout << name() << " S_RECEIVE_CMD " << std::hex << (int)command << std::endl; 86 94 #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; 128 144 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++; 138 156 #ifdef SOCLIB_MODULE_DEBUG0 139 157 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; 140 158 #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 { 161 187 #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 { 188 std::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 { 169 198 #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 } 199 std::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; 202 256 break; 257 258 default: 259 p_spi_miso = !p_spi_ss.read(); 260 break; 203 261 } 204 262 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 218 264 spi_clk = p_spi_clk.read(); 219 265 spi_mosi_previous = p_spi_mosi; 266 220 267 } // end GenMealy() 221 268 222 269 223 ////////////////////// 270 //////////////////////////////////////////////////////// 224 271 void SdMMC::handle_sdmmc_cmd(uint8_t cmd, uint32_t data) 225 272 { 226 273 m_datalen_rcv = 0; 227 m_databuf[0] = 0x04; //illegal command228 m_datalen_snd = 1; 274 m_databuf[0] = 0x04; // default value : illegal command 275 m_datalen_snd = 1; // default value : 1 byte 229 276 230 277 if (m_sdstate == SD_IDLE) 231 278 m_databuf[0] |= 0x01; // idle 232 279 233 if ((cmd & 0x40) == 0) { 280 if ((cmd & 0x40) == 0) 281 { 234 282 //illegal command 235 283 return; 236 284 } 237 285 cmd &= 0x3f; 238 if (m_acmd) { 286 287 if (m_acmd) 288 { 239 289 #ifdef SOCLIB_MODULE_DEBUG0 240 290 std::cout << name() << " new acmd " << std::dec << (int)cmd << " args " << std::hex << data << " crc " << (int)cmdcrc << std::endl; 241 291 #endif 242 292 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 251 252 253 254 255 256 257 258 m_databuf[ 7] = 0; // vendor specific259 260 261 262 263 264 break;265 default:266 std::cout << name() << " unknown acmd " << std::dec267 << (int)cmd << std::endl;268 break; // return illegal command293 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 269 319 } 270 } else { 320 } 321 else 322 { 271 323 #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 } 324 std::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 } 392 451 #ifdef SOCLIB_MODULE_DEBUG 393 452 std::cout << name() << " new cmd write " << std::dec << (int)cmd << " args " << std::hex << data << std::endl; 394 453 #endif 395 396 397 398 break;399 }400 case 55: 401 //app-specific command follow402 403 404 405 406 case 58: 407 //send OCR408 m_databuf[4] = (m_sdstate == SD_IDLE) ? 0x1 : 0x0; // R1409 m_databuf[3] = 0x80; // power up complete, SDSC410 m_databuf[2] = 0xff; // all voltages supported411 m_databuf[1] = 0x00;412 m_databuf[0] = 0x00;413 m_datalen_snd = 5;414 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; 419 478 } 420 479 } 421 } 422 480 } // end handle_sdmmc_cmd() 481 482 /////////////////////////////////////////////////////////// 423 483 void SdMMC::handle_sdmmc_write(uint8_t cmd, uint32_t data) 424 484 { … … 428 488 std::cout << name() << " cmd write " << std::dec << (int)cmd << " args " << std::hex << data << std::endl; 429 489 #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 } 463 527 break; 464 }465 528 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 } 470 534 } 471 535 return; 472 536 } 473 537 474 ////////////////////////////////////////////////////////////// ////////////////538 ////////////////////////////////////////////////////////////// 475 539 SdMMC::SdMMC( sc_core::sc_module_name name, 476 477 540 const std::string &filename, 541 const uint32_t latency) 478 542 479 543 : caba::BaseModule(name), … … 516 580 const char* spi_str[] = 517 581 { 518 519 520 521 522 523 524 525 526 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", 527 591 }; 528 592 if (spi_clk != p_spi_clk.read()) {
Note: See TracChangeset
for help on using the changeset viewer.