⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mmc.c

📁 NXP LPC系列AMR7的开发程序源码(LCD
💻 C
📖 第 1 页 / 共 2 页
字号:
Int32U Freq;
Int64U Tmp;
  // Calculate SPI max clock
  Freq = MmcTransfExp[CSD_GET_TRAN_SPEED_EXP()] * MmcCsdMant[CSD_GET_TRAN_SPEED_MANT()];
  Freq = MmcSetClockFreq(Freq);
  if(MmcDskCtrlBlk.DiskType == DiskMMC)
  {
    // Calculate Time outs for MMC cards
    Tmp = MmmcAccessTime[CSD_GET_TAAC_EXP()] * MmcCsdMant[CSD_GET_TAAC_MANT()];
    Tmp /= 10000; // us
    // Freq [Hz], Tmp[1 us], *10
    Tmp = (Freq*Tmp)/100000LL;
    // NSAC*100*10
    Tmp += 1000*CSD_GET_NSAC();
    // Max time out
    Tnac = Tmp;
    Twr  = Tmp * (1<<CSD_GET_R2W_FACTOR());
  }
  else
  {
    // Calculate Time outs for SD cards
    // Freq [Hz], RD_TIME_OUT[ms]
    Tmp = Freq/1000;
    Tnac = Tmp * RD_TIME_OUT;
    Twr  = Tmp * WR_TIME_OUT;
  }
  // Calculate Block size and Block Number
  MmcDskCtrlBlk.BlockSize = 1<<CSD_GET_READ_BL_LEN();
  MmcDskCtrlBlk.BlockNumb = (CSD_GET_C_SIZE()+1)*(4<<CSD_GET_C_SIZE_MULT());
  // Set Write Protect
  bMmcPermWriteProtect = CSD_GET_PERM_WRITE_PROTECT() |\
                         CSD_GET_TMP_WRITE_PROTECT();
  MmcDskCtrlBlk.WriteProtect = MmcWriteProtect() |\
                               bMmcPermWriteProtect;
}

/*************************************************************************
 * Function Name: MmcRead
 * Parameters: pInt8U pData, Int32U Add, Int32U Length
 *
 * Return: MmcState_t
 *
 * Description: Read from a Mmc
 *
 *************************************************************************/
