打印

RL-FlashFS V6.X提供的H7版CMSIS-Driver驱动并不支持eMMC,得自己修改实现

[复制链接]
306|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
3月的尾巴|  楼主 | 2018-8-4 07:26 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
当前提供的这个MCI_STM32H7XXX驱动文件仅支持SD卡,实际测试并不支持eMMC。

这个自己修改还是有点难度的,而使用老版本的RL-FlashFS好修改些。

之前F4的驱动写法:#define __DRV_ID   mci0_drv
#define __SDIOCLK  48000000
#define __CPUCLK  168000000

/* MCI Driver Interface functions */
static BOOL Init (void);
static BOOL UnInit (void);
static void Delay (U32 us);
static BOOL BusMode (U32 mode);
static BOOL BusWidth (U32 width);
static BOOL BusSpeed (U32 kbaud);
static BOOL Command (U8 cmd, U32 arg, U32 resp_type, U32 *rp);
static BOOL ReadBlock (U32 bl, U8 *buf, U32 cnt);
static BOOL WriteBlock (U32 bl, U8 *buf, U32 cnt);
static BOOL SetDma (U32 mode, U8 *buf, U32 cnt);
static U32  CheckMedia (void);        /* Optional function for SD card check  */
void SD_Link_EXTIConfig(void);

/* MCI Device Driver Control Block */
MCI_DRV __DRV_ID = {
  Init,
  UnInit,
  Delay,
  BusMode,
  BusWidth,
  BusSpeed,
  Command,
  ReadBlock,
  WriteBlock,
  SetDma,
  CheckMedia                            /* Can be NULL if not existing        */
};


/* Wait time in for loop cycles */
#define DMA_TOUT  10000000

/*--------------------------- Init -------------------------------------------*/

static BOOL Init (void) {
  /* Initialize SDIO interface. */
  /* Enable GPIOE (card detect), GPIOD (command), GPIOC (data) clock */
  RCC->AHB1ENR |= RCC_AHB1ENR_GPIOEEN |
                  RCC_AHB1ENR_GPIODEN |
                  RCC_AHB1ENR_GPIOCEN;

  RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN;
  /* Enable IO compensation cell */
  SYSCFG->CMPCR |= SYSCFG_CMPCR_CMP_PD;
  while (!(SYSCFG->CMPCR & SYSCFG_CMPCR_READY));

  /* PC.08, PC.09, PC.10, PC.11, PC.12 pin: D0, D1, D2, D3, CLK pin */
  GPIOC->MODER   &= ~0x03FF0000;
  GPIOC->MODER   |=  0x02AA0000;        /* Pins to alternate function         */
  GPIOC->OTYPER  &= ~0x00001F00;        /* Configure as push-pull pins        */
  GPIOC->PUPDR   &= ~0x03FF0000;
  GPIOC->PUPDR   |=  0x01550000;        /* Pull-ups on pins                   */
  GPIOC->OSPEEDR |=  0x03FF0000;        /* Pins output speed to 100MHz        */

  GPIOC->AFR[1]  &= ~0x000FFFFF;
  GPIOC->AFR[1]  |=  0x000CCCCC;        /* Pins assigned to AF12 (SDIO)       */

  /* Configure PD.02 CMD line */
  GPIOD->MODER   &= ~0x0000030;
  GPIOD->MODER   |=  0x0000020;         /* Pins to alternate function         */
  GPIOD->OTYPER  &= ~0x0000004;         /* Configure as push-pull pin         */
  GPIOD->PUPDR   &= ~0x0000030;
  GPIOD->PUPDR   |=  0x0000010;         /* Pull-up on pin                     */      
  GPIOD->OSPEEDR |=  0x0000030;         /* Pins output speed to 100MHz        */

  GPIOD->AFR[0]  &= ~0x00000F00;
  GPIOD->AFR[0]  |=  0x00000C00;        /* Pin assigned to AF12 (SDIO)        */

  /* Configure PE.2 Card Detect input */
  SD_Link_EXTIConfig();

  /* Enable SDIO clock */
  RCC->APB2ENR  |=  RCC_APB2ENR_SDIOEN;

  /* Reset/Dereset SDIO */
  RCC->APB2RSTR |=  RCC_APB2RSTR_SDIORST;
  RCC->APB2RSTR &= ~RCC_APB2RSTR_SDIORST;

  /* Power-on, the card is clocked */
  SDIO->POWER  = SDIO_POWER_PWRCTRL_1 | SDIO_POWER_PWRCTRL_0;

    /* Enable DMA2 clock */
  RCC->AHB1ENR |= RCC_AHB1ENR_DMA2EN;

  /* Success, SDIO initialized. */
  return (__TRUE);
}


/*--------------------------- UnInit -----------------------------------------*/

