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

SD card initialization failure sometimes

I'm designing a EEPROM type of memory using a SDCard. The write and read functions works fine, but the initialization does not work sometimes and it stays in a loop (because of the way the event handler is working). I'm using the 12.3 version of the SDK and the nRF51822. Does anybodi know how to fix it? I've already tried in different Cards, but the error is the same. 

#include "lk_types.h"

#include "lk_board_lk2.h"
#include "lk_gpio.h"

#include "lk_eeprom.h"
#include "lk_sd_card.h"
#include "lk_errors.h"
#include <stdlib.h>
#include "app_sdcard.h"
#include "lk_millis.h"
#include <string.h>
#include "nrf_drv_spi.h"
// #include "lk_eeprom_sdc.h"

#if defined DEBUG_MSG_SD_CARD
#include "lk_printf.h"
#include "lk_test_sd_card.h"
#endif

#if defined LK_TEST_EEPROM
#include <stdlib.h>
#include "lk_printf.h"
#endif

#define SDC_SCK_PIN     2  ///< SDC serial clock (SCK) pin.
#define SDC_MOSI_PIN    3  ///< SDC serial data in (DI) pin.
#define SDC_MISO_PIN    4  ///< SDC serial data out (DO) pin.
#define SDC_CS_PIN      30  ///< SDC chip select (CS) pin.

static const app_sdc_config_t sdc_cfg = {
	.mosi_pin = SDC_MOSI_PIN,
	.miso_pin = SDC_MISO_PIN,
	.sck_pin  = SDC_SCK_PIN,
	.cs_pin   = SDC_CS_PIN
};
#define SIZE_BLOCK 512
 uint32_t last_block= 0xFFFFFFFF;
uint8_t last_block_buff[SIZE_BLOCK];
volatile uint8_t lk_flag = 0;

void sdc_handler(sdc_evt_t const * p_event)
{
    switch(p_event->type)
    {
        case SDC_EVT_INIT:
            if (p_event->result != SDC_SUCCESS)
            {
                lk_flag = 0;

            }
            else
            {
                lk_flag = 1;
            }
        case SDC_EVT_READ:
            if (p_event->result != SDC_SUCCESS)
            {
                // lk_printf("Event read result: %u", p_event->result);
            }
            else
            {
                /* Read successful. */
            }
        /* ... */
        default: break;
    }
    return;
}

static bool _lk_initialized = false;
uint8_t flag_sdc = 0;

static uint8_t lk_check_sdc (void)
{
    uint16_t timeout = 0xFFFF;
    while(app_sdc_busy_check() && --timeout);

    if (timeout != 0)
    {
        return 0;
    }    
    else
    {
        flag_sdc = 1;
        return 1;
    }
    
}





uint32_t lk_eeprom_init(void){

	#if defined DEBUG_MSG_SD_CARD
    lk_printf("lk_eeprom_sdc_init\n");
	 #endif
     
    flag_sdc = 0;

    uint32_t timeout = 0xFFFF;
    uint16_t count_init = 0;

    while(!lk_flag)
    {
        timeout = 0xFFFF;
        app_sdc_init(&sdc_cfg, sdc_handler);
        count_init++;
        lk_printf("Iteracoes: %u\n", count_init);
        while (!lk_flag && --timeout);
    }
    

    lk_printf("Init counter: %u\n", count_init);
    return 0;
}

uint32_t lk_eeprom_write_byte(uint16_t Address, uint8_t data){
	#if defined DEBUG_MSG_SD_CARD
	lk_printf("lk_eeprom_write_sdc_byte\n");
	#endif

    uint32_t lk_error = app_sdc_block_write(&data, Address, 1);

	return lk_error;
}

uint32_t lk_eeprom_read_byte(uint16_t Address, uint8_t *data){
	#if defined DEBUG_MSG_SD_CARD
	lk_printf("lk_eeprom_read_sdc_byte\n");

	#endif

    uint32_t lk_error = app_sdc_block_read(data, Address, 1);
        
	return lk_error; 
}

