📄 mmc_x_hw_imx21ads.c
字号:
/*
**********************************************************************
* Micrium, Inc.
* 949 Crestview Circle
* Weston, FL 33327-1848
*
* uC/FS
*
* (c) Copyright 2001 - 2003, Micrium, Inc.
* All rights reserved.
*
***********************************************************************
----------------------------------------------------------------------
File : mmc_x_hw.c
Purpose : Sample MMC hardware layer for i.MX21ADS
Author : ES
---------------------------END-OF-HEADER------------------------------
*/
/*********************************************************************
*
* #include Section
*
**********************************************************************
*/
#include "fs_api.h"
#include "fs_conf.h"
#if FS_USE_MMC_DRIVER
#include "mmc.h"
#include "mmc_x_hw.h"
#include <includes.h>
/*********************************************************************
*
* #define constants
*
**********************************************************************
*/
#define MMC_INIT_FREQUENCY 400 /* MMC/SD frequency = 400 KHZ on startup */
#define FS__MMC_DEFAULTSUPPLYVOLTAGE 3300 /* MMC/SD Operating voltage in millivolts */
/*********************************************************************
*
* Constant Checking
*
**********************************************************************
*/
#if ((FS_USE_MMC_DRIVER == 1) && (OSView_Uses_Own_Timer != 1))
#error "The MMC/SD hardware driver shares a general purpose timer with uC/OS-View" \n
Set BSP_TickMode to 0 and OSView_Uses_Own_Timer to 1 in bsp.h"
#endif
/*********************************************************************
*
* #define Macros
*
* Notes : The Following macros are used when bit-banging the MMC/SD
* : card IO lines via software. When HW_USE_SPI is defined as 0
**********************************************************************
*/
#define SPI_SET_CLK() PTE_DR |= (1 << 23) /* Raise SCLK */
#define SPI_CLR_CLK() PTE_DR &= ~(1 << 23) /* Lower SCLK */
#define SPI_SET_DATAOUT() PTE_DR |= (1 << 22) /* Raise MISO */
#define SPI_CLR_DATAOUT() PTE_DR &= ~(1 << 22) /* Lower MISO */
#define SPI_SET_CS() PTE_DR |= (1 << 21) /* Raise CardSelect */
#define SPI_CLR_CS() PTE_DR &= ~(1 << 21) /* Lower CardSelect */
#define SPI_DATAIN() (PTE_SSR & (1 << 18)) /* 0 if input bit is clr else > 0 if set */
/*********************************************************************
*
* Local Globals
*
**********************************************************************
*/
static FS_U32 SPI_DlyNbrCnts;
/*********************************************************************
*
* Local functions
*
**********************************************************************
*/
static void SPI_DELAY(void);
/*********************************************************************
*
* _Init
*
* Description:
* FS low level Generap Purpose IO Port Init for SPI software emulation
*
* Parameters:
* void
*
* Return value:
* void
*/
void _Init(void) {
/* Use GPIO and bit bang */
PCCR0 |= GPIO_EN; /* Enable GPIO module clock */
PTE_GIUS |= 0x00FC0000; /* Port E pins / CSPI3 not GPIO */
PTE_DDIR |= 0x00E00000; /* [23:21] = output, 19 = input */
PTE_ICONFA2 &= ~0x000000C0; /* Pin 19, GPIO_In -> A_Out */
PTE_0CR2 |= 0x0000FC00; /* Data Reg. -> Pins [23:21] */
}
/*********************************************************************
*
* FS_MMC_HW_X_BusyLedOff
*
* Description:
* FS low level function. Switches the busy LED off.
*
* Parameters:
* Unit - Unit number
*
* Return value:
* void
*/
void FS_MMC_HW_X_BusyLedOff (FS_U8 Unit) {
LED_Off(2);
}
/*********************************************************************
*
* FS_MMC_HW_X_BusyLedOn
*
* Description:
* FS low level function. Switches the busy LED off.
*
* Parameters:
* Unit - Unit number
*
* Return value:
* void
*/
void FS_MMC_HW_X_BusyLedOn (FS_U8 Unit) {
LED_On(2);
}
/*********************************************************************
*
* FS_MMC_HW_X_EnableCS
*
* Description:
* FS low level function. Sets the card slot active using the
* chip select (CS) line.
*
* Parameters:
* Unit - Unit number
*
* Return value:
* void
*/
void FS_MMC_HW_X_EnableCS (FS_U8 Unit) {
SPI_CLR_CS();
}
/*********************************************************************
*
* FS_MMC_HW_X_EnableCS
*
* Description:
* FS low level function. Sets the card slot inactive using the
* chip select (CS) line.
*
* Parameters:
* Unit - Unit number
*
* Return value:
* void
*/
void FS_MMC_HW_X_DisableCS(FS_U8 Unit) {
SPI_SET_CS();
}
/*********************************************************************
*
* FS_MMC_HW_X_IsWriteProtected
*
* Description:
* FS low level function. Returns the state of the physical write
* protection of the SD cards.
*
* Parameters:
* Unit - Unit number
*
* Return value:
* 1 - the card is write protected
* ==0 - the card is not write protected
*/
FS_U8 FS_MMC_HW_X_IsWriteProtected(FS_U8 Unit) {
/* If the card slot has no write switch detector, return 0 */
return 0;
}
/*********************************************************************
*
* FS_MMC_HW_X_SetMaxSpeed
*
* Description:
* FS low level function. Sets the SPI interface to one of three
* possible frequencies. Either the MMC/SD recommended startup
* frequency, which is 400 KHZ, or the specified MaxFrequency
* which is read from the MMC/SD card's CSD, or lastly, the
* maximum possible speed based on the minimum delay that can
* be created with the general purpose timer (GPT). If the
* specified frequency, MaxFreq, is too fast and can not be
* set as a result of the GPT not being fast enough, then the
* actual frequency based on the speed of the GPT under its fastest
* operation is returned.
*
* Note: This function is called twice during startup. Once to
* initialize the port with a frequency of 400 KHZ and
* read the cards CSD information, then a second time
* with the MaxFreq = to the maximum medium frequency
* read from the cards CSD.
*
* Parameters:
* Unit - Unit number
* MaxFreq - SPI clock frequency in kHz
*
* Return value:
* max. frequency - the maximum frequency set in kHz
* ==0 - the frequency could not be set
*/
FS_U16 FS_MMC_HW_X_SetMaxSpeed(FS_U8 Unit, FS_U16 MaxFreq) {
FS_U16 actual_freq;
if (MaxFreq == MMC_INIT_FREQUENCY) { /* If we are setting the initialization frequency */
_Init(); /* Initialize the IO pins for bit banging the SPI */
return MMC_INIT_FREQUENCY; /* Return the Init frequency, 400 KHZ. */
} else { /* Attempt to set a frequency other than the initialization frequency */
SPI_DlyNbrCnts = ((GPT2CLK / (MaxFreq * 1000)) / 2); /* Calculate the number of SPI_DELAY() counts necessary */
if (SPI_DlyNbrCnts == 0) { /* If the delay counts is zero, then the delay is faster */
actual_freq = ((MCLK / PERDIV1) / 1000); /* then the timer can run. So return the maximum frequency */
return actual_freq; /* possible bassed on the speed of the GTP input clock */
} else {
return MaxFreq; /* If the specified MaxFrequency can be set, then return that value */
}
}
}
/*********************************************************************
*
* FS_MMC_HW_X_SetVoltage
*
* Description:
* FS low level function. Be sure that your card slot si within the given
* voltage range. Return 1 if your slot can support the required voltage,
* and if not, return 0;
*
* Parameters:
* Unit - Unit number
* MaxFreq - SPI clock frequency in kHz
*
* Return value:
* 1 - the card slot supports the voltage range
* ==0 - the card slot does not support the voltage range
*/
FS_U8 FS_MMC_HW_X_SetVoltage(FS_U8 Unit, FS_U16 Vmin, FS_U16 Vmax) {
FS_U8 r;
/* voltage range check */
if ((Vmin <= FS__MMC_DEFAULTSUPPLYVOLTAGE) && (Vmax >= FS__MMC_DEFAULTSUPPLYVOLTAGE)) {
r = 1;
} else {
r = 0;
}
return r;
}
/*********************************************************************
*
* FS_MMC_HW_X_IsPresent
*
* Description:
* Returns the state of the media. If you do not know the state, return
* FS_MEDIA_STATEUNKNOWN and the higher layer will try to figure out if
* a media is present.
*
* Parameters:
* Unit - Unit number
*
* Return value:
* FS_MEDIA_STATEUNKNOWN - the state of the media is unkown
* FS_MEDIA_ISNOTPRESENT - no card is present
* FS_MEDIA_ISPRESENT - a card is present
*/
FS_U8 FS_MMC_HW_X_IsPresent(FS_U8 Unit) {
return FS_MEDIA_STATEUNKNOWN;
}
/*********************************************************************
*
* FS_MMC_HW_X_Read
*
* Description:
* FS low level function. Reads a specified number of bytes from MMC
* card to buffer.
*
* Parameters:
* Unit - Unit number
* pData - Pointer to a data buffer
* NumBytes - Number of bytes
*
* Return value:
* void
*/
void FS_MMC_HW_X_Read (FS_U8 Unit, FS_U8 * pData, int NumBytes) {
FS_U8 c;
FS_U8 bpos;
do {
c = 0;
bpos = 8; /* get 8 bits */
do { SPI_CLR_CLK();
c <<= 1;
if (SPI_DATAIN() > 0) {
c |= 1;
}
SPI_SET_CLK();
} while (--bpos);
*pData++ = c;
} while (--NumBytes);
}
/*********************************************************************
*
* FS_MMC_HW_X_Write
*
* Description:
* FS low level function. Writes a specified number of bytes from
* data buffer to the MMC/SD card.
*
* Parameters:
* Unit - Unit number
* pData - Pointer to a data buffer
* NumBytes - Number of bytes
*
* Return value:
* void
*/
void FS_MMC_HW_X_Write(FS_U8 Unit, const unsigned char * pData, int NumBytes) {
int i;
FS_U8 mask;
FS_U8 data;
for (i = 0; i < NumBytes; i++) {
data = pData[i];
mask = 0x80;
while (mask > 0) {
if ((data & mask) > 0) {
SPI_SET_DATAOUT();
} else {
SPI_CLR_DATAOUT();
}
SPI_CLR_CLK();
SPI_DELAY();
SPI_SET_CLK();
SPI_DELAY();
mask >>= 1;
}
}
SPI_SET_DATAOUT(); /* default state of data line is high */
}
/*********************************************************************
*
* SPI_DELAY
*
* Description:
* FS low level function which regulates the rate of the MMCCLK
* pin toggle for software emulation, aka bit banging of the
* MMC/SD card slot.
*
* Parameters:
* void
*
* Return value:
* void
*
* Notes : 1) Shares a generap purpose timer with uC/OS-View!
*/
static void SPI_DELAY(void) {
FS_U32 tmr_start_val;
tmr_start_val = GPT2_TCN1;
while ((GPT2_TCN1 - tmr_start_val) < SPI_DlyNbrCnts) {
;
}
}
#endif /* FS_USE_MMC_DRIVER */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -