PSoC6 SDHC DDR Support

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
Ray_Liang
Employee
Employee
50 sign-ins 10 questions asked 5 likes given

Hi PSoC Experts,

I feel confuse on the Spec of PSoC6 2MB and MTB2.x PDL document about SDHC DDR.

In the datasheet and TRM, PSoC6 SDHC support DDR, but current version of PDL document and source code are not include the support about DDR.

TRM:

pastedImage_0.png

Datasheet:

pastedImage_2.png

psoc6pdl -> html document SDHC portion:

pastedImage_3.png

psoc6pdl -> cy_sd_host.h

pastedImage_1.png

========================================

I want to clarify that does PSOC6 2MB can support SDHC DDR50 ?

If yes, does it mean the current PDL not support the DDR? When will it be supported?  Can we support DDR by write the Register bit mention in TRM?

Regards,

Ray

0 Likes
1 Solution

Hi JiaweiL_16 and Rakshith M B,

I have tested SDHC0 in slightly modified CY8CPROTO-062-4343W PSoC 6 in DDR mode.

Works perfect. Basically, this is the best mode for this SDHC.

As you can see from previous thread Re: CY8CPROTO-062-4343w SD card ,

switching to 1.8V was added to Proto Kit. 4343W was disconnected and instead of it  microSD connector was attached at approximately 2 cm distance by thin (127um diameter) silver wires. Silver wires are nothing special, they are just convenient for soldering to tiny pads of the Proto Kit.

Then, connectivity was tested with two microSD cards. One of them was very popular Samsung Evo+ 128GB, white-red color, and the second one was the fastest available card Lexar 1800x 32GB. The first card was able to connect at the rate DDR75, and the second - at the rate DDR70. These two cards did not connect at the rates of +5 MHz above given. As you can see, frequencies are much higher officially declared DDR40. It was possible to send commands and receive proper responses multiple times at indicated data rates, practically endless. However, usually it is important not only to transmit data, but to do this inert particular usually short timer intervals. And in this respect indicated high clock rates are bad, because packets are re-transmitted many times and the data transfer rate degrades. How critical degradation is, depends on application. I did not investigate what clock gives the highest throughput, although this may be very interesting. I  checked what clocks provide error-less transmission in my particular application. The goal of the application was to store continuous 26.6 MBps data stream in memory card. To prevent data loss due to writing delays and data corruption in transmission I organized ~1MB ring buffer in processor RAM. The external device wrote data in this ring buffer, and SDHC took it by DMA and stored in memory card. If SDHC does not write data in a timely manner, there is ~1MB buffer overrun and the data is lost. Thus, I measured number of such overruns in transmission of 16GB blocks. Each block needs ~10 min at the given rate 26.6 MBps. Results are the following:

Samsung Evo+ 128GB: DDR50 - no overruns, DDR55 - 3 overruns.

Lexar 1800x 32GB: DDR55 - no overruns, DDR60 - 1 overrun.

Here I would like to note that Lexar probably did not have less errors in communication than Samsung, but faster internals of this cards allowed to correct these errors faster, avoiding overruns at higher rates.

For comparison I also tested Samsung Evo+ 128GB in SDR mode. The result:

SDR50 - no overruns, SDR55 - 4 overruns.

Clock IN and OUT delays in the register SDHC0_CORE_GP_OUT_R were adjusted for DDR and SDR modes respectively as recommended for reliable transmission. IO voltage was 1.8V in both modes as recommended.

As you can see, safety margin in frequency for DDR is practically identical to SDR. Thus, this modes can be used with the same success, and SDR50 and DDR50 are the highest data rates that can be recommended under used test conditions (with fixed room temperature). All higher frequencies are above official SD specification and should not be used in mass production. If temperature can change in a wide range, one probably should not exceed Cypress recommended SDR40 and DDR40.

Here I would like to note that indicated data rates indeed was slightly higher because used in the Proto kit crystal has frequency 34.4064MHz, and maximal allowed input frequency in Modus toolbox is 33.333 MHz. Thus, when I write DDR50, indeed frequency was 50*34.4064/33.3333 = 51.6097MHz.

