This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

app_sdc_init() not allowed to use XL1 (P0.0) as sck pin? / Proper setup of SD Card with other SPI usage

NRF52840, S140, SDK 14.2

I am trying to write to an SD Card. But whenever I insert the card, I get a failure on ASSERT. I believe this is because I am using P0.0 as the SCK pin, and anything &-ed with 0 is 0. 

Does this mean I am not allowed to use the 0.0 SCK pin? That seems wrong. Was this fixed in a later SDK update? 

When I comment out the &&  p_config->sck_pin, I no longer get the Assert. however, I get this error instead (triggered from nrf_drv_spi_init()) 

which is NRF_ERROR_INVALID_STATE (Invalid state, operation disallowed in this state)

I suspect this is because now that I am trying to use the SD Card, there are 2 SPI resources on the system. I configured the SD Card as follows:

Whereas the other SPI device was configured "normally":

 (i do app_error_check in the fn that calls spi_config). 

This error happens and the application freezes immediately when I use SPI 0 for the second SPI device. When I use SPI 1 for the second SPI device without changing the GPIO pins, I get strange behavior: my main loop stops running entirely (seems to hit power manage and just stop? but I have interrupts coming in), and garbage data (instead of the data that is normally sent) goes out on my SPI line to the second device. I am able to still connect over BLE though. Why is this happening?

I read this and this. My other questions:

  1. What SPI instance is the SD Card using? SPI 0? 
  2. Is each SPI instance supposed to use its own separate GPIO?

If this is the case that I have to use a separate SPI instance with separate GPIO, it is a bit disappointing that NRF doesn't let you use SPI for its intended purpose (multiplexing data on a bus). I am a little low on board space and would prefer not to route 3 extra lines if possible. Please advise. What should my path forward be, to use SPI with SD card and a different device?

Thank you!

  • The issue has not happened for a few days now. Not sure what the issue was. But the SD card is working great. You can probably consider this closed. Thank you again for your help. 

  • Thanks a lot for the reply! Your notes are very helpful. I was able to get data written with my custom board, but for reasons you mentioned, the example does not work with my custom board very well.

    Are you sure that it was this change that caused it to no longer initialize?

    Turns out that it does actually sometimes (and mostly all the time now) initialize properly. But it seems like sometimes the card does not get mounted properly if it gets pushed in too fast? Does that make sense to you? The problem has become sporadic and seems loosely correlated with how gently I push in the SD card to the connector.

    By the way, is there any way to detect whether the SD Card is full? I know how to read the capacity, but I wasn't sure if that is total capacity (regardless of how full) or capacity remaining. 

    Thanks!

  • Are you using some card detect signal from the socket to detect the card? Do you immediately initialize the card when detecting the signal?

    You may try introducing a short delay, to allow the card to fully insert, or to avoid signal bounce issues. You can use app_timer for this purpose. Start the timer on the first reception of the "card detected" signal, check that the signal is still in the "card detected" state at timeout, and then initialize the card.

  • Thank you, Jorgen.

    I do use a card detect signal (card detect pin goes low when card is inserted), and I have a 1s timer between insertion detection and initialization. i want to say there were more issues before I put the timer in, but there are still issues sometimes. I have built in an LED warning light to let the user know they should remove and re-insert if it fails to initialize or mount. 

    1) Can you answer this question too?

    By the way, is there any way to detect whether the SD Card is full? I know how to read the capacity, but I wasn't sure if that is total capacity (regardless of how full) or capacity remaining.

    2) There seems to be a bug in the SDC part of the SDK: 

    The code ASSERTS if sdc_cmd returns NRF_ERROR_BUSY. Adding line 10 below (which is the condition that causes sdc_cmd to return this error) fixes the Assert.

    ret_code_t app_sdc_block_read(uint8_t * p_buf, uint32_t block_address, uint16_t block_count)
    {
        ASSERT(p_buf);
    
        if (m_cb.state.op == SDC_UNINITIALIZED)
        {
            return NRF_ERROR_INVALID_STATE;
        }
        if (m_cb.state.op != SDC_OP_IDLE
    			|| m_cb.state.bus_state != SDC_BUS_IDLE)	// WARNING: SDK mod
        {
            return NRF_ERROR_BUSY;
        }
        if (block_count == 0)
        {
            return NRF_ERROR_INVALID_PARAM;
        }
    
        m_cb.state.op = SDC_OP_READ;
    
        if (!m_cb.info.type.sdhc)
        {
            m_cb.state.rw_op.address = block_address * SDC_SECTOR_SIZE;
        }
        else
        {
            m_cb.state.rw_op.address = block_address;
        }
        m_cb.state.rw_op.buffer = p_buf;
        m_cb.state.rw_op.block_count = block_count;
        m_cb.state.rw_op.blocks_left = block_count;
    
        PT_INIT(&m_cb.state.pt);
        uint8_t command = (block_count > 1) ? CMD18 : CMD17;
        ret_code_t err_code = sdc_cmd(command, m_cb.state.rw_op.address, SDC_R1);
        APP_ERROR_CHECK(err_code);
    
        return NRF_SUCCESS;
    }

    1. You can use f_getfree() for this. I used the following code with the FatFs example in the latest SDK:
      FATFS *p_fs;
      DWORD fre_clust, fre_sect, tot_sect;
      
      /* Get volume information and free clusters of drive 1 */
      res = f_getfree("", &fre_clust, &p_fs);
      APP_ERROR_CHECK(res);
      
      /* Get total sectors and free sectors */
      tot_sect = (p_fs->n_fatent - 2) * p_fs->csize;
      fre_sect = fre_clust * p_fs->csize;
      
      
      /* Print the free space (assuming 512 bytes/sector) */
      NRF_LOG_INFO("%10lu KiB total drive space.\n%10lu KiB available.\n", tot_sect / 2, fre_sect / 2);

      This will give the remaining capacity in number of clusters, so it will depend a bit on the cluster size. This is the output I get with a 8GB SD-card:
      <info> app: FATFS example started.
      <info> app: Initializing disk 0 (SDC)...
      <info> app: Capacity: 7580 MB
      <info> app: Mounting volume...
      <info> app:    7760896 KiB total drive space.
         7760800 KiB available.
      <info> app: 
       Listing directory: /
          33578  NORDIC.TXT<info> app: Writing to file NORDIC.TXT...
      <info> app: 250 bytes written.
      
    2. How do you get into the state where this error is reported? I cannot remember to have seen this when running the FatFs examples. Note that there are a bug related to reinitialization in older SDK versions, which may be related. This is fixed in the latest SDK release.
Related