Vybrid eSDHC Controller

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Vybrid eSDHC Controller

737 Views
ogj
Contributor IV

I am trying to get a simple SDHC driver to work using the A5 core of the Vybrid processor. The board is a custom, however I know that both the board and the card are functional as I can use a Freescale driver and both work fine. I have pared down the driver to better understand what is going on in the initialization of an SDHC card.

I’m using PLL3 @ 480 MHz /5 to supply the clock into the eSDHC module. This supplies a 96 MHz clock into the module. During initialization this is divided down by the SYSCTL dividers to 400 KHz (/16 /15). The PRSSTAT_SDSTB bit is set so I know the module clock is functional. Then I run the following code:

   // Initialize the SDHC IO pins and module clock

   _esdhc_hw_init(1);    //set up the pins for SDHC 1

   _esdhc_clk_init(1);    //set up the clock

 

   // Disable the SDHC card clock per errata e3980

   esdhc_ptr->SYSCTL &= ~SDHC_SYSCTL_SDCLKEN_MASK;

  

   // Reset the controller

   esdhc_ptr->SYSCTL |= SDHC_SYSCTL_RSTA_MASK;

  

   // Set to low speed for initialization

   _esdhc_set_baudrate_low(esdhc_device_ptr->ESDHC_REG_PTR,   //pointer to reg set

                           _esdhc_init_parms->CLOCK_SPEED,    //incoming clock speed

                           400000);                           //desired clock speed

  // Enable the SDHC card clock again

   esdhc_ptr->SYSCTL |=  SDHC_SYSCTL_SDCLKEN_MASK;

  

   // CMD0 - Go to idle - reset card

   command.COMMAND = CMD0;

   command.ARGUMENT = 0;

   command.BLOCKS = 0;

   val = _esdhc_send_cmd(esdhc_device_ptr, &command);

   if(val & ESDHC_ERROR_MASK)

   {

      return(ESDHC_ERROR_INIT_FAILED);

   }

 

  

   // CMD8 - Check HC support, verify 2.7 to 3.6V operation

   command.COMMAND = CMD8;

   command.ARGUMENT = 0x000001AA;   // Voltage supply 2.7-3.6V 0x100 + 0xAA check pattern

   command.BLOCKS = 0;

   val = _esdhc_send_cmd(esdhc_device_ptr, &command);

 

Sending CMD8 always fails showing the card didn’t respond after 64 clocks. The register setup right after sending  CMD8 is:

 

 Note that the card clock is disabled using bit SDCLKEN before the RSTA and the clock dividers are set in SYSCTL per errata e3980. Then the clock is re-enabled. The send_cmd checks for no ongoing activity. All of the registers seem OK. Any ideas why the card doesn’t respond?

Tags (1)
0 Kudos
2 Replies

651 Views
ogj
Contributor IV