static BOOL UnInit (void) {

  /* Reset PC.8, PC.9, PC.10, PC.11, PC.12 pins */
  GPIOC->MODER &= ~0x03FF0000;
  /* Reset PD.2 */
  GPIOD->MODER &= ~(3 <<  4);

  /* Disable SDIO module clock */
  RCC->APB2ENR &= ~RCC_APB2ENR_SDIOEN;

  return (__TRUE);
}


/*--------------------------- Delay ------------------------------------------*/

static void Delay (U32 us) {
  /* Approximate delay in micro seconds. */
  U32 i;

  for (i = WAIT_CNT(__CPUCLK, us); i; i--);
}


/*--------------------------- BusMode ----------------------------------------*/

static BOOL BusMode (U32 mode) {
  /* Set SDIO Bus mode to Open Drain or Push Pull. */

  switch (mode) {
    case BUS_OPEN_DRAIN:
      GPIOD->OTYPER  |=  0x00000010;    /* Configure as open-drain            */
      return (__TRUE);

    case BUS_PUSH_PULL:
      GPIOD->OTYPER  &= ~0x00000010;    /* Configure as push-pull pin         */
      return (__TRUE);
   
    default:
      return (__FALSE);
  }
}


/*--------------------------- BusWidth ---------------------------------------*/

static BOOL BusWidth (U32 width) {
  /* Set SDIO Bus width. */

  switch (width) {
    case 1:
      SDIO->CLKCR &= ~SDIO_CLKCR_WIDBUS;
      return (__TRUE);

    case 4:
#ifdef __XYNERGY
      return (__FALSE);
#else
      SDIO->CLKCR |=  SDIO_CLKCR_WIDBUS_0;
      return (__TRUE);
#endif
   
    default:
      return (__FALSE);
  }
}


/*--------------------------- BusSpeed ---------------------------------------*/

static BOOL BusSpeed (U32 kbaud) {
  /* Set SDIO clock speed to desired value. */
  U32 div;

  /* baud = SDIOCLK / (div + 2) */
  div = (__SDIOCLK/1000 + kbaud - 1) / kbaud;
  if (div < 2)    div  = 0;
  else            div -= 2;
  if (div > 0xFF) div  = 0xFF;
  SDIO->CLKCR = (SDIO->CLKCR & ~0xFF) | SDIO_CLKCR_PWRSAV | SDIO_CLKCR_CLKEN | div;
  return (__TRUE);
}


/*--------------------------- Command ----------------------------------------*/

static BOOL Command (U8 cmd, U32 arg, U32 resp_type, U32 *rp) {
  /* Send a Command to Flash card and get a Response. */
  U32 cmdval,stat;

  cmd   &= SDIO_CMD_CMDINDEX;
  cmdval = SDIO_CMD_CPSMEN | cmd;
  switch (resp_type) {
    case RESP_SHORT:
      cmdval |= SDIO_CMD_WAITRESP_0;
      break;
    case RESP_LONG:
      cmdval |= SDIO_CMD_WAITRESP_1 | SDIO_CMD_WAITRESP_0;
      break;
  }
  /* Send the command. */
  SDIO->ARG = arg;
  SDIO->CMD = cmdval;

  if (resp_type == RESP_NONE) {
    /* Wait until command finished. */
    while (SDIO->STA & SDIO_STA_CMDACT);
    stat = SDIO->STA;
    SDIO->ICR = 0x00C007FF;
    if (stat & SDIO_STA_CMDSENT) {
      return (__TRUE);
    }
    return (__FALSE);   
  }

  for (;;) {
    stat = SDIO->STA;
    if (stat & SDIO_STA_CTIMEOUT) {
      SDIO->ICR = stat & SDIO_STA_CLEAR_MASK;
      return (__FALSE);
    }
    if (stat & SDIO_STA_CCRCFAIL) {
      SDIO->ICR = stat & SDIO_STA_CLEAR_MASK;
      if ((cmd == SEND_OP_COND)      ||
          (cmd == SEND_APP_OP_COND)  ||
          (cmd == STOP_TRANS)) {
        SDIO->CMD = 0;
        break;
      }
      return (__FALSE);
    }
    if (stat & SDIO_STA_CMDREND) {
      SDIO->ICR = stat & SDIO_STA_CLEAR_MASK;
      break;
    }
  }
  if ((SDIO->RESPCMD & 0x3F) != cmd) {
    if ((SDIO->RESPCMD & 0x3F) != 0x3F) {
      return (__FALSE);
    }
  }
  /* Read MCI response registers */
  rp[0] = SDIO->RESP1;
  if (resp_type == RESP_LONG) {
    rp[1] = SDIO->RESP2;
    rp[2] = SDIO->RESP3;
    rp[3] = SDIO->RESP4;
  }
  return (__TRUE);
}


/*--------------------------- ReadBlock --------------------------------------*/