What advantages can have DDR mode against SDR? It has slightly decreased energy losses at parasitic capacitance of CLK line. However, if we shall assume that capacitance of this line is about 4 pF, parasitic current with 1.8V switching at 50MHz will be only 360uA. The card itself of good brands usually consumes about 25 mA at 3.3V. Thus, evergy losses at parasitic capacitance can be neglected. Another much more essential advantage is linked with restrains of PSoC 6 processor architecture. In the current processor Octal SPI (SMIF) sits on the same clock with SDHC1. This is basically the reason why I used SDHC0 for the current test and not SDHC1 that already has microSD connector attached. If, for instance, clock at Octal SPI is limited by 40 MHz, clock at SDHC1 will be also 40 MHz. And here at 40 MHz DDR40 will have 2x advantage against SDR20.

To activate DDR in PSoC 6.one cad do the following:

1. In cy_sd_host.h add enumerated type to type definition (last entrance):

/** The bus speed modes. */

typedef enum

{

    CY_SD_HOST_BUS_SPEED_DEFAULT            = 0U,  /**< Default Speed mode: 3.3V signaling at 25 MHz SDClk. */

    CY_SD_HOST_BUS_SPEED_HIGHSPEED          = 1U,  /**< High Speed mode: 3.3V signaling at 50 MHz SDClk. */

    CY_SD_HOST_BUS_SPEED_SDR12_5            = 2U,  /**< SDR12: UHS-I (1.8V signaling) at 25 MHz SDClk (12.5 MB/sec). */

    CY_SD_HOST_BUS_SPEED_SDR25              = 3U,  /**< SDR25: UHS-I (1.8V signaling) at 50 MHz SDClk (25 MB/sec). */

    CY_SD_HOST_BUS_SPEED_SDR50              = 4U,  /**< SDR50: UHS-I (1.8V signaling) at 100 MHz SDClk (50 MB/sec). */

    CY_SD_HOST_BUS_SPEED_EMMC_LEGACY        = 5U,  /**< Backwards Compatibility with legacy MMC card (26MB/sec max). */

    CY_SD_HOST_BUS_SPEED_EMMC_HIGHSPEED_SDR = 6U,   /**< eMMC High speed SDR (52MB/sec max) */

    CY_SD_HOST_BUS_SPEED_DDR50              = 7U  /**< DDR50: UHS-I (1.8V signaling) at 50 MHz SDClk (50 MB/sec). */

} cy_en_sd_host_bus_speed_mode_t;

2. In cy_sd_host.c add constant CY_SD_HOST_DDR50_SPEED = 4. Total list of available modes will look as:

#define CY_SD_HOST_DEFAULT_SPEED (0UL)
#define CY_SD_HOST_HIGH_SPEED    (1UL)
#define CY_SD_HOST_SDR12_SPEED   (0UL)  /* The SDR12/Legacy speed. */
#define CY_SD_HOST_SDR25_SPEED   (1UL)  /* The SDR25/High Speed SDR speed. */
#define CY_SD_HOST_SDR50_SPEED   (2UL)  /* The SDR50 speed. */
#define CY_SD_HOST_DDR50_SPEED          (4UL)  /* The DDR50 speed. */

3. In cy_sd_host.c, in procedure Cy_SD_Host_SetBusSpeedMode(), switch of speedMode should be complemented as:

/* 2. Change Bus Speed Mode: Issue CMD6 with mode 1 */

            switch (speedMode)

            {

                case CY_SD_HOST_BUS_SPEED_EMMC_LEGACY:

                case CY_SD_HOST_BUS_SPEED_DEFAULT:

                case CY_SD_HOST_BUS_SPEED_SDR12_5:

                    highSpeedValue = CY_SD_HOST_SDR12_SPEED; /* Max clock = 25 MHz */

                    break;

                case CY_SD_HOST_BUS_SPEED_EMMC_HIGHSPEED_SDR:

                case CY_SD_HOST_BUS_SPEED_SDR25:

                case CY_SD_HOST_BUS_SPEED_HIGHSPEED:

                    highSpeedValue = CY_SD_HOST_SDR25_SPEED; /* Max clock = 50 MHz */

                    break;

                case CY_SD_HOST_BUS_SPEED_SDR50:

                    highSpeedValue = CY_SD_HOST_SDR50_SPEED; /* Max clock = 100 MHz */

                    break;

                case CY_SD_HOST_BUS_SPEED_DDR50:

                    highSpeedValue = CY_SD_HOST_DDR50_SPEED; /* Max clock = 50 MHz + DDR */

                    break;

                default:

                    ret = CY_SD_HOST_ERROR_INVALID_PARAMETER;

                    break;

            }

