SPI模式定时的microSD卡

时间:2016-02-25 08:53:17

标签: c embedded atmel

我正在以SPI模式在SD卡上写入和读取值。写入和读取512字节块的频率设置为10Mhz。对于写入块,它需要大约5ms,块之间的时序大约是10ms。

有没有办法提高写作速度?

void sd_card_write_block(uint16 blockNumber, uint8* buffer)
{
  uint16 blockLow = 0;
  uint16 blockHigh = 0;
  uint8 dummy = 0;
  uint8 result = 0;
  uint8 data_block_start_byte = 0;
  uint8 write_command[SD_CMD_SIZE] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
  uint8 dummy_buffer[DUMMY_BUFFER_LENGTH] = {0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF};
  uint8 i = 0;
  uint8 check_response[CHECK_RESPONSE_SIZE] = {0x00, 0x00, 0x00};
  uint8 check_response1[CHECK_RESPONSE_SIZE] = {0x00, 0x00, 0x00};
  uint8 r1 = 0;
  uint16 retry = 0;
  uint8 response1 = 0;

  dummy = 0xFF;
  //initialize the dummy buffer to keep MOSI pin High
  for(i = 0; i < DUMMY_BUFFER_LENGTH; i++)
  {
    dummy_buffer[i] = 0xFF;
  }

  //set CS pin low
  spi_select_slave( &spi_master_instance, &slave, true);

  //send three clock cycles with MOSI HIGH (Ncs)
  spi_write_buffer_wait( &spi_master_instance, dummy_buffer, NCS_LENGTH);

  //block size was set in sd_init
  blockLow = ((blockNumber & 0x003F) << 9);
  blockHigh = ((blockNumber & 0xFFC0) >> 7);

  //send SD CMD24(WRITE_SINGLE_BLOCK) to write the data to SD card
  write_command[0] = 0x58;

  //high block address bits, blockHigh HIGH and LOW
  write_command[1] = (blockHigh >> 0x08);

  write_command[2] = (blockHigh & 0xFF);
  //low block address bits, blockLow HIGH and LOW
  write_command[3] = (blockLow >> 0x08);
  write_command[4] = (blockLow & 0xFF);

  //checksum is no longer required but send 0xFF
  write_command[5] = 0xFF;

  spi_write_buffer_wait( &spi_master_instance, write_command, SD_CMD_SIZE);


  spi_transceive_buffer_wait( &spi_master_instance, dummy_buffer, check_response, CHECK_RESPONSE_SIZE);

  //send three clock cycles with MOSI High
  spi_write_buffer_wait( &spi_master_instance, dummy_buffer, DUMMY_BUFFER_LENGTH);

  //set bit 0 to 0 which indicates the beginning of the data block
  data_block_start_byte = DATA_BLOCK_START_TOKEN;
  spi_transceive_buffer_wait( &spi_master_instance, &data_block_start_byte, &result, SD_RESPONSE_SIZE);


  /*takes so long because its similar to transreceivea and it discards the rx*/
  spi_write_buffer_wait( &spi_master_instance, buffer, SD_BLOCK_LENGTH);


  //read the microSD card response
  spi_transceive_buffer_wait( &spi_master_instance, dummy_buffer, check_response1, CHECK_RESPONSE_SIZE);

  do
   {
     // write dummy byte
     spi_transceive_buffer_wait( &spi_master_instance, &dummy, &response1, SD_RESPONSE_SIZE);

     r1 = response1;
     // do retry counter
     retry++;
     if(retry > MAX_TIMEOUT)
     {
       spi_select_slave( &spi_master_instance, &slave, false);
       break;
     }
   }
   while(r1 == END_OF_BLOCK_RESPONSE);
  //set the CS High
  spi_select_slave( &spi_master_instance, &slave, false);
}

3 个答案:

答案 0 :(得分:1)

你不能,至少不是。原因是SPI模式本身就是瓶颈。所以,你可以在这里和那里使用一些技巧来提高速度,但你真的不会从中受益。如果你真的需要那么快的话,我建议你使用SDIO(它没有你想象的那么复杂)。如果您正在使用AVR,请尝试使用xmega阵容(请不要引用我的内容,因为我使用的是ARM,因此我没有完全了解AVR,或者完全切换到另一个阵容。

答案 1 :(得分:0)

为了获得更高的写入速度,您需要:
- 使用更快的时钟
- 使用更宽的公共汽车
- 一次写出更大的块(2k或4k)

换句话说,您几乎需要使用SDIO规范。

还有一些方法可以开始一个大的顺序事务,而不是在收到所有数据之后结束它(但可能是在SDIO规范而不是SPI命令接口)。这些提示告诉控制器它可以准备一大部分闪存,而不是提交写缓冲区直到它满了。

即使这样,你偶尔会有“非常长”的写入周期,所以你不能依靠SD卡实时流出高速数据而不需要缓冲区来处理延迟时间。

答案 2 :(得分:0)

您应该发布了spi_write_buffer_wait代码,但请考虑以下内容:

重新排列实际写入函数中发送数据的内容。想一想。您必须等到SD卡指示您,该字节已成功写入。使用此“无用”等待时间来准备下一个数据。

/* write a single block */
for ( i = MMC_BLOCKLEN; i > 0; i-- ) {
    uint8_t data = *buffer;
    buffer++;
    wait_till_send_done();
    xmit_byte ( data );
}
wait_till_send_done();

在那里准备要发送的字节,并且在开始等待SD卡指示其成功写入前一个字节之前,将指针向前移动

检查生成的ASM代码也是个好主意......

如果您要写入超过512字节的数据,请考虑使用多块写入(例如一次4k块)。

通常SD卡的内部块大小超过512字节。因此要写入512字节,它们必须在内部读取例如4k,交换你的512字节并将所有内容写回...所以一次写入更多数据总是一个好主意......