static BOOL ReadBlock (U32 bl, U8 *buf, U32 cnt) {
  /* Read one or more 512 byte blocks from Flash Card. */
  U32 i;

  SDIO->DLEN    = cnt * 512;
  SDIO->DTIMER  = cnt * DATA_RD_TOUT_VALUE;

  SDIO->DCTRL   = SDIO_DCTRL_DBLOCKSIZE_3 | SDIO_DCTRL_DBLOCKSIZE_0 |
                  SDIO_DCTRL_DMAEN        | SDIO_DCTRL_DTDIR        |
                  SDIO_DCTRL_DTEN         ;

  for (i = DMA_TOUT; i; i--) {   
    if (DMA2->LISR & DMA_LISR_TEIF3) {
      break;
    }
   
    if (DMA2->LISR & DMA_LISR_TCIF3) {
      if ((SDIO->STA & (SDIO_STA_DBCKEND|SDIO_STA_DATAEND)) == (SDIO_STA_DBCKEND|SDIO_STA_DATAEND)) {
        /* Data transfer finished. */
        return (__TRUE);
      }
    }
  }
  /* DMA Transfer timeout. */
  return (__FALSE);
}


/*--------------------------- WriteBlock -------------------------------------*/

static BOOL WriteBlock (U32 bl, U8 *buf, U32 cnt) {
  /* Write a cnt number of 512 byte blocks to Flash Card. */
  U32 i;

  SDIO->DLEN    = cnt * 512;
  SDIO->DTIMER  = cnt * DATA_WR_TOUT_VALUE;
  SDIO->DCTRL   = SDIO_DCTRL_DBLOCKSIZE_3 | SDIO_DCTRL_DBLOCKSIZE_0 |
                  SDIO_DCTRL_DMAEN        | SDIO_DCTRL_DTEN         ;

  for (i = DMA_TOUT; i; i--) {
    if (DMA2->LISR & DMA_LISR_TEIF3) {
      break;
    }
   
    if (DMA2->LISR & DMA_LISR_TCIF3) {
      if ((SDIO->STA & (SDIO_STA_DBCKEND|SDIO_STA_DATAEND)) == (SDIO_STA_DBCKEND|SDIO_STA_DATAEND)) {
        /* Data transfer finished. */
        return (__TRUE);
      }
    }
  }
  /* DMA Transfer timeout. */
  return (__FALSE);
}


/*--------------------------- DmaStart ---------------------------------------*/

static BOOL SetDma (U32 mode, U8 *buf, U32 cnt) {
  /* Configure DMA Channel 4, Stream 3 for read or write */

  DMA2->LIFCR = 0x0F4 << 20;                   /* Clear all IRQs              */

  DMA2_Stream3->CR  &= ~DMA_SxCR_EN;           /* Disable stream 3            */
  while (DMA2_Stream3->CR & DMA_SxCR_EN);      /* Wait until stream disabled  */

  DMA2_Stream3->FCR |=  DMA_SxFCR_DMDIS |      /* Disable direct mode         */
                        DMA_SxFCR_FTH   ;      /* FIFO threshold full         */

  DMA2_Stream3->PAR  = (U32)&(SDIO->FIFO);
  DMA2_Stream3->M0AR = (U32)buf;

  if (mode == DMA_READ) {
    /* Transfer from SDIO-FIFO to memory. */
    DMA2_Stream3->CR = (4 << 25) |             /* Use channel 4               */
                       (1 << 23) |             /* Memory burst 4 beats        */
                       (1 << 21) |             /* Peripheral burst 4 beats    */
                       (3 << 16) |             /* Priority level high         */
                       (2 << 13) |             /* Memory size 32-bits         */
                       (2 << 11) |             /* Peripheral size 32-bits     */
                       (1 << 10) |             /* Memory addr increment       */
                       (1 <<  5) ;             /* Peripheral flow control     */
  }
  else {
    /* Transfer from memory to SDIO-FIFO. */
    DMA2_Stream3->CR = (4 << 25) |             /* Use channel 4               */
                       (1 << 23) |             /* Memory burst 4 beats        */
                       (1 << 21) |             /* Peripheral burst 4 beats    */
                       (3 << 16) |             /* Priority level very high    */
                       (2 << 13) |             /* Memory size 32-bits         */
                       (2 << 11) |             /* Peripheral size 32-bits     */
                       (1 << 10) |             /* Memory addr increment       */
                       (1 <<  6) |             /* Memory-to-peripheral        */
                       (1 <<  5) ;             /* Peripheral flow control     */
  }

  /* Enable DMA channels, little endian */
  DMA2_Stream3->CR  |= DMA_SxCR_EN;            /* Enable stream 3             */
  return __TRUE;
}


/*--------------------------- CheckMedia -------------------------------------*/

static U32 CheckMedia (void) {
  /* Read CardDetect and WriteProtect SD card socket pins. */
  U32 stat = 0;

  if (!(GPIOE->IDR & (1 << 2))) {
    /* Card is inserted (CD=0). */
    stat |= M_INSERTED;
  }

#if 0
  if (/* Write protect switch is active */) {
    stat |= M_PROTECTED;
  }
#endif

  return (stat);
}

使用特权

评论回复

相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

433

主题

433

帖子

0

粉丝