text: /**
   * \file   hs_mmcsd_rw.c
   *
   * \brief   This is a sample application file demonstrating read and write to
   *          SD Card.
   *
   *          Application Configuration:
   *
   *              Modules Used:
   *                  MMCSD0
   *                  DMA
   *                  UART0
   *                  Timer7
   *
   *              Configurable Parameters:
   *                  None
   *
   *              Hard-coded configuration of other parameters:
   *                  Card type - SD card
   *                  Bit Modes - 4 bit
   *                  Transfer Speed - Upto High Speed
   *                  Data buffer size - 64Kb
   *                  Console interface - Uart interface is default configuration.
   *                                      For semihosting set ConsoleUtilsSetType
   *                                      to CONSOLE_DEBUGGER and set compile time
   *                                      macro CONSOLE as SEMIHOSTING.
   *
   *
   *          Application UseCase:
   *              Perform text file or directory access on SD Card supporting
   *              fatfs file system.
   *              Supported commands are
   *                  1. ls - list the files of current directory
   *                  2. cd/chdir - change to given directory
   *                  3. pwd - print current directory
   *                  4. cat
   *                     a. Echo contents of a file
   *                     b. Read from a file and write to another
   *                     c. Echo the input taken through xmodem
   *                     d. Take input through xmodem and write 'n' times to file
   *                  5. rm - remove a file or empty directory
   *                  6. mkdir - create a directory
   *                  5. help/?/h - help on supported commandline operations
   *
   *          Running example:
   *              1. Format SD card for FAT filesystem, insert card in the board,
   *                 load example application and run.
   *              2. UART console provides interface to perform text file or
   *                 directory access on SD card.
   *
   *          Limitations:
   *              1. Only SD card is supported.
   *              2. Only standard ASCII characters are supported.
   *              3. Data size that can be read through xmodem is limited by size
   *                 of data buffer.
   *
   *          Note:
   *              1. This example is not fully complaint to semihosting. To take
   *                 commandline instruction non-blocking uart interface is used.
   *                 The same is not possible with semihosting console interface.
   *                 If semihosting is enabled for this example, commandline instr
   *                 has to be provided through uart but the same is displayed on
   *                 debugger console interface. It is recommended to use Uart
   *                 console interface only.
   *              2. Example is tested with FAT32 filesystem only.
   *
  */
  
  /*
  * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/ 
  */
  /* 
  *  Redistribution and use in source and binary forms, with or without 
  *  modification, are permitted provided that the following conditions 
  *  are met:
  *
  *    Redistributions of source code must retain the above copyright 
  *    notice, this list of conditions and the following disclaimer.
  *
  *    Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the 
  *    documentation and/or other materials provided with the   
  *    distribution.
  *
  *    Neither the name of Texas Instruments Incorporated nor the names of
  *    its contributors may be used to endorse or promote products derived
  *    from this software without specific prior written permission.
  *
  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  */
  
  #include "mmcsd_proto.h"
  #include "hs_mmcsdlib.h"
  #include "beaglebone.h"
  #include "edma_event.h"
  #include "soc_AM335x.h"
  #include "interrupt.h"
  #include "consoleUtils.h"
  #include "hs_mmcsd.h"
  #include "string.h"
  #include "delay.h"
  #include "cache.h"
  #include "edma.h"
  #include "mmu.h"
  #ifdef MMCSD_PERF
  #include "perf.h"
  #endif
  
  /******************************************************************************
  **                      INTERNAL MACRO DEFINITIONS
  *******************************************************************************/
  
  /* Frequency */
  #define HSMMCSD_IN_FREQ                96000000 /* 96MHz */
  #define HSMMCSD_INIT_FREQ              400000   /* 400kHz */
  
  #define HSMMCSD_CARD_DETECT_PINNUM     6
  
  /* EDMA3 Event queue number. */
  #define EVT_QUEUE_NUM                  0
   
  /* EDMA3 Region Number. */
  #define REGION_NUMBER                  0
  
  /* Block size config */
  #define HSMMCSD_BLK_SIZE               512
  #define HSMMCSD_RW_BLK                 1
  
  /* Global data pointers */
  #define HSMMCSD_DATA_SIZE              512
  
  /* GPIO instance related macros. */
  #define GPIO_INST_BASE                 (SOC_GPIO_0_REGS)
  
  /* MMCSD instance related macros. */
  #define MMCSD_INST_BASE                (SOC_MMCHS_0_REGS)
  #define MMCSD_INT_NUM                  (SYS_INT_MMCSD0INT)
  
  /* EDMA instance related macros. */
  #define EDMA_INST_BASE                 (SOC_EDMA30CC_0_REGS)
  #define EDMA_COMPLTN_INT_NUM           (SYS_INT_EDMACOMPINT)
  #define EDMA_ERROR_INT_NUM             (SYS_INT_EDMAERRINT) 
  
  /* EDMA Events */
  #define MMCSD_TX_EDMA_CHAN             (EDMA3_CHA_MMCSD0_TX)
  #define MMCSD_RX_EDMA_CHAN             (EDMA3_CHA_MMCSD0_RX)
  
  /* MMU related macros. */
  #define START_ADDR_OCMC                 0x40300000
  #define START_ADDR_DDR                  0x80000000
  #define START_ADDR_DEV                  0x44000000
  #define NUM_SECTIONS_DDR                512
  #define NUM_SECTIONS_DEV                960
  #define NUM_SECTIONS_OCMC               1
  
  /* SD card info structure */
  mmcsdCardInfo sdCard;
  
  /* SD Controller info structure */
  mmcsdCtrlInfo  ctrlInfo;
  
  /******************************************************************************
  **                      FUNCTION PROTOTYPES
  *******************************************************************************/
  extern void HSMMCSDFsMount(unsigned int driveNum, void *ptr);
  extern void HSMMCSDFsProcessCmdLine(void);
  extern int Cmd_help(int argc, char *argv[]);
  
  /* EDMA callback function array */
  static void (*cb_Fxn[EDMA3_NUM_TCC]) (unsigned int tcc, unsigned int status);
  
  /******************************************************************************
  **                      VARIABLE DEFINITIONS
  *******************************************************************************/
  /* Global flags for interrupt handling */
  volatile unsigned int sdBlkSize = HSMMCSD_BLK_SIZE;
  volatile unsigned int callbackOccured = 0; 
  volatile unsigned int xferCompFlag = 0; 
  volatile unsigned int dataTimeout = 0;
  volatile unsigned int cmdCompFlag = 0;
  volatile unsigned int cmdTimeout = 0; 
  volatile unsigned int errFlag = 0;
  
  #ifdef __IAR_SYSTEMS_ICC__
  #pragma data_alignment=SOC_CACHELINE_SIZE
  unsigned char data[HSMMCSD_DATA_SIZE];
  
  #elif defined(__TMS470__)
  #pragma DATA_ALIGN(data, SOC_CACHELINE_SIZE);
  unsigned char data[HSMMCSD_DATA_SIZE];
  
  #elif defined(gcc)
  unsigned char data[HSMMCSD_DATA_SIZE] 
                      __attribute__ ((aligned (SOC_CACHELINE_SIZE)))= {0};
  
  #else
  #error "Unsupported Compiler. \r\n"
  
  #endif
  
  /* page tables start must be aligned in 16K boundary */                  //
  #ifdef __TMS470__
  #pragma DATA_ALIGN(pageTable, MMU_PAGETABLE_ALIGN_SIZE);
  static volatile unsigned int pageTable[MMU_PAGETABLE_NUM_ENTRY];
  #elif defined(__IAR_SYSTEMS_ICC__)
  #pragma data_alignment=MMU_PAGETABLE_ALIGN_SIZE
  static volatile unsigned int pageTable[MMU_PAGETABLE_NUM_ENTRY];
  #elif defined(gcc)
  static volatile unsigned int pageTable[MMU_PAGETABLE_NUM_ENTRY] 
              __attribute__((aligned(MMU_PAGETABLE_ALIGN_SIZE)));
  #else
  #error "Unsupported Compiler. \r\n"
  #endif
  
  /******************************************************************************
  **                          FUNCTION DEFINITIONS
  *******************************************************************************/
  
  /*
  ** This function will setup the MMU. The function maps three regions -
  ** 1. DDR
  ** 2. OCMC RAM
  ** 3. Device memory
  ** The function also enables the MMU.
  */
  void MMUConfigAndEnable(void)
  {
      /*
      ** Define DDR memory region of AM335x. DDR can be configured as Normal
      ** memory with R/W access in user/privileged modes. The cache attributes
      ** specified here are,
      ** Inner - Write through, No Write Allocate
      ** Outer - Write Back, Write Allocate
      */
      REGION regionDdr = {
                          MMU_PGTYPE_SECTION, START_ADDR_DDR, NUM_SECTIONS_DDR,
                          MMU_MEMTYPE_NORMAL_NON_SHAREABLE(MMU_CACHE_WT_NOWA,
                                                           MMU_CACHE_WB_WA),
                          MMU_REGION_NON_SECURE, MMU_AP_PRV_RW_USR_RW,
                          (unsigned int*)pageTable
                         };
      /*
      ** Define OCMC RAM region of AM335x. Same Attributes of DDR region given.
      */
      REGION regionOcmc = {
                           MMU_PGTYPE_SECTION, START_ADDR_OCMC, NUM_SECTIONS_OCMC,
                           MMU_MEMTYPE_NORMAL_NON_SHAREABLE(MMU_CACHE_WT_NOWA,
                                                            MMU_CACHE_WB_WA),
                           MMU_REGION_NON_SECURE, MMU_AP_PRV_RW_USR_RW,
                           (unsigned int*)pageTable
                          };
  
      /*
      ** Define Device Memory Region. The region between OCMC and DDR is
      ** configured as device memory, with R/W access in user/privileged modes.
      ** Also, the region is marked 'Execute Never'.
      */
      REGION regionDev = {
                          MMU_PGTYPE_SECTION, START_ADDR_DEV, NUM_SECTIONS_DEV,
                          MMU_MEMTYPE_DEVICE_SHAREABLE,
                          MMU_REGION_NON_SECURE,
                          MMU_AP_PRV_RW_USR_RW  | MMU_SECTION_EXEC_NEVER,
                          (unsigned int*)pageTable
                         };
  
      /* Initialize the page table and MMU */
      MMUInit((unsigned int*)pageTable);
  
      /* Map the defined regions */
      MMUMemRegionMap(&regionDdr);
      MMUMemRegionMap(&regionOcmc);
      MMUMemRegionMap(&regionDev);
  
      /* Now Safe to enable MMU */
      MMUEnable((unsigned int*)pageTable);
  }
  
  /*
   * Check command status
   */
  
  static unsigned int HSMMCSDCmdStatusGet(mmcsdCtrlInfo *ctrl)
  {
      unsigned int status = 0;
  
      while ((cmdCompFlag == 0) && (cmdTimeout == 0));
  
      if (cmdCompFlag)
      {
          status = 1;
          cmdCompFlag = 0;
      }
  
      if (cmdTimeout)
      {
          status = 0;
          cmdTimeout = 0;
      }
  
      return status;
  }
  
  static unsigned int HSMMCSDXferStatusGet(mmcsdCtrlInfo *ctrl)
  {
      unsigned int status = 0;
      volatile unsigned int timeOut = 0xFFFF;
  
      while ((xferCompFlag == 0) && (dataTimeout == 0));
  
      if (xferCompFlag)
      {
          status = 1;
          xferCompFlag = 0;
      }
  
      if (dataTimeout)
      {
          status = 0;
          dataTimeout = 0;
      }
  
      /* Also, poll for the callback */
      if (HWREG(ctrl->memBase + MMCHS_CMD) & MMCHS_CMD_DP)
      {
          while(callbackOccured == 0 && ((timeOut--) != 0));
          callbackOccured = 0;
  
          if(timeOut == 0)
          {
              status = 0;
          }
      }
  
      ctrlInfo.dmaEnable = 0;
  
      return status;
  }
  
  void HSMMCSDRxDmaConfig(void *ptr, unsigned int blkSize, unsigned int nblks)
  {
      EDMA3CCPaRAMEntry paramSet;
  
      paramSet.srcAddr    = ctrlInfo.memBase + MMCHS_DATA;
      paramSet.destAddr   = (unsigned int)ptr;
      paramSet.srcBIdx    = 0;
      paramSet.srcCIdx    = 0;
      paramSet.destBIdx   = 4;
      paramSet.destCIdx   = (unsigned short)blkSize;
      paramSet.aCnt       = 0x4;
      paramSet.bCnt       = (unsigned short)blkSize/4;
      paramSet.cCnt       = (unsigned short)nblks;
      paramSet.bCntReload = 0x0;
      paramSet.linkAddr   = 0xffff;
      paramSet.opt        = 0;
  
      /* Set OPT */
      paramSet.opt |= ((MMCSD_RX_EDMA_CHAN << EDMA3CC_OPT_TCC_SHIFT) & EDMA3CC_OPT_TCC);
  
      /* 1. Transmission complition interrupt enable */
      paramSet.opt |= (1 << EDMA3CC_OPT_TCINTEN_SHIFT);
  
      /* 2. Read FIFO : SRC Constant addr mode */
      paramSet.opt |= (1 << 0);
  
      /* 3. SRC FIFO width is 32 bit */
      paramSet.opt |= (2 << 8);
  
      /* 4.  AB-Sync mode */
      paramSet.opt |= (1 << 2);
  
      /* configure PaRAM Set */
      EDMA3SetPaRAM(EDMA_INST_BASE, MMCSD_RX_EDMA_CHAN, &paramSet);
  
      /* Enable the transfer */
      EDMA3EnableTransfer(EDMA_INST_BASE, MMCSD_RX_EDMA_CHAN, EDMA3_TRIG_MODE_EVENT);
  }
  
  void HSMMCSDTxDmaConfig(void *ptr, unsigned int blkSize, unsigned int blks)
  {
      EDMA3CCPaRAMEntry paramSet;
  
      paramSet.srcAddr    = (unsigned int)ptr;
      paramSet.destAddr   = ctrlInfo.memBase + MMCHS_DATA;
      paramSet.srcBIdx    = 4;
      paramSet.srcCIdx    = blkSize;
      paramSet.destBIdx   = 0;
      paramSet.destCIdx   = 0;
      paramSet.aCnt       = 0x4;
      paramSet.bCnt       = (unsigned short)blkSize/4;
      paramSet.cCnt       = (unsigned short)blks;
      paramSet.bCntReload = 0x0;
      paramSet.linkAddr   = 0xffff;
      paramSet.opt        = 0;
  
      /* Set OPT */
      paramSet.opt |= ((MMCSD_TX_EDMA_CHAN << EDMA3CC_OPT_TCC_SHIFT) & EDMA3CC_OPT_TCC);
  
      /* 1. Transmission complition interrupt enable */
      paramSet.opt |= (1 << EDMA3CC_OPT_TCINTEN_SHIFT);
  
      /* 2. Read FIFO : DST Constant addr mode */
      paramSet.opt |= (1 << 1);
  
      /* 3. DST FIFO width is 32 bit */
      paramSet.opt |= (2 << 8);
  
      /* 4.  AB-Sync mode */
      paramSet.opt |= (1 << 2);
  
      /* configure PaRAM Set */
      EDMA3SetPaRAM(EDMA_INST_BASE, MMCSD_TX_EDMA_CHAN, &paramSet);
  
      /* Enable the transfer */
      EDMA3EnableTransfer(EDMA_INST_BASE, MMCSD_TX_EDMA_CHAN, EDMA3_TRIG_MODE_EVENT);
  }
  
  static void HSMMCSDXferSetup(mmcsdCtrlInfo *ctrl, unsigned char rwFlag, void *ptr,
                               unsigned int blkSize, unsigned int nBlks)
  {
      callbackOccured = 0;
      xferCompFlag = 0;
  
      if (rwFlag == 1)
      {
          HSMMCSDRxDmaConfig(ptr, blkSize, nBlks);
      }
      else
      {
          HSMMCSDTxDmaConfig(ptr, blkSize, nBlks);
      }
  
      ctrl->dmaEnable = 1;
      HSMMCSDBlkLenSet(ctrl->memBase, blkSize);
  }
  
  
  /*
  ** This function is used as a callback from EDMA3 Completion Handler.
  */
  static void callback(unsigned int tccNum, unsigned int status)
  {
      callbackOccured = 1;
      EDMA3DisableTransfer(EDMA_INST_BASE, tccNum, EDMA3_TRIG_MODE_EVENT);
  }
  
  static void Edma3CompletionIsr(void)
  {
      volatile unsigned int pendingIrqs;
      volatile unsigned int isIPR = 0;
  
      unsigned int indexl;
      unsigned int Cnt = 0;
  
      indexl = 1;
  
      isIPR = EDMA3GetIntrStatus(EDMA_INST_BASE);
  
      if(isIPR)
      {
          while ((Cnt < EDMA3CC_COMPL_HANDLER_RETRY_COUNT)&& (indexl != 0u))
          {
              indexl = 0u;
              pendingIrqs = EDMA3GetIntrStatus(EDMA_INST_BASE);
  
              while (pendingIrqs)
              {
                  if((pendingIrqs & 1u) == TRUE)
                  {
                      /**
                      * If the user has not given any callback function
                      * while requesting the TCC, its TCC specific bit
                      * in the IPR register will NOT be cleared.
                      */
                      /* here write to ICR to clear the corresponding IPR bits */
  
                      EDMA3ClrIntr(EDMA_INST_BASE, indexl);
  
                      if (cb_Fxn[indexl] != NULL)
                      {
                          (*cb_Fxn[indexl])(indexl, EDMA3_XFER_COMPLETE);
                      }
                  }
                  ++indexl;
                  pendingIrqs >>= 1u;
              }
              Cnt++;
          }
      }
  }
  
  static void Edma3CCErrorIsr(void)
  {
      volatile unsigned int pendingIrqs;
      volatile unsigned int evtqueNum = 0;  /* Event Queue Num */
      volatile unsigned int isIPRH = 0;
      volatile unsigned int isIPR = 0;
      volatile unsigned int Cnt = 0u;
      volatile unsigned int index;
  
      pendingIrqs = 0u;
      index = 1u;
  
      isIPR  = EDMA3GetIntrStatus(EDMA_INST_BASE);
      isIPRH = EDMA3IntrStatusHighGet(EDMA_INST_BASE);
  
      if((isIPR | isIPRH ) || (EDMA3QdmaGetErrIntrStatus(EDMA_INST_BASE) != 0)
          || (EDMA3GetCCErrStatus(EDMA_INST_BASE) != 0))
      {
          /* Loop for EDMA3CC_ERR_HANDLER_RETRY_COUNT number of time,
           * breaks when no pending interrupt is found
           */
          while ((Cnt < EDMA3CC_ERR_HANDLER_RETRY_COUNT)
                      && (index != 0u))
          {
              index = 0u;
  
              if(isIPR)
              {
                     pendingIrqs = EDMA3GetErrIntrStatus(EDMA_INST_BASE);
              }
              else
              {
                     pendingIrqs = EDMA3ErrIntrHighStatusGet(EDMA_INST_BASE);
              }
  
              while (pendingIrqs)
              {
                     /*Process all the pending interrupts*/
                     if(TRUE == (pendingIrqs & 1u))
                     {
                        /* Write to EMCR to clear the corresponding EMR bits.
                         */
                          /*Clear any SER*/
  
                          if(isIPR)
                          {
                               EDMA3ClrMissEvt(EDMA_INST_BASE, index);
                          }
                          else
                          {
                               EDMA3ClrMissEvt(EDMA_INST_BASE, index + 32);
                          }
                     }
                     ++index;
                     pendingIrqs >>= 1u;
              }
              index = 0u;
              pendingIrqs = EDMA3QdmaGetErrIntrStatus(EDMA_INST_BASE);
              while (pendingIrqs)
              {
                  /*Process all the pending interrupts*/
                  if(TRUE == (pendingIrqs & 1u))
                  {
                      /* Here write to QEMCR to clear the corresponding QEMR bits*/
                      /*Clear any QSER*/
                      EDMA3QdmaClrMissEvt(EDMA_INST_BASE, index);
                  }
                  ++index;
                  pendingIrqs >>= 1u;
              }
              index = 0u;
  
  
              pendingIrqs = EDMA3GetCCErrStatus(EDMA_INST_BASE);
              if (pendingIrqs != 0u)
              {
              /* Process all the pending CC error interrupts. */
              /* Queue threshold error for different event queues.*/
              for (evtqueNum = 0u; evtqueNum < SOC_EDMA3_NUM_EVQUE; evtqueNum++)
                  {
                  if((pendingIrqs & (1u << evtqueNum)) != 0u)
                  {
                          /* Clear the error interrupt. */
                          EDMA3ClrCCErr(EDMA_INST_BASE, (1u << evtqueNum));
                      }
                  }
  
              /* Transfer completion code error. */
              if ((pendingIrqs & (1 << EDMA3CC_CCERR_TCCERR_SHIFT)) != 0u)
              {
                  EDMA3ClrCCErr(EDMA_INST_BASE,
                                        (0x01u << EDMA3CC_CCERR_TCCERR_SHIFT));
              }
                  ++index;
              }
              Cnt++;
          }
      }
  
  }
  
  static void HSMMCSDIsr(void)
  {
      volatile unsigned int status = 0;
  
      status = HSMMCSDIntrStatusGet(ctrlInfo.memBase, 0xFFFFFFFF);
      
      HSMMCSDIntrStatusClear(ctrlInfo.memBase, status);
  
      if (status & HS_MMCSD_STAT_CMDCOMP)
      {
          cmdCompFlag = 1;
      }
  
      if (status & HS_MMCSD_STAT_ERR)
      {
          errFlag = status & 0xFFFF0000;
  
          if (status & HS_MMCSD_STAT_CMDTIMEOUT)
          {
              cmdTimeout = 1;
          }
  
          if (status & HS_MMCSD_STAT_DATATIMEOUT)
          {
              dataTimeout = 1;
          }
      }
  
      if (status & HS_MMCSD_STAT_TRNFCOMP)
      {
          xferCompFlag = 1;
      }
  }
  
  
  /*
  ** This function configures the AINTC to receive EDMA3 interrupts.
  */
  static void EDMA3AINTCConfigure(void)
  {
      /* Initializing the ARM Interrupt Controller. */
      IntAINTCInit();
  
      /* Registering EDMA3 Channel Controller transfer completion interrupt.  */
      IntRegister(EDMA_COMPLTN_INT_NUM, Edma3CompletionIsr);
  
      /* Setting the priority for EDMA3CC completion interrupt in AINTC. */
      IntPrioritySet(EDMA_COMPLTN_INT_NUM, 0, AINTC_HOSTINT_ROUTE_IRQ);
  
      /* Registering EDMA3 Channel Controller Error Interrupt. */
      IntRegister(EDMA_ERROR_INT_NUM, Edma3CCErrorIsr);
  
      /* Setting the priority for EDMA3CC Error interrupt in AINTC. */
      IntPrioritySet(EDMA_ERROR_INT_NUM, 0, AINTC_HOSTINT_ROUTE_IRQ);
  
      /* Enabling the EDMA3CC completion interrupt in AINTC. */
      IntSystemEnable(EDMA_COMPLTN_INT_NUM);
      
      /* Enabling the EDMA3CC Error interrupt in AINTC. */
      IntSystemEnable(EDMA_ERROR_INT_NUM);
  
      /* Registering HSMMC Interrupt handler */
      IntRegister(MMCSD_INT_NUM, HSMMCSDIsr);
  
      /* Setting the priority for EDMA3CC completion interrupt in AINTC. */
      IntPrioritySet(MMCSD_INT_NUM, 0, AINTC_HOSTINT_ROUTE_IRQ);
  
      /* Enabling the HSMMC interrupt in AINTC. */
      IntSystemEnable(MMCSD_INT_NUM);
  
      /* Enabling IRQ in CPSR of ARM processor. */
      IntMasterIRQEnable();
  }
  
  
  /* 
  ** Powering up, initializing and registering interrupts for EDMA.
  */
  
  static void EDMA3Initialize(void)
  {
      /* Initialization of EDMA3 */
      EDMA3Init(EDMA_INST_BASE, EVT_QUEUE_NUM);
  
      /* Configuring the AINTC to receive EDMA3 interrupts. */ 
      EDMA3AINTCConfigure();
  }
  
  static void HSMMCSDEdmaInit(void)
  {
      /* Initializing the EDMA. */
      EDMA3Initialize();
  
      /* Request DMA Channel and TCC for MMCSD Transmit*/
      EDMA3RequestChannel(EDMA_INST_BASE, EDMA3_CHANNEL_TYPE_DMA,
                          MMCSD_TX_EDMA_CHAN, MMCSD_TX_EDMA_CHAN,
                          EVT_QUEUE_NUM);
  
      /* Registering Callback Function for TX*/
      cb_Fxn[MMCSD_TX_EDMA_CHAN] = &callback;
  
      /* Request DMA Channel and TCC for MMCSD Receive */
      EDMA3RequestChannel(EDMA_INST_BASE, EDMA3_CHANNEL_TYPE_DMA,
                          MMCSD_RX_EDMA_CHAN, MMCSD_RX_EDMA_CHAN,
                          EVT_QUEUE_NUM);
  
      /* Registering Callback Function for RX*/
      cb_Fxn[MMCSD_RX_EDMA_CHAN] = &callback;
  }
  
  /*
  ** Initialize the MMCSD controller structure for use
  */
  static void HSMMCSDControllerSetup(void)
  {
      ctrlInfo.memBase = MMCSD_INST_BASE;
      ctrlInfo.ctrlInit = HSMMCSDControllerInit;
      ctrlInfo.xferSetup = HSMMCSDXferSetup;
      ctrlInfo.cmdStatusGet = HSMMCSDCmdStatusGet;
      ctrlInfo.xferStatusGet = HSMMCSDXferStatusGet;
      /* Use the funciton HSMMCSDCDPinStatusGet() to use the card presence
         using the controller.
      */
      ctrlInfo.cardPresent = HSMMCSDCardPresent;
      ctrlInfo.cmdSend = HSMMCSDCmdSend;
      ctrlInfo.busWidthConfig = HSMMCSDBusWidthConfig;
      ctrlInfo.busFreqConfig = HSMMCSDBusFreqConfig;
      ctrlInfo.intrMask = (HS_MMCSD_INTR_CMDCOMP | HS_MMCSD_INTR_CMDTIMEOUT |
                              HS_MMCSD_INTR_DATATIMEOUT | HS_MMCSD_INTR_TRNFCOMP);
      ctrlInfo.intrEnable = HSMMCSDIntEnable;
      ctrlInfo.busWidth = (SD_BUS_WIDTH_1BIT | SD_BUS_WIDTH_4BIT);
      ctrlInfo.highspeed = 1;
      ctrlInfo.ocr = (SD_OCR_VDD_3P0_3P1 | SD_OCR_VDD_3P1_3P2);
      ctrlInfo.card = &sdCard;
      ctrlInfo.ipClk = HSMMCSD_IN_FREQ;
      ctrlInfo.opClk = HSMMCSD_INIT_FREQ;
      ctrlInfo.cdPinNum = HSMMCSD_CARD_DETECT_PINNUM;
      sdCard.ctrl = &ctrlInfo;
  
      callbackOccured = 0;
      xferCompFlag = 0;
      dataTimeout = 0;
      cmdCompFlag = 0;
      cmdTimeout = 0;
  }
  
  
  int main(void)
  {
      volatile unsigned int i = 0;
      volatile unsigned int initFlg = 1;
  
      /* Setup the MMU and do necessary MMU configurations. */
      MMUConfigAndEnable();
  
      /* Enable all levels of CACHE. */
      CacheEnable(CACHE_ALL);
  
      /* Initialize console for communication with the Host Machine */
      ConsoleUtilsInit();
  
      /*
      ** Select the console type based on compile time check
      ** Note: This example is not fully complaint to semihosting. It is
      **       recommended to use Uart console interface only.
      */
      ConsoleUtilsSetType(CONSOLE_UART);
  
      /* Configure the EDMA clocks. */
      EDMAModuleClkConfig();
  
      /* Configure EDMA to service the HSMMCSD events. */
      HSMMCSDEdmaInit();
  
      /* Perform pin-mux for HSMMCSD pins. */
      HSMMCSDPinMuxSetup();
  
      /* Enable module clock for HSMMCSD. */
      HSMMCSDModuleClkConfig();
  
      DelayTimerSetup();
  
  #ifdef MMCSD_PERF
      PerfTimerSetup();
  #endif
  
      /* Basic controller initializations */
      HSMMCSDControllerSetup();
  
      /* Initialize the MMCSD controller */
      MMCSDCtrlInit(&ctrlInfo);
  
      MMCSDIntEnable(&ctrlInfo);
  
      while(1)
      {
          if((HSMMCSDCardPresent(&ctrlInfo)) == 1)
          {
              if(initFlg)
              {
                  HSMMCSDFsMount(0, &sdCard);
                  initFlg = 0;
                  Cmd_help(0, NULL);
              }
              HSMMCSDFsProcessCmdLine();
          }
          else
          {
              delay(1);
  
              i = (i + 1) & 0xFFF;
  
              if(i == 1)
              {
                   ConsoleUtilsPrintf("Please insert the card \n\r");
              }
  
              if(initFlg != 1)
              {
                   /* Reinitialize all the state variables */
                   callbackOccured = 0;
                   xferCompFlag = 0;
                   dataTimeout = 0;
                   cmdCompFlag = 0;
                   cmdTimeout = 0;
  
                   /* Initialize the MMCSD controller */
                   MMCSDCtrlInit(&ctrlInfo);
  
                   MMCSDIntEnable(&ctrlInfo);
              }
  
              initFlg = 1;
          }
      }
  }
  
  