uint32_t lk_eeprom_write_page(uint16_t Address, uint8_t* pData, uint8_t size)
{
	#if defined DEBUG_MSG_SD_CARD
	// lk_printf("lk_eeprom_write_sdc_page\n");
    // lk_printf("Flag: %i\n", flag_sdc);
	#endif

   
    if (flag_sdc == 1)
    {
        return LK_EEPROM_SDC_CARD_NOT_FOUND;
    }
        
    uint16_t block_address = Address % 512;
    uint32_t block = Address/512;
    uint16_t aux1 = 512 - block_address; 
    uint8_t buff[512];
    uint16_t i = 0;
    uint16_t time_in, time_out;
    uint32_t lk_error;
    
    time_in = lk_millis_get();

 //Read the first block   
    lk_check_sdc();

    lk_error = app_sdc_block_read(buff, block, 1);
    
    if (lk_error != LK_SUCCESS)
    {
        return lk_error;
    }

    if (size > aux1)
    {
// Save the first block bytes at the buffer
        uint16_t aux2 = size - aux1;
        for (i = 0; i < aux1;i++)
            buff[block_address + i] = pData[i];
    
// Write the first block
        lk_check_sdc();


            lk_error = app_sdc_block_write(buff, block, 1);
            if (lk_error != LK_SUCCESS)
            {
                return lk_error;
            }

            lk_check_sdc();
            lk_error = app_sdc_block_read(last_block_buff, block, 1);
            if ((memcmp(buff, last_block_buff, SIZE_BLOCK)) != 0)
            {
                return LK_EEPROM_SDC_WRITE_ERROR;
            }
   
// Read second block
        lk_check_sdc();

        lk_error = app_sdc_block_read(buff, (block+1), 1);  
        if (lk_error != LK_SUCCESS)
        {
            return lk_error;
        }
// Save the second block bytes at the buffer  
        for (i = 0; i < aux2; i++)
            buff[i] = pData[aux1 + i];
    
// Write the second block    
        lk_check_sdc();

            lk_error = app_sdc_block_write(buff, block+1, 1);
            if (lk_error != LK_SUCCESS)
            {
                return lk_error;
            }

            lk_check_sdc();
            lk_error = app_sdc_block_read(last_block_buff, block+1, 1);
            
            if ((memcmp(buff, last_block_buff, SIZE_BLOCK)) != 0)
            {
                return LK_EEPROM_SDC_WRITE_ERROR;
            }
   
    last_block = block+1;
    memcpy(last_block_buff, buff, sizeof(buff));
    time_out = lk_millis_get();
    }
    else
    {

// Save the block bytes at the buffer  
        for (i = 0; i < size; i++)
            buff[block_address + i] = pData[i];
    
// Write the block    
        lk_check_sdc();


            lk_error = app_sdc_block_write(buff, block, 1);
            if (lk_error != LK_SUCCESS)
            {
                return lk_error;
            }
            lk_check_sdc();
            lk_error = app_sdc_block_read(last_block_buff, block, 1);
            
            if ((memcmp(buff, last_block_buff, SIZE_BLOCK)) != 0)
            {
                return LK_EEPROM_SDC_WRITE_ERROR;
            }


    last_block = block;
    memcpy(last_block_buff, buff, sizeof(buff));
    time_out = lk_millis_get();
    }


    uint32_t time = time_out-time_in;
    // lk_printf("Time: %lu\n", time);

	return LK_SUCCESS; 
}

uint32_t lk_eeprom_read_page(uint16_t Address, uint8_t* pData, uint8_t size){
	#if defined DEBUG_MSG_SD_CARD
	// lk_printf("lk_eeprom_read_sdc_page\n");
	#endif
    
    uint16_t time_in, time_out;

    time_in = lk_millis_get();
    
    if (flag_sdc == 1)
    {
        return LK_EEPROM_SDC_CARD_NOT_FOUND;
    }
        
	uint16_t block_address = Address % 512;
    uint32_t block = Address/512;
    uint16_t aux1 = 512 - block_address; 
    uint32_t lk_error;
    uint16_t i = 0;
    if (block == last_block)
    {
        // memcpy(buff, last_block_buff, sizeof(buff));

    }
    else
    {
        lk_check_sdc();
        lk_error = app_sdc_block_read(last_block_buff, block, 1);
        // lk_check_sdc();
        if (lk_error != LK_SUCCESS)
        {
            return lk_error;
        }
        

        // memcpy(last_block_buff, buff, sizeof(buff));
    }
     
 //Read the first block   


    if (size > aux1)
    {

// Save the first block bytes at output
        uint16_t aux2 = size - aux1;
        for (i = 0; i < aux1;i++)
            pData[i] = last_block_buff[block_address + i];

// Read second block
        lk_check_sdc();

        lk_error = app_sdc_block_read(last_block_buff, (block+1), 1);
        // lk_check_sdc();
        if (lk_error != LK_SUCCESS)
        {
            return lk_error;
        }  

// Save the second block bytes at the output  
        for (i = 0; i < aux2; i++)
            pData[aux1 + i] = last_block_buff[i];
        
        last_block = block+1;

    }
    else
    {

// Save the block bytes at the buffer  
        for (i = 0; i < size; i++)
            pData[i] = last_block_buff[block_address + i];
        last_block = block;
    }
    time_out = lk_millis_get();
   uint32_t time = time_out-time_in;
//    lk_printf("Time: %lu\n", time);
	return LK_SUCCESS; 
}

  • Hello,

    The write and read functions works fine, but the initialization does not work sometimes and it stays in a loop (because of the way the event handler is working).

    I too would suspect it to be due to the way the event handler is set up.
    I notice that you are never checking the returned error code of the app_sdc_init call. Could you please make sure to pass the returned error code to an APP_ERROR_CHECK?
    You should always check the returned error codes, since you will not know that the function has failed unless you do.

    Please also make sure that you have DEBUG enabled in your preprocessor defines, like shown in the included image:
      
    This will make a more detailed debug message be written to your log when an APP_ERROR_MESSAGE is passed a non-NRF_SUCCESS error code.

    Please do this, and let me know what is written to the logger when the initialization fails.

    Looking forward to resolving this issue together!

    Best regards,
    Karl

Related