title: STM32F4Discovery - SDCard sector reading
body: <p>long time I try to implement FatFs module, but its gets crazy after every sd card formatting. (different errors each time). I've decided to go lower and check my SDCard drivers and I've noticed that when I read some (but ALWAYS THE SAME) of sector's field I receive garbage and I can't interpret it.</p>
  
  <p>My driver's test looks like below:</p>
  
  <pre><code>#if 1 //SD Card Test
  uint16_t i;
  uint8_t CSD; //card capacity
  uint8_t CID; //card id
  uint8_t Buffer[512]; //this buffer is written to card
  for(i=0; i&lt;512;i++)
  {
      Buffer[i]=i;
  }
  SD_CardInit();          //card initialization
  CSD = SD_Read_CSD();    //read capacity
  CID = SD_Read_CSD();    //read ID
  SD_WriteBlock(0x200, Buffer, 512);  //write Buffer under 0x200 (512) address
  SD_Read_Block(0x200);               //read buffer from 0x200
  CSD = 0;
  #endif
  </code></pre>
  
  <p>I put breakpoint at CSD = 0; line. Here is what I get after writing and reading the same address:<br></p>
  
  <p><a href="https://i.stack.imgur.com/N0nhq.jpg" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/N0nhq.jpg" alt="enter image description here"></a></p>
  
  <p>Buffer is filled with numbers from 0 to 255 (two times, because of overflow).
  To reduce noise I've minimized SPI frequency to minimum. Nothing changed. But in fact that wrong numbers appears ALWAYS under the same table index and with the same values suggest that is no problem with noise, but some error.
  It looks like drivers works properly, because they write and read most of the fields, but always in the same it answer with garbage. I can't find any trace what could I do wrong. Do I write under some permitted address? When I read any random address I receive the same result.</p>
  
  <p>I include functions: read and write (SD_Sector is a global buffer)</p>
  
  <p>WRITE</p>
  
  <pre><code>// Write block of data to the SD card
  // input:
  //   addr - start address of the block (must be power of two)
  //   pBuf - pointer to the buffer with data
  //   len - buffer length
  // return: SDR_xxx
  SDResult_TypeDef SD_WriteBlock(uint32_t addr, uint8_t *pBuf, uint32_t len)
  {
      uint32_t wait;
      uint16_t CRC_loc; // Calculated CRC16 of the block
      uint16_t i;
      uint8_t cmdres, response, temp;
  
      SDCard_privChipSelect();
  
      // Calculate 16-bit CRC
      CRC_loc = CRC16_buf(pBuf,len);
  
      // SDSC card uses byte unit address and
      // SDHC/SDXC cards use block unit address (1 unit = 512 bytes)
      // For SDHC/SDXC card addr must be converted to block address
  #if 0 //TODO: reconsider PiechotM, do not work with that line
      if (SD_CardType == SD_HIGH_CAPACITY_SD_CARD) addr &gt;&gt;= 9;
  #endif
      response = SD_SendCmd(SD_CMD_WRITE_SINGLE_BLOCK,addr); // CMD24
  
      if (response != 0x00)
      {
          // Something wrong happened, do nothing
          return response; // SD_CMD_READ_SINGLE_BLOCK command returns bad response
      }
      else
      {
          wait = 0; response = 0;
          while (++wait &lt;= 512/*0x1ff*/ &amp;&amp; response == 0xff)
          {
              temp = 0xFF;
              SD_Send( temp );
              response = SD_Recv();
          }
          if (wait &gt;= 0x1ff) return 0xff;
  
          // Send start block token
          SD_Send(SD_TOKEN_START_BLOCK);
  
          // Send data block
          for (i = 0; i &lt; len; i++)
          {
              uint8_t temp;
  
              SD_Send( *pBuf++ );
          }
  
          // Send CRC
          SD_Send(CRC_loc &gt;&gt; 8);
          SD_Send((uint8_t)CRC_loc);
      }
  
      // Get response from the SD card
      cmdres = SD_Recv();
      cmdres &amp;= 0x1f;
      if (cmdres != SD_TOKEN_DATA_ACCEPTED)
      {
          // Data block rejected by SD card for some reason
          // Release SD card
          SD_Send(0xff);
  
          SDCard_privChipDeSelect();
  
          if (cmdres &amp; SD_TOKEN_WRITE_CRC_ERROR) return SDR_WriteCRCError;
          if (cmdres &amp; SD_TOKEN_WRITE_ERROR) return SDR_WriteErrorInternal;
          return SDR_WriteError;
      }
  
      // Wait while the SD card is busy by data programming
      wait = 0x7fff; // Recommended timeout is 250ms (500ms for SDXC) 
      do
      {
          cmdres = SD_Recv();
      } while (cmdres == 0 &amp;&amp; --wait);
  
      // Provide extra 8 clocks for the card (from SanDisk specification)
      SD_Send(0xff);
  
      // Release SD card
      SDCard_privChipDeSelect();
  
      // Must send at least 74 clock ticks to SD Card
      for (wait = 0; wait &lt; 10; wait++) SD_Send(0xff);
  
      return SDR_Success;
  }
  </code></pre>
  
  <p>READ</p>
  
  <pre><code>// return:
  // 0x00 -- read OK
  // 0x01..0xfe -- error response from CMD17
  // 0xff -- timeout
  uint8_t SD_Read_Block(uint32_t addr)
  {
      uint32_t wait;
      uint16_t i;
      uint8_t response;
  
      SDCard_privChipSelect();
  
  #if 0 //TODO: reconsider PiechotM, do not work with that line
      if (SD_CardType != SD_HIGH_CAPACITY_SD_CARD) addr &lt;&lt;= 9; // Convert block number to byte offset
  #endif
      response = SD_SendCmd(SD_CMD_READ_SINGLE_BLOCK,addr); // CMD17
      if (response != 0x00)
      {
          // Something wrong happened, fill buffer with zeroes
          for (i = 0; i &lt; 512; i++) SD_sector[i] = 0;
          return response; // SD_CMD_READ_SINGLE_BLOCK command returns bad response
      }
      else
      {
          wait = 0; response = 0;
          while (++wait &lt;= 0x1ff &amp;&amp; response != 0xfe) response = SD_Recv();
          if (wait &gt;= 0x1ff) return 0xff;
          // Read 512 bytes of sector
          for (i = 0; i &lt; 512; i++) SD_sector[i] = SD_Recv();
      }
  
      // Receive 16-bit CRC (some cards demand this)
      SD_CRC16_rcv  = SD_Recv() &lt;&lt; 8;
      SD_CRC16_rcv |= SD_Recv();
  
      // Calculate CRC16 of received buffer
      SD_CRC16_cmp = CRC16_buf(&amp;SD_sector[0],512);
  
      SDCard_privChipDeSelect();
  
      // Must send at least 74 clock ticks to SD Card
      for (wait = 0; wait &lt; 8; wait++) SD_Send(0xff);
  
      return 0;
  }
  
  /* -------------------- WRITE SECTION ------------------------------*/
  /*               Lonely Wolf library imported                       */
  /*------------------------PiechotM----------------------------------*/
  
  // Send buffer to the SD card
  // input:
  //   pBuf - pointer to the buffer
  //   len - length of the buffer
  // return: last response from SD card
  void SD_WriteBuf(uint8_t *pBuf, uint16_t len)
  {
      while (len--) SD_Send(*pBuf++);
  }
  </code></pre>
  
  <p>I will be very thankful for your help!</p>
  
  <p>Best regards,</p>
  
  <p>Maks Piechota</p>