Skip to main content
Poonam Deoghare
Associate II
May 29, 2018
Solved

SD read/write with DMA mode working only in debug mode

  • May 29, 2018
  • 16 replies
  • 3882 views
Posted on May 29, 2018 at 13:55

Hi All,

I am working on STM32F413 Disco kit and trying to read/write into SD card using DMA mode.

My requirement is -   i have to call single function which will read/write into SD card in 1ms timer callback function.

It is working fine in debug mode but not in normal mode.

Is there any delay issue ? Because when we run in debug mode, automatically delay is getting added.

Our project requirement is very rigid that we should not use HAL_Delay().

Please provide your suggestions.

My code:-

/********************************************/

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)

{    // TIM1 is configured for 1ms

        if(htim->Instance == TIM1)    {

        SDtest();     

    }

}

/********************************************/

void SDtest(void){

      LastWriteAddr = SD_WriteBlocks_DMA(Tx,TEMP_RAW_DATA_START_ADDR,1);

        LastReadAddr = SD_ReadBlocks_DMA(Rx,TEMP_RAW_DATA_START_ADDR,1);

}

/********************************************/

/*** Function To write into SD card via DMA***/

uint32_t SD_WriteBlocks_DMA(uint8_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks)

{

    if(SDOperationState == SDWriteOperation)

    {

        printf('\n SD_WriteBlocks_DMA SDWriteOperation\n');

        SDState = SDCardAvailable;

        return 0;

    }   

    if(SDState == SDCardAvailable)

    {    

        printf('\n SD_WriteBlocks_DMA\n');

        HAL_SD_WriteBlocks_DMA(&hsd, (uint8_t *)pData, WriteAddr, NumOfBlocks);

        SDState = SDCardBusy;

        return 0;

  }

  if(txDone == true)

  {

        WriteAddr += EACH_BLOCK_SIZE;

        SDOperationState = SDWriteOperation;

        printf('\n SD_WriteBlocks_DMA txDone\n');

        txDone = false;

        return WriteAddr;

  }    

}

/********************************************/

/*** Function To read from SD card via DMA***/

uint32_t SD_ReadBlocks_DMA(uint8_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks)

{  

    if(SDOperationState == SDReadOperation)

    {

        SDState = SDCardAvailable;

        return 0;

    }

    if(SDState == SDCardAvailable)

    {    

        HAL_SD_ReadBlocks_DMA(&hsd, (uint8_t *)pData, ReadAddr, NumOfBlocks);

        SDState = SDCardBusy;

        return 0;

    }

  if(rxDone == true)

  {

        ReadAddr += EACH_BLOCK_SIZE;

        SDOperationState = SDReadOperation;        

        printf('SD card Read Done \n');

        printf('Rx is %s \n',Rx);

        rxDone = false;

        return ReadAddr ;

  }

}

/********************************************/

enum SDStateEnum{

    SDCardAvailable,

    SDCardBusy

};

enum SDOperationStateEnum{

    SDIdle,

    SDWriteOperation,

    SDReadOperation

};

enum SDStateEnum SDState = SDCardAvailable;

enum SDOperationStateEnum SDOperationState = SDIdle;

/********************************************/

Thanks,