inline
MmcState_t MmcRead(pInt8U pData, Int32U Add, Int32U Length)
{
Int32U Data;
MmcState_t Status = MmcOk;
DataCtrl_t DataCtrl = {0};

  if(Length == 0)
  {
    return(Status);
  }
  // Check data length size - it must be divisible of the card's block size
  assert((Length % MmcDskCtrlBlk.BlockSize) == 0);

  // Set read time out
  MCIDATATIMER = Tnac;
  // Clear all related flags
  MCICLEAR = 0x0000072A;

  // DMA init
  // set source address
  DMACC0SRCADDR = (Int32U)&MCIFIFO0;
  // set destination address
  DMACC0LLI = 0;                  // no linked list
  DMACC0CONTROL_bit.SWIDTH = 2;   // source width 32 bits
  DMACC0CONTROL_bit.DWIDTH = 0;   // destination width 8 bits
  DMACC0CONTROL_bit.SBSIZE = 2;   // 8 words
  DMACC0CONTROL_bit.DBSIZE = 2;   // 8 words
  DMACC0CONTROL_bit.DI = 1;       // destination address increment
  DMACC0CONTROL_bit.SI = 0;       // source address increment
  DMACC0CONTROL_bit.I  = 1;       // enable terminal count interrupt

  while(Length)
  {
    // Set data size for one block
    MCIDATALENGTH = MmcDskCtrlBlk.BlockSize;
    Data = Add;
    Status = MmcSendCmd(CMD17,&Data);
    if(MmcOk != Status)
    {
      return(Status);
    }

    if(!(Data & READY_FOR_DATA) ||
       ((Data & CURRENT_STATE) != CARD_TRAN))
    {
      MmcSendCmd(CMD12,NULL);
      return(MmcCardError);
    }

    DMACC0DESTADDR = (Int32U)pData;
    // Peripheral to memory. Peripheral control
    DMACC0CONFIGURATION_bit.SRCPERIPHERAL = DMA_MMCSD;
    DMACC0CONFIGURATION_bit.DESTPERIPHERAL = 0;
    DMACC0CONFIGURATION_bit.FLOWCNTRL = 6;
    DMACC0CONFIGURATION_bit.L = 1;
    DMACC0CONFIGURATION_bit.E = 1;

    // block length
    DataCtrl.BLOCKSIZE = CSD_GET_READ_BL_LEN();
    // Data direction
    DataCtrl.DIRECTION = 1;
    // Block transfer
    DataCtrl.MODE = 0;
    // DMA disable
    DataCtrl.DMAENABLE = 1;
    // Enable data path
    DataCtrl.ENABLE = 1;
    MCIDATACTRL = DataCtrl.Data;
    MCI_BUS_DLY();

    // wait receive complete
    while(MCISTATUS_bit.RXACTIVE);

    DMACC0CONFIGURATION_bit.E = 0;
    if(DMACRAWINTERRORSTATUS_bit.RAWINTERRORSTATUS0)
    {
      // clear error flag and terminate transfer
      DMACINTERRCLR_bit.INTERRCLR0 = 1;
      return(MmcDmaError);
    }

    DMACINTTCCLEAR_bit.INTTCCLEAR0 = 1;

    MCIDATACTRL = 0;
    MCI_BUS_DLY();

    // data timeout
    if(MCISTATUS_bit.DATATIMEOUT)
    {
      MCICLEAR = 1UL << 3;
      return(MmcNoResponse);
    }
    // Start bit not detected on all data signals in wide bus mode.
    if(MCISTATUS_bit.STARTBITERR)
    {
      MCICLEAR = 1UL << 9;
      return(MmcCardError);
    }
    // CRC error
    if(MCISTATUS_bit.DATACRCFAIL)
    {
      MCICLEAR = 1UL << 1;
      return(MmcCardError);
    }
    // rx overrun
    if(MCISTATUS_bit.RXOVERRUN)
    {
      MCICLEAR = 1UL << 5;
      return(MmcCardError);
    }

    Length -= MmcDskCtrlBlk.BlockSize;
    Add += MmcDskCtrlBlk.BlockSize;
    pData += MmcDskCtrlBlk.BlockSize;

    // Clear data end and data block end
    MCICLEAR = (1UL << 8) | (1UL << 10);
    // data end
    if(!Length)
    {
      return(Status);
    }
    // loop read next block
  }
  return(Status);
}

/*************************************************************************
 * Function Name: MmcWrite
 * Parameters: const Int8U * pData, Int32U Add, Int32U Length
 *
 * Return: MmcState_t
 *
 * Description: Write to a Mmc
 *
 *************************************************************************/