I was doing some comparison to the code that works and noticed that I wasn't sending the 80 initial clock pulses by setting the INITA bit in SYSCTL. Here is the new code:

   // Initialize the SDHC pins and clock
   _esdhc_hw_init(1);
   _esdhc_clk_init(1);
  
   // Disable the SDHC card clock per errata e3980
   esdhc_ptr->SYSCTL &= ~SDHC_SYSCTL_SDCLKEN_MASK;
  
   // Reset the controller
   esdhc_ptr->SYSCTL |= SDHC_SYSCTL_RSTA_MASK;
   while(esdhc_ptr->SYSCTL & SDHC_SYSCTL_RSTA_MASK);
   // Just to keep card detection working
   esdhc_ptr->SYSCTL = SDHC_SYSCTL_PEREN_MASK;
   // Switch off external DMA requests
    esdhc_ptr->VENDOR = 0;
   // Set any default size of data block
   esdhc_ptr->BLKATTR = SDHC_BLKATTR_BLKCNT(1) | SDHC_BLKATTR_BLKSIZE(512);
   
   esdhc_ptr->WML = SDHC_WML_RDWML(1) | SDHC_WML_WRWML(1); /* To do: set up the right value */
   // Poll inhibit bits
   while(esdhc_ptr->PRSSTAT & (SDHC_PRSSTAT_CIHB_MASK | SDHC_PRSSTAT_CDIHB_MASK));
  
   // Set to low speed for initialization
   _esdhc_set_baudrate_low(esdhc_device_ptr->ESDHC_REG_PTR,       //pointer to reg set
                           esdhc_device_ptr->INIT->CLOCK_SPEED,   //incoming clock speed
                           400000);                               //desired card clock speed
  
   // Enable the SDHC card clock
   esdhc_ptr->SYSCTL |= SDHC_SYSCTL_SDCLKEN_MASK;
   // Clear flags in IRQSTAT (write 1 to clear)
   esdhc_ptr->IRQSTAT = 0xFFFF;
   esdhc_ptr->IRQSTATEN =  SDHC_IRQSTATEN_DMAESEN_MASK         // DMA Error Status Enable
                         | SDHC_IRQSTATEN_AC12ESEN_MASK        // Auto CMD12 Error Status Enable
                         | SDHC_IRQSTATEN_DEBESEN_MASK         // Data End Bit Error Status Enable
                         | SDHC_IRQSTATEN_DCESEN_MASK          // Data CRC Error Status Enable
                         | SDHC_IRQSTATEN_DTOESEN_MASK         // Data Timeout Error Status Enable
                         | SDHC_IRQSTATEN_CIESEN_MASK          // Command Index Error Status Enable
                         | SDHC_IRQSTATEN_CEBESEN_MASK         // Command End Bit Error Status Enable
                         | SDHC_IRQSTATEN_CCESEN_MASK          // Command CRC Error Status Enable
                         | SDHC_IRQSTATEN_CTOESEN_MASK         // Command Timeout Error Status Enable
                         //| SDHC_IRQSTATEN_CINTSEN_MASK         // Card Interrupt Status Enable
                         | SDHC_IRQSTATEN_CRMSEN_MASK          // Card Removal Status Enable
                         | SDHC_IRQSTATEN_CINSEN_MASK          // Card Insertion Status Enable
                         //| SDHC_IRQSTATEN_BRRSEN_MASK          // Buffer Read Ready Status Enable
                         //| SDHC_IRQSTATEN_BWRSEN_MASK          // Buffer Write Ready Status Enable
                         | SDHC_IRQSTATEN_DINTSEN_MASK         // DMA Interrupt Status Enable
                         | SDHC_IRQSTATEN_BGESEN_MASK          // Block Gap Event Status Enable
                         | SDHC_IRQSTATEN_TCSEN_MASK           // Transfer Complete Status Enable
                         | SDHC_IRQSTATEN_CCSEN_MASK;          // Command Complete Status Enable
   
   // 80 initial clocks
   esdhc_ptr->SYSCTL |= SDHC_SYSCTL_INITA_MASK;
   while(esdhc_ptr->SYSCTL & SDHC_SYSCTL_INITA_MASK);
   // Check card
    if(esdhc_ptr->PRSSTAT & SDHC_PRSSTAT_CINS_MASK)
    {
        esdhc_device_ptr->CARD = ESDHC_CARD_UNKNOWN;
    }
  
   // CMD0 - Go to idle - reset card
   command.COMMAND = CMD0;
   command.ARGUMENT = 0;
   command.BLOCKS = 0;
   val = _esdhc_send_cmd(esdhc_device_ptr, &command);
   if(val & ESDHC_ERROR_MASK)
   {
      return(ESDHC_ERROR_INIT_FAILED);
   }
  
   // CMD8 - Check HC support, verify 2.7 to 3.6V operation
   command.COMMAND = CMD8;
   command.ARGUMENT = 0x000001AA;   // Voltage supply 2.7-3.6V 0x100 + 0xAA check pattern
   command.BLOCKS = 0;
   val = _esdhc_send_cmd(esdhc_device_ptr, &command);
It still doesn't work - CMD8 still shows no clock. However now the CRM bit is set in IRQSTAT. It is interesting that CINS (card inserted bit) in PRSSTAT is low when there is definitely a card inserted.
0 Kudos

651 Views
ogj
Contributor IV

This got cut out of the above post:

CMD8.PNG

0 Kudos