Poonam

    This topic has been closed for replies.
    Best answer by Poonam Deoghare
    Posted on June 05, 2018 at 10:20

    I have created few volatile flags for Read and write.

    volatile bool SDWRITE = 0;

    volatile bool SDREAD = 0;

    Also the card status must be checked after read/write operations.

    Used these flags at proper place as shown in below code.

    Called below code in 1ms timer callback function.

    if(SDWRITE == 0)

            {

                HAL_SD_WriteBlocks_DMA(&hsd, buff, write_addr, 1);

                SDWRITE = 1;

            }

            if(SDWRITE == 1)

            {

                 if(HAL_SD_GetCardState(&hsd) == HAL_SD_CARD_TRANSFER)

                {

                      if(SDREAD == 0)

                    {    

                        //printf('\n SDREAD  0 \n');

                        HAL_SD_ReadBlocks_DMA(&hsd,read_buff,read_addr,1);                    

                        SDREAD = 1;

                    }

                    if(SDREAD == 1)

                    {

                        //printf('\n SDREAD  1 \n');

                        if(HAL_SD_GetCardState(&hsd) == HAL_SD_CARD_TRANSFER)

                        {    

                            //printf('\n  SDREAD HAL_SD_CARD_TRANSFER\n');                        

                            SDWRITE = 0;

                            write_addr +=0x200;

                            SDREAD = 0;

                            read_addr += 0x200;

                            //printf('\n read_buff is %s write_addr = 0x%x \n',read_buff,write_addr);

                            //printf('\n read_addr is 0x%x\n',read_addr);                            

                            //printf('\n write_addr is 0x%x\n',write_addr);    

                        }   

    16 replies

    AvaTar
    Senior III
    May 29, 2018
    Posted on May 29, 2018 at 14:49

    It is working fine in debug mode but not in normal mode.

    You can safely assume that both configurations (debug and release) have different settings.

    Please provide your suggestions.

    I don't do any Cube/HAL code, but I would start to either compare the settings for both configurations, or the emitted build commands. Per

    #define

    's in your code, the actual source code might be different.
    Tesla DeLorean
    Guru
    May 29, 2018
    Posted on May 29, 2018 at 16:23

    Make sure SDState and anything that is touched under interrupt is declared volatile.

    Make sure to set the new SDState immediately so as not to create race conditions with the likes of printf, HAL_SD_Read/WriteBlocks_DMA, and reentry of the 1ms ticker.

    If you are not doing this with an RTOS, I'd probably lean to pumping the SD activity in a foreground task.

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    Poonam Deoghare
    Associate II
    May 29, 2018
    Posted on May 29, 2018 at 16:58

    I have used enum for flags[as you can see in my code above] and volatile for variables which are getting called in interrupt.

    I am not using RTOS. Its a bare metal project.

    Is ENUM is creating problem but then its working fine in debug mode.

    In debug mode also , if I step in very fast, it doesn't work .

    I have to step in slow then only it works.

    Thanks,

    Poonam

    Tesla DeLorean
    Guru
    May 29, 2018
    Posted on May 29, 2018 at 17:24

    Your code creates race conditions

        if(SDState == SDCardAvailable)

        {    

            printf('\n SD_WriteBlocks_DMA\n');

            HAL_SD_WriteBlocks_DMA(&hsd, (uint8_t *)pData, WriteAddr, NumOfBlocks);

            SDState = SDCardBusy; // Far too late to do this

            return 0;

      }
    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    T J
    Senior III
    May 29, 2018
    Posted on May 29, 2018 at 16:39

    Like

    Turvey.Clive

    hinted, I would suggest that don't print in an interrupt,

    just set a flag, maybe write to a table, and let the foreground do all the printing.

    feel free to use globals for flags and permanent buffers linking interrupts to the foreground process.

    is that the opposite of volatile ?

    Poonam Deoghare
    Associate II
    June 5, 2018
    Posted on June 05, 2018 at 09:29

    The problem is solved with proper utilization of flags in timer callback function.

    Thanks.

    T J
    Senior III
    June 5, 2018
    Posted on June 05, 2018 at 09:37

    which flags ?

    The object of the forum is to have a easy path to a solution.

    If its ok with you, the Solution is ?

    Poonam Deoghare
    Poonam DeoghareAuthorBest answer
    Associate II
    June 5, 2018
    Posted on June 05, 2018 at 10:20

    I have created few volatile flags for Read and write.

    volatile bool SDWRITE = 0;

    volatile bool SDREAD = 0;

    Also the card status must be checked after read/write operations.

    Used these flags at proper place as shown in below code.

    Called below code in 1ms timer callback function.

    if(SDWRITE == 0)

            {

                HAL_SD_WriteBlocks_DMA(&hsd, buff, write_addr, 1);

                SDWRITE = 1;

            }

            if(SDWRITE == 1)

            {

                 if(HAL_SD_GetCardState(&hsd) == HAL_SD_CARD_TRANSFER)

                {

                      if(SDREAD == 0)

                    {    

                        //printf('\n SDREAD  0 \n');

                        HAL_SD_ReadBlocks_DMA(&hsd,read_buff,read_addr,1);                    

                        SDREAD = 1;

                    }

                    if(SDREAD == 1)

                    {

                        //printf('\n SDREAD  1 \n');

                        if(HAL_SD_GetCardState(&hsd) == HAL_SD_CARD_TRANSFER)

                        {    

                            //printf('\n  SDREAD HAL_SD_CARD_TRANSFER\n');                        

                            SDWRITE = 0;

                            write_addr +=0x200;

                            SDREAD = 0;

                            read_addr += 0x200;

                            //printf('\n read_buff is %s write_addr = 0x%x \n',read_buff,write_addr);

                            //printf('\n read_addr is 0x%x\n',read_addr);                            

                            //printf('\n write_addr is 0x%x\n',write_addr);    

                        }   
    Poonam Deoghare
    Associate II
    June 11, 2018
    Posted on June 11, 2018 at 12:17

    Hi ,

    I have one new requirement as follow.

    I need to find the bad sector of SD card and I should not write/ read into those?

    Is there any API to find these Bad sector?

    OR I have to manually do this?

    Also is there any API to format the SD card?

    And Regarding class speed

    Class 10 :- will this type of card work with STM32F23 MCU?

    Thanks,

    Poonam

    Tesla DeLorean
    Guru
    June 11, 2018
    Posted on June 11, 2018 at 13:50

    Who creates these requirements? Ask that person what they expect...

    The card is going to hide a lot of defects from you, and will have a number of spare blocks internally to manage that. If you want to find them you're going to have to scan the media looking for hard errors, or there might be some specific CMD the card supports to report the defect list, or manage it. With SCSI devices these where MODE PAGES as I recall. Review the published SDMMC specification.

    FatFs provides f_mkfs() to write initial structures to the media.

    Not familiar with the STM32F23, the code provided by ST should work for all SD, SDHC and SDXC cards to Class 10 and beyond, and north of 400 GB in capacity. Not sure you're going to hit Class 10 numbers unless you recode the driver and optimize how you stream data to the card.

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    Poonam Deoghare
    Associate II
    June 15, 2018
    Posted on June 15, 2018 at 19:13

    Hi,

    I will find the bad sector by implementing following.

    Write fixed 512 byte and read it back . If getting the exact same then make that block as good sector.

    I am trying to get the card info using HAL_SD_GetCardInfo(), but for all the cards following info is constant.

    cart type = 1

    card version =1

    class = 5B5 

    Could you please help me in this?

    Tesla DeLorean
    Guru
    June 15, 2018
    Posted on June 15, 2018 at 19:29

    >>Write fixed 512 byte and read it back . If getting the exact same then make that block as good sector.

    I don't think this is an effective manner to achieve the stated goal, there are several layers of CRC/ECC and block management between you and the flash array to learn anything useful. Like I said earlier, there are likely card level methods that will expose lower levels of functionality.

    If you proceed on the current route, you should do blocks of at least 32KB, doing interaction at a sector level will be excruciating slow. In terms of media/file-system integrity I would write massive pseudo-random sequences across the media, this will expose cross-linking, or mirroring of data in multiple places.

    >>Could you please help me in this?

    I'm not looking to perform work assignments in an unpaid capacity.

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    Poonam Deoghare
    Associate II
    June 15, 2018
    Posted on June 15, 2018 at 20:10

    Never mind Clive.

    Thanks anyways.

    Regards,

    Poonam