inline
MmcState_t MmcWrite(const Int8U * pData, Int32U Add, Int32U Length)
{
Int32U Data;
MmcState_t Status = MmcOk;
DataCtrl_t DataCtrl = {0};

  if(!Length)
  {
    return(Status);
  }
  // Check data length size - it must be divisible of the card's block size
  assert((Length % MmcDskCtrlBlk.BlockSize) == 0);

  // Set write time out
  MCIDATATIMER = Twr;
  // Clear all related flags
  MCICLEAR = 0x0000072A;

  // DMA init
  // set source address
  DMACC0DESTADDR = (Int32U)&MCIFIFO0;
  DMACC0LLI = 0;                  // no linked list
  DMACC0CONTROL_bit.SWIDTH = 0;   // source width 8 bits
  DMACC0CONTROL_bit.DWIDTH = 2;   // destination width 32 bits
  DMACC0CONTROL_bit.SBSIZE = 2;   // 8 words
  DMACC0CONTROL_bit.DBSIZE = 2;   // 8 words
  DMACC0CONTROL_bit.DI = 0;       // destination address increment
  DMACC0CONTROL_bit.SI = 1;       // source address increment
  DMACC0CONTROL_bit.I  = 1;       // enable terminal count interrupt

  while(Length)
  {
    // Set data size for one block
    MCIDATALENGTH = MmcDskCtrlBlk.BlockSize;

    Data = Add;
    Status = MmcSendCmd(CMD24,&Data);
    if(MmcOk != Status)
    {
      return(Status);
    }

    if(!(Data & READY_FOR_DATA) ||
       ((Data & CURRENT_STATE) != CARD_TRAN))
    {
      MmcSendCmd(CMD12,NULL);
      return(MmcCardError);
    }

    // set destination address
    DMACC0SRCADDR = (Int32U)pData;
    // Peripheral to memory. Peripheral control
    DMACC0CONFIGURATION_bit.SRCPERIPHERAL = 0;
    DMACC0CONFIGURATION_bit.DESTPERIPHERAL = DMA_MMCSD;
    DMACC0CONFIGURATION_bit.FLOWCNTRL = 5;
    DMACC0CONFIGURATION_bit.L = 1;
    DMACC0CONFIGURATION_bit.E = 1;

    // block length
    DataCtrl.BLOCKSIZE = CSD_GET_READ_BL_LEN();
    // Data direction
    DataCtrl.DIRECTION = 0;
    // Block transfer
    DataCtrl.MODE = 0;
    // DMA disable
    DataCtrl.DMAENABLE = 1;
    // Enable data path
    DataCtrl.ENABLE = 1;
    MCIDATACTRL = DataCtrl.Data;
    MCI_BUS_DLY();

    // wait transfer complete
    while(MCISTATUS_bit.TXACTIVE);

    DMACC0CONFIGURATION_bit.E = 0;
    if(DMACRAWINTERRORSTATUS_bit.RAWINTERRORSTATUS0)
    {
      // clear error flag and terminate transfer
      DMACINTERRCLR_bit.INTERRCLR0 = 1;
      return(MmcDmaError);
    }

    DMACINTTCCLEAR_bit.INTTCCLEAR0 = 1;

    MCIDATACTRL = 0;
    MCI_BUS_DLY();

    // data timeout
    if(MCISTATUS_bit.DATATIMEOUT)
    {
      MCICLEAR = 1UL << 3;
      return(MmcNoResponse);
    }
    // Start bit not detected on all data signals in wide bus mode.
    if(MCISTATUS_bit.STARTBITERR)
    {
      MCICLEAR = 1UL << 9;
      return(MmcCardError);
    }
    // CRC error
    if(MCISTATUS_bit.DATACRCFAIL)
    {
      MCICLEAR = 1UL << 1;
      return(MmcCardError);
    }
    // tx underrun
    if(MCISTATUS_bit.TXUNDERRUN)
    {
      MCICLEAR = 1UL << 4;
      return(MmcCardError);
    }

    Length -= MmcDskCtrlBlk.BlockSize;
    Add += MmcDskCtrlBlk.BlockSize;
    pData += MmcDskCtrlBlk.BlockSize;

    // Clear data end and data block end
    MCICLEAR = (1UL << 8) | (1UL << 10);
    // data end
    if(!Length)
    {
      return(Status);
    }
    // loop write next block
  }
  return(Status);
}

/*************************************************************************
 * Function Name: MmcVerify
 * Parameters: const Int8U * pData, Int32U Add, Int32U Length
 *
 * Return: MmcState_t
 *
 * Description: Verify on a Mmc
 *
 *************************************************************************/
static inline
MmcState_t MmcVerify(const Int8U * pData, Int32U Add, Int32U Length)
{
#pragma segment="USB_DMA_RAM"
#pragma location="USB_DMA_RAM"
__no_init static Int8U TempBuffer[2048];  // maximum block length is 2048
MmcState_t Status = MmcOk;

  while(Length)
  {
    Status = MmcRead(TempBuffer,Add,MmcDskCtrlBlk.BlockSize);
    if(Status != MmcOk)
    {
      break;
    }
    for(Int32U i = 0; i < MmcDskCtrlBlk.BlockSize; ++i)
    {
      if(TempBuffer[i] != *pData++)
      {
        return(MmcMiscompare);
      }
    }
    Length -= MmcDskCtrlBlk.BlockSize;
    Add += MmcDskCtrlBlk.BlockSize;
  }
  return(Status);
}

/*************************************************************************
 * Function Name: MmcGetLastError
 * Parameters: none
 *
 * Return: Int32U
 *
 * Description: Return Last error
 *
 *************************************************************************/
Int32U MmcGetLastError(void)
{
  return(MmcLastError);
}

/*************************************************************************
 * Function Name: MmcStatusUpdate
 * Parameters: none
 *
 * Return: none
 *
 * Description: Update status of SD/MMC card
 *
 *************************************************************************/
void MmcStatusUpdate (void)
{
Int32U Data = CardRCA;
  // Update WP state
  MmcDskCtrlBlk.WriteProtect = MmcWriteProtect() |\
                               bMmcPermWriteProtect;
  if(!MmcPresent())
  {
    MmcDskCtrlBlk.DiskStatus = DiskNotPresent;
    MmcPowerDown();
    return;
  }

  if((MmcDskCtrlBlk.DiskStatus != DiskCommandPass))
  {
    switch (MmcInitMedia())
    {
    case MmcOk:
      MmcDskCtrlBlk.DiskStatus = DiskCommandPass;
      MmcDskCtrlBlk.MediaChanged = TRUE;
      break;
    case MmcCardError:
      MmcDskCtrlBlk.DiskStatus = DiskNotReady;
      break;
    default:
      MmcDskCtrlBlk.DiskStatus = DiskNotPresent;
      break;
    }
  }
  else if(MmcSendCmd(CMD13,&Data) != MmcOk)
  {
    MmcDskCtrlBlk.DiskStatus = DiskNotReady;
  }
  else if (!(Data & READY_FOR_DATA))
  {
    MmcDskCtrlBlk.DiskStatus = DiskNotReady;
  }
  else if ((Data & CURRENT_STATE) == CARD_TRAN)
  {
    MmcDskCtrlBlk.DiskStatus = DiskCommandPass;
  }
  else
  {
    MmcDskCtrlBlk.DiskStatus = DiskNotReady;
  }
}

/*************************************************************************
 * Function Name: MmcDiskInit
 * Parameters:  none
 *
 * Return: none
 *
 * Description: Init MMC/SD disk
 *
 *************************************************************************/
void MmcDiskInit (void)
{
  MmcDskCtrlBlk.BlockNumb =\
  MmcDskCtrlBlk.BlockSize =\
  MmcLastError           = 0;
  // Init SPI
  MmcInit();
  // Media Init
  switch (MmcInitMedia())
  {
  case MmcOk:
    MmcCsdImplemet();
    MmcDskCtrlBlk.DiskStatus = DiskCommandPass;
    MmcDskCtrlBlk.MediaChanged = TRUE;
    break;
  case MmcCardError:
    MmcDskCtrlBlk.DiskStatus = DiskNotReady;
    break;
  default:
    MmcDskCtrlBlk.DiskStatus = DiskNotPresent;
    break;
  }
}

#ifdef MMC_DISK_INFO
/*************************************************************************
 * Function Name: MmcDiskInfo
 * Parameters:  pInt8U pData, DiskInfoType_t DiskInfoType
 *
 * Return: Int32U
 *
 * Description: Return pointer to Info structure of the disk
 * (Inquiry or Format capacity)
 *
 *************************************************************************/
Int32U MmcDiskInfo (pInt8U pData, DiskInfoType_t DiskInfoType)
{
pMmc3FormatCapResponse_t pFormatCapacity;
  switch (DiskInfoType)
  {
  case DiskInquiry:
    memcpy(pData,MmcDskInquiry,SizeOfInquiryDescMmcDsk);
    return(SizeOfInquiryDescMmcDsk);
  case DiskFormatCapacity:
    pFormatCapacity = (pMmc3FormatCapResponse_t)pData;
    memset(pFormatCapacity,0,sizeof(Mmc3FormatCapResponse_t));
    pFormatCapacity->CapacityListLength = sizeof(Mmc3FormatCapDescriptor_t);
    if (MmcDskCtrlBlk.DiskStatus != DiskCommandPass)
    {
      pFormatCapacity->MaximumDescriptor.DescriptorType    = FormattedMedia;
      pFormatCapacity->MaximumDescriptor.BlockLength[0]    = (MmcDskCtrlBlk.BlockSize >> 16) & 0xFF;
      pFormatCapacity->MaximumDescriptor.BlockLength[1]    = (MmcDskCtrlBlk.BlockSize >>  8) & 0xFF;
      pFormatCapacity->MaximumDescriptor.BlockLength[2]    = (MmcDskCtrlBlk.BlockSize      ) & 0xFF;
      pFormatCapacity->MaximumDescriptor.NumberofBlocks[0] = (MmcDskCtrlBlk.BlockNumb >> 24) & 0xFF;
      pFormatCapacity->MaximumDescriptor.NumberofBlocks[1] = (MmcDskCtrlBlk.BlockNumb >> 16) & 0xFF;
      pFormatCapacity->MaximumDescriptor.NumberofBlocks[2] = (MmcDskCtrlBlk.BlockNumb >>  8) & 0xFF;
      pFormatCapacity->MaximumDescriptor.NumberofBlocks[3] = (MmcDskCtrlBlk.BlockNumb      ) & 0xFF;
    }
    else
    {
      pFormatCapacity->MaximumDescriptor.DescriptorType    = NoMediaPresent;
      pFormatCapacity->MaximumDescriptor.BlockLength[0]    = (2048       >> 16) & 0xFF;
      pFormatCapacity->MaximumDescriptor.BlockLength[1]    = (2048       >>  8) & 0xFF;
      pFormatCapacity->MaximumDescriptor.BlockLength[2]    = (2048            ) & 0xFF;
      pFormatCapacity->MaximumDescriptor.NumberofBlocks[0] = (0xFFFFFFFF >> 24) & 0xFF;
      pFormatCapacity->MaximumDescriptor.NumberofBlocks[1] = (0xFFFFFFFF >> 16) & 0xFF;
      pFormatCapacity->MaximumDescriptor.NumberofBlocks[2] = (0xFFFFFFFF >>  8) & 0xFF;
      pFormatCapacity->MaximumDescriptor.NumberofBlocks[3] = (0xFFFFFFFF      ) & 0xFF;
    }
    return(sizeof(Mmc3FormatCapResponse_t));
  }
  return(0);
}
#endif // MMC_DISK_INFO