That are all changes that are needed in the library.

Initialization code in the user program can look as:

//Enable and init SDHC0

Cy_SD_Host_Enable(SDHC0);

Cy_SD_Host_Init(SDHC0, &SDHC0_config, &sdHostContext);

Cy_SD_Host_InitCard(SDHC0, &SDHC0_card_cfg, &sdHostContext);

//

Cy_SD_Host_SetBusSpeedMode(SDHC0,CY_SD_HOST_BUS_SPEED_DDR50,&sdHostContext); //This is to send command CMD6 to set DDR in microSD

Cy_SD_Host_SdCardChangeClock(SDHC0, CY_SD_HOST_CLK_50M);                            //this is needed - works was 100M

Cy_SysLib_Delay(Delay); //msec, my addition, otherwise hangs?

//Change controller settings for DDR

uint32 refgen, reg_address;

reg_address = 0x4046103E; //register SDHC0_CORE_HOST_CTRL2_R ; setting of this register is very essential

refgen = CY_GET_REG32(reg_address);

refgen &= ~0x0000007;    //clear bits 2:0

refgen |= 0x0000004;    // set bit 2, DDR50

CY_SET_REG32(reg_address, refgen);    // Set register

Cy_SysLib_Delay(1);        //This delay is necessary!!!

//

reg_address = 0x40461534; //register SDHC0_CORE_GP_OUT_R ; setting of this register is essential for high clock rate

refgen = CY_GET_REG32(reg_address);

refgen |= 0x00003C0;    // set bits 9-6, Card clock IN and OUT delays for DDR50

CY_SET_REG32(reg_address, refgen);    // Set register

Cy_SysLib_Delay(1);        //This delay is necessary!!!

Here I modified registers at fixed addresses. This works, but using named registers could increase portability of the code.

I just did not find where register names  SDHC0_CORE_HOST_CTRL2_R and SDHC0_CORE_GP_OUT_R might be declared.

One also should not forget to change/override functions to set 1.8V IO voltage as it is described in documentation.

Given above code was compiled in Modus 1.1. It probably will work in Modus 2.0.

With best regards,

Alexei

View solution in original post

2 Replies
Rakshith
Moderator
Moderator
Moderator
250 likes received 1000 replies posted 750 replies posted

Hi JiaweiL_16​,

The PDL and HAL SDHC drivers do not currently support DDR50 speed mode. But the SDHC hardware block does support DDR40 at 1.8V signalling as mentioned in the PSoC 6 MCU: CY8C62x8, CY8C62xA Architecture TRM​ -

pastedImage_0.png

You should be able to write into the HOST_CTRLx_R registers to enable DDR speed mode. Please refer to the  Cy_SD_Host_SetHostSpeedMode function implementation in cy_sd_host.c PDL file. You can modify the function to write appropriate values as mentioned in Architecture TRM to enable DDR mode.

Please refer to the page 1545 of Register TRM for more details regarding the HOST_CTRLx_R register.

Thanks and Regards,

Rakshith M B

Thanks and Regards,
Rakshith M B
0 Likes

Hi JiaweiL_16 and Rakshith M B,

I have tested SDHC0 in slightly modified CY8CPROTO-062-4343W PSoC 6 in DDR mode.

Works perfect. Basically, this is the best mode for this SDHC.

As you can see from previous thread Re: CY8CPROTO-062-4343w SD card ,

switching to 1.8V was added to Proto Kit. 4343W was disconnected and instead of it  microSD connector was attached at approximately 2 cm distance by thin (127um diameter) silver wires. Silver wires are nothing special, they are just convenient for soldering to tiny pads of the Proto Kit.

Then, connectivity was tested with two microSD cards. One of them was very popular Samsung Evo+ 128GB, white-red color, and the second one was the fastest available card Lexar 1800x 32GB. The first card was able to connect at the rate DDR75, and the second - at the rate DDR70. These two cards did not connect at the rates of +5 MHz above given. As you can see, frequencies are much higher officially declared DDR40. It was possible to send commands and receive proper responses multiple times at indicated data rates, practically endless. However, usually it is important not only to transmit data, but to do this inert particular usually short timer intervals. And in this respect indicated high clock rates are bad, because packets are re-transmitted many times and the data transfer rate degrades. How critical degradation is, depends on application. I did not investigate what clock gives the highest throughput, although this may be very interesting. I  checked what clocks provide error-less transmission in my particular application. The goal of the application was to store continuous 26.6 MBps data stream in memory card. To prevent data loss due to writing delays and data corruption in transmission I organized ~1MB ring buffer in processor RAM. The external device wrote data in this ring buffer, and SDHC took it by DMA and stored in memory card. If SDHC does not write data in a timely manner, there is ~1MB buffer overrun and the data is lost. Thus, I measured number of such overruns in transmission of 16GB blocks. Each block needs ~10 min at the given rate 26.6 MBps. Results are the following:

Samsung Evo+ 128GB: DDR50 - no overruns, DDR55 - 3 overruns.

Lexar 1800x 32GB: DDR55 - no overruns, DDR60 - 1 overrun.

Here I would like to note that Lexar probably did not have less errors in communication than Samsung, but faster internals of this cards allowed to correct these errors faster, avoiding overruns at higher rates.

For comparison I also tested Samsung Evo+ 128GB in SDR mode. The result:

SDR50 - no overruns, SDR55 - 4 overruns.

Clock IN and OUT delays in the register SDHC0_CORE_GP_OUT_R were adjusted for DDR and SDR modes respectively as recommended for reliable transmission. IO voltage was 1.8V in both modes as recommended.

As you can see, safety margin in frequency for DDR is practically identical to SDR. Thus, this modes can be used with the same success, and SDR50 and DDR50 are the highest data rates that can be recommended under used test conditions (with fixed room temperature). All higher frequencies are above official SD specification and should not be used in mass production. If temperature can change in a wide range, one probably should not exceed Cypress recommended SDR40 and DDR40.

Here I would like to note that indicated data rates indeed was slightly higher because used in the Proto kit crystal has frequency 34.4064MHz, and maximal allowed input frequency in Modus toolbox is 33.333 MHz. Thus, when I write DDR50, indeed frequency was 50*34.4064/33.3333 = 51.6097MHz.

What advantages can have DDR mode against SDR? It has slightly decreased energy losses at parasitic capacitance of CLK line. However, if we shall assume that capacitance of this line is about 4 pF, parasitic current with 1.8V switching at 50MHz will be only 360uA. The card itself of good brands usually consumes about 25 mA at 3.3V. Thus, evergy losses at parasitic capacitance can be neglected. Another much more essential advantage is linked with restrains of PSoC 6 processor architecture. In the current processor Octal SPI (SMIF) sits on the same clock with SDHC1. This is basically the reason why I used SDHC0 for the current test and not SDHC1 that already has microSD connector attached. If, for instance, clock at Octal SPI is limited by 40 MHz, clock at SDHC1 will be also 40 MHz. And here at 40 MHz DDR40 will have 2x advantage against SDR20.

To activate DDR in PSoC 6.one cad do the following:

1. In cy_sd_host.h add enumerated type to type definition (last entrance):

/** The bus speed modes. */

typedef enum

{

    CY_SD_HOST_BUS_SPEED_DEFAULT            = 0U,  /**< Default Speed mode: 3.3V signaling at 25 MHz SDClk. */

    CY_SD_HOST_BUS_SPEED_HIGHSPEED          = 1U,  /**< High Speed mode: 3.3V signaling at 50 MHz SDClk. */

    CY_SD_HOST_BUS_SPEED_SDR12_5            = 2U,  /**< SDR12: UHS-I (1.8V signaling) at 25 MHz SDClk (12.5 MB/sec). */

    CY_SD_HOST_BUS_SPEED_SDR25              = 3U,  /**< SDR25: UHS-I (1.8V signaling) at 50 MHz SDClk (25 MB/sec). */

    CY_SD_HOST_BUS_SPEED_SDR50              = 4U,  /**< SDR50: UHS-I (1.8V signaling) at 100 MHz SDClk (50 MB/sec). */

    CY_SD_HOST_BUS_SPEED_EMMC_LEGACY        = 5U,  /**< Backwards Compatibility with legacy MMC card (26MB/sec max). */

    CY_SD_HOST_BUS_SPEED_EMMC_HIGHSPEED_SDR = 6U,   /**< eMMC High speed SDR (52MB/sec max) */

    CY_SD_HOST_BUS_SPEED_DDR50              = 7U  /**< DDR50: UHS-I (1.8V signaling) at 50 MHz SDClk (50 MB/sec). */

} cy_en_sd_host_bus_speed_mode_t;

2. In cy_sd_host.c add constant CY_SD_HOST_DDR50_SPEED = 4. Total list of available modes will look as:

#define CY_SD_HOST_DEFAULT_SPEED (0UL)
#define CY_SD_HOST_HIGH_SPEED    (1UL)
#define CY_SD_HOST_SDR12_SPEED   (0UL)  /* The SDR12/Legacy speed. */
#define CY_SD_HOST_SDR25_SPEED   (1UL)  /* The SDR25/High Speed SDR speed. */
#define CY_SD_HOST_SDR50_SPEED   (2UL)  /* The SDR50 speed. */
#define CY_SD_HOST_DDR50_SPEED          (4UL)  /* The DDR50 speed. */

3. In cy_sd_host.c, in procedure Cy_SD_Host_SetBusSpeedMode(), switch of speedMode should be complemented as:

/* 2. Change Bus Speed Mode: Issue CMD6 with mode 1 */

            switch (speedMode)

            {

                case CY_SD_HOST_BUS_SPEED_EMMC_LEGACY:

                case CY_SD_HOST_BUS_SPEED_DEFAULT:

                case CY_SD_HOST_BUS_SPEED_SDR12_5:

                    highSpeedValue = CY_SD_HOST_SDR12_SPEED; /* Max clock = 25 MHz */

                    break;

                case CY_SD_HOST_BUS_SPEED_EMMC_HIGHSPEED_SDR:

                case CY_SD_HOST_BUS_SPEED_SDR25:

                case CY_SD_HOST_BUS_SPEED_HIGHSPEED:

                    highSpeedValue = CY_SD_HOST_SDR25_SPEED; /* Max clock = 50 MHz */

                    break;

                case CY_SD_HOST_BUS_SPEED_SDR50:

                    highSpeedValue = CY_SD_HOST_SDR50_SPEED; /* Max clock = 100 MHz */

                    break;

                case CY_SD_HOST_BUS_SPEED_DDR50:

                    highSpeedValue = CY_SD_HOST_DDR50_SPEED; /* Max clock = 50 MHz + DDR */

                    break;

                default:

                    ret = CY_SD_HOST_ERROR_INVALID_PARAMETER;

                    break;

            }

That are all changes that are needed in the library.

Initialization code in the user program can look as:

//Enable and init SDHC0

Cy_SD_Host_Enable(SDHC0);

Cy_SD_Host_Init(SDHC0, &SDHC0_config, &sdHostContext);

Cy_SD_Host_InitCard(SDHC0, &SDHC0_card_cfg, &sdHostContext);

//

Cy_SD_Host_SetBusSpeedMode(SDHC0,CY_SD_HOST_BUS_SPEED_DDR50,&sdHostContext); //This is to send command CMD6 to set DDR in microSD

Cy_SD_Host_SdCardChangeClock(SDHC0, CY_SD_HOST_CLK_50M);                            //this is needed - works was 100M

Cy_SysLib_Delay(Delay); //msec, my addition, otherwise hangs?

//Change controller settings for DDR

uint32 refgen, reg_address;

reg_address = 0x4046103E; //register SDHC0_CORE_HOST_CTRL2_R ; setting of this register is very essential

refgen = CY_GET_REG32(reg_address);

refgen &= ~0x0000007;    //clear bits 2:0

refgen |= 0x0000004;    // set bit 2, DDR50

CY_SET_REG32(reg_address, refgen);    // Set register

Cy_SysLib_Delay(1);        //This delay is necessary!!!

//

reg_address = 0x40461534; //register SDHC0_CORE_GP_OUT_R ; setting of this register is essential for high clock rate

refgen = CY_GET_REG32(reg_address);

refgen |= 0x00003C0;    // set bits 9-6, Card clock IN and OUT delays for DDR50

CY_SET_REG32(reg_address, refgen);    // Set register

Cy_SysLib_Delay(1);        //This delay is necessary!!!

Here I modified registers at fixed addresses. This works, but using named registers could increase portability of the code.

I just did not find where register names  SDHC0_CORE_HOST_CTRL2_R and SDHC0_CORE_GP_OUT_R might be declared.

One also should not forget to change/override functions to set 1.8V IO voltage as it is described in documentation.

Given above code was compiled in Modus 1.1. It probably will work in Modus 2.0.

With best regards,

Alexei