/*************************************************************************
 * Function Name: MmcGetDiskCtrlBkl
 * Parameters:  none
 *
 * Return: pDiskCtrlBlk_t
 *
 * Description: Return pointer to control block structure of the disk
 *
 *************************************************************************/
pDiskCtrlBlk_t MmcGetDiskCtrlBkl (void)
{
  return(&MmcDskCtrlBlk);
}

/*************************************************************************
 * Function Name: MmcDiskIO
 * Parameters: pInt8U pData,Int32U BlockStart,
 *             Int32U BlockNum, DiskIoRequest_t IoRequest
 *
 * Return: DiskStatusCode_t
 *
 * Description: MMC/SD disk I/O
 *
 *************************************************************************/
DiskStatusCode_t MmcDiskIO (pInt8U pData,Int32U BlockStart,
                             Int32U BlockNum, DiskIoRequest_t IoRequest)
{
  if((pData == NULL) || (BlockStart+BlockNum > MmcDskCtrlBlk.BlockNumb))
  {
    return(DiskParametersError);
  }
  if (MmcDskCtrlBlk.DiskStatus != DiskCommandPass)
  {
    return(MmcDskCtrlBlk.DiskStatus);
  }
  switch (IoRequest)
  {
  case DiskWrite:
    if(MmcDskCtrlBlk.WriteProtect)
    {
      return(DiskParametersError);
    }
    switch (MmcWrite(pData,BlockStart*MmcDskCtrlBlk.BlockSize,BlockNum*MmcDskCtrlBlk.BlockSize))
    {
    case MmcOk:
      break;
    case MmcCardError:
      MmcDskCtrlBlk.DiskStatus = DiskNotReady;
      break;
    default:
      MmcDskCtrlBlk.DiskStatus = DiskNotPresent;
      break;
    }
    break;
  case DiskRead:
    switch (MmcRead(pData,BlockStart*MmcDskCtrlBlk.BlockSize,BlockNum*MmcDskCtrlBlk.BlockSize))
    {
    case MmcOk:
      break;
    case MmcCardError:
      MmcDskCtrlBlk.DiskStatus = DiskNotReady;
      break;
    default:
      MmcDskCtrlBlk.DiskStatus = DiskNotPresent;
      break;
    }
    break;
  case DiskVerify:
    switch (MmcVerify(pData,BlockStart*MmcDskCtrlBlk.BlockSize,BlockNum*MmcDskCtrlBlk.BlockSize))
    {
    case MmcOk:
      break;
    case MmcMiscompare:
      return(DiskMiscompareError);
    case MmcCardError:
      MmcDskCtrlBlk.DiskStatus = DiskNotReady;
      break;
    default:
      MmcDskCtrlBlk.DiskStatus = DiskNotPresent;
      break;
    }
    break;
  default:
    return(DiskParametersError);
  }
  return(MmcDskCtrlBlk.DiskStatus);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -