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

📄 halayer.c

📁 The high portable FAT filesystem library for embedded system.
💻 C
字号:
/**
 *	HALayer.c:	implementation of the HALayer.
 *	class HALayer:	defines the hardware specific portions
 *					of the MMC/SD card FAT library.  This file
 *					needs to be adapted for the specific microcontroller
 *					of choice
 *
 *	Author:	Ivan Sham
 *	Date: June 26, 2004
 *	Version: 2.0
 *	Note: Developed for William Hue and Pete Rizun
 *
 *****************************************************************
 *  Change Log
 *----------------------------------------------------------------
 *  Date    |   Author          | Reason for change
 *----------------------------------------------------------------
 * Aug31/04     William Hue       Removed convertCharToLong().
 *                                Changed char types to
 *                                unsigned char.
 *
 * Jul18/04     Alex Jiang        Added void parameter to
 *                                functions with no parameters.
 *                                Made delay a static function.
 *
 * Jan03/05     William Hue       Clean-up for
 *                                Circuit Cellar article.
 **/

#include "HALayer.h"

extern unsigned long sectorZero;

static void delay(uint16 d) 
{
	uint16 i;

	for (i = 0; i < d; i++) 
	{
        nop();
        nop();
		nop();
		nop();
	}
}

/**
 *	case insensitive compare of the 2 inputs
 *	returns true if and only if c1 = c2 or if
 *	c1 and c2 are the same character with different
 *	capitialization
 *
 *	@param	c1			input 1
 *	@param	c2			input 2
 **/
boolean charEquals(const char c1, const char c2)
{
	if((((c1 >= 'A')&&(c1 <= 'Z'))||((c1 >= 'a')&&(c1 <= 'z')))&&
		(((c2 >= 'A')&&(c2 <= 'Z'))||((c2 >= 'a')&&(c2 <= 'z'))))
	{
		if((c1 | 0x20) == (c2 | 0x20))
		{
			return TRUE;
		}
	}
	else
	{
		if(c1 == c2)
		{
			return TRUE;
		}
	}
	return FALSE;
}

/**
 *	Hardware Abstraction Layer initialization
 **/
void HALayerInit(void)
{
	MEM_PORT_OUT = 0;					// initialize all bits in P4 to be zero
	MEM_PORT_DIR = MEM_PORT_DIR_SET;
    MEM_PORT_SEL = 0;

	// Set the signals to the right initial state:
    MEM_PORT_OUT |= CS | SDI;

    // Switch the signals to the SPI:
	MEM_PORT_SEL = MEM_PORT_SEL_INIT;

	U1CTL = CHAR + SYNC + MM + SWRST;
	U1TCTL = CKPH + SSEL1 + SSEL0 + STC;
	U1BR0 = 2;							// 2 is the minimum divisor
	U1BR1 = 0;
	U1MCTL = 0;
	ME2 |= USPIE1;
	U1CTL &= ~SWRST;
}


/**
 *	checks if there is a memory card in the slot
 *	pulls 
 *
 *	@return	FALSE		card not detected
 *	@return TRUE		car detected
 **/
boolean detectCard(void)
{
	MEM_PORT_DIR &= ~CS;
	delay(18);
	if((MEM_PORT_IN & CS) == 0)	
	{
		MEM_PORT_DIR |= CS;
		return FALSE;
	}
	MEM_PORT_DIR |= CS;	
	return TRUE;
}

/**
 *	sends a byte on the SPI to the memory card
 *
 *	@param	inBuf		byte to be sent
 **/
void spi_put(unsigned char inBuf)
{
	U1TXBUF = inBuf;
	while((U1TCTL & TXEPT) == 0)
    {
        nop();	
    }
	U1TCTL &= ~TXEPT;
}

/**
 *	reads a byte from the SPI to the memory card
 *
 *	@return	U1RXBUF		byte read
 **/
unsigned char spi_get(void)
{	
	U1TXBUF = 0xFF;
	while((U1TCTL & TXEPT) == 0)
    {
        nop();	
    }
	U1TCTL &= ~TXEPT;
	return U1RXBUF;
}

/**
 *	sends the command to the the memory card with the 4 arguments and the CRC
 *
 *	@param command		the command
 *	@param argX			the arguments
 *	@param CRC			cyclic redundancy check
 **/
void sendCommand(unsigned char command, unsigned char argA,
                 unsigned char argB, unsigned char argC,
                 unsigned char argD, unsigned char CRC)
{	
	spi_put(command);
	spi_put(argA);
	spi_put(argB);
	spi_put(argC);
	spi_put(argD);
	spi_put(CRC);
}

/**
 *	waits for the memory card to response
 *
 *	@param expRes		expected response
 *
 *	@return TRUE		card responded within time limit
 *	@return FALSE		card did not response
 **/
boolean cardResponse(unsigned char expRes)
{
	unsigned char actRes;
	unsigned int count = 256;
	actRes = 0xFF;
	while ((actRes != expRes) && (count > 0))
	{
		actRes = spi_get();		
		count--;
	}
	if (count == 0)
		return FALSE; 
	return TRUE;
}

/**
 *	initializes the memory card by brign it out of idle state and 
 *	sets it up to use SPI mode
 *
 *	@return TRUE		card successfully initialized
 *	@return FALSE		card not initialized
 **/
boolean memCardInit(void)
{
	unsigned int count;
	MEM_PORT_OUT |= CS;	
	for (count = 0;count < 10; count++)
    {
		spi_put(0xFF);
    }
	MEM_PORT_OUT &= ~CS;
	sendCommand(CMD0,0,0,0,0,0x95);	// initializes the MMC
	if(cardResponse(0x01))
	{				
		count = 255;
		do
		{
			sendCommand(CMD1,0,0,0,0,0xFF);	// brings card out of idle state
			count--;
		} while ((!cardResponse(0x00)) && (count > 0));
		MEM_PORT_OUT |= CS;
		spi_put(0xFF);	
		if(count == 0)
			return FALSE;
	}
	else
	{
		MEM_PORT_OUT |= CS;
		return FALSE;		
	}
	return TRUE;
}

/**
 *	Initialize the block length in the memory card to be 512 bytes
 *	
 *	return TRUE			block length sucessfully set
 *	return FALSE		block length not sucessfully set
 **/
boolean setBLockLength(void)
{
	MEM_PORT_OUT &= ~CS;
	sendCommand(CMD16,0,0,2,0,0xFF);
	if(cardResponse(0x00))
	{
		spi_put(0xFF);
		MEM_PORT_OUT |= CS;
		return TRUE;
	}
	spi_put(0xFF);
	MEM_PORT_OUT |= CS;
	return FALSE;
}

/**
 *	locates the offset of the partition table from the absolute zero sector
 *
 *	return ...			the offset of the partition table
 **/
unsigned long getPartitionOffset(void)
{
	unsigned int count = 0;
	unsigned long offset = 0;
	unsigned char charBuf;
	MEM_PORT_OUT &= ~CS;
	sendCommand(CMD17,0,0,0,0,0xFF);
	if(cardResponse(0x00))
	{
		if(cardResponse(0xFE))
		{
			for(count = 0; count < 454; count++)
				spi_get();
			charBuf = spi_get();
			offset = charBuf;
			charBuf = spi_get();
			offset |= (unsigned long int)charBuf << 8;
			charBuf = spi_get();
			offset |= (unsigned long int)charBuf << 16;
			charBuf = spi_get();
			offset += (unsigned long int)charBuf << 24;
			for(count = 458; count < SECTOR_SIZE; count++)
				spi_get();
			spi_get();
			spi_get();
		}
	}
	MEM_PORT_OUT |= CS;
	spi_get();
	return offset;
}

/**
 *	checks to see if previous write operation is sucessful
 *	
 *	@return TRUE		if data is successfully written to disk
 *	@return FALSE		if data is not successfully written to disk
 **/
boolean checkWriteState(void)
{
	unsigned int count = 0;
	char inRes;
	while(count <= 64)
	{
		inRes = spi_get();
		if((inRes & 0x1F) == 0x05)
			break;
		else if((inRes & 0x1F) == 0x0B)
			return FALSE;
		else if((inRes & 0x1F) == 0x0D)
			return FALSE;
		count++;
	}
	count = 0;
	while((count < 64) && (spi_get() == 0x00));
	if(count < 64)
		return TRUE;
	else
		return FALSE;
}

/**
 *	read content of the sector indicated by the input and place it in the buffer
 *
 *	@param	sector		sector to be read
 *	@param	*buf		pointer to the buffer
 *
 *	@return	...			number of bytes read
 **/
unsigned int readSector(unsigned long sector, unsigned char *buf)
{
    unsigned int count = 0;
	sector += sectorZero;
	sector *= 2;	
	MEM_PORT_OUT &= ~CS;
	sendCommand(CMD17,(sector>>16)&0xFF,(sector>>8)&0xFF,sector&0xFF,0,0xFF);
	if(cardResponse(0x00))
	{
		if(cardResponse(0xFE))
		{
			for(count = 0; count < SECTOR_SIZE; count++)
			{
				buf[count] = spi_get();
			}
			spi_get();
			spi_get();
		}
	}
	MEM_PORT_OUT |= CS;
	spi_get();
	return count;
}

/**
 *	read partial content of the sector indicated by the input and place it in the buffer
 *
 *	@param	sector		sector to be read
 *	@paran	*buf		pointer to the buffer
 *	@param	bytesOffset	starting point in the sector for reading
 *	@param	bytesToRead	number of bytes to read
 *
 *	@return	...			number of bytes read
 **/
unsigned int readPartialSector(unsigned long sector,
                               unsigned int byteOffset,
                               unsigned int bytesToRead,
                               unsigned char *buf)
{
    int count = 0;
	int countRead = 0;
	int leftover = SECTOR_SIZE - byteOffset - bytesToRead;
	sector += sectorZero;
	sector *= 2;	
	MEM_PORT_OUT &= ~CS;
	sendCommand(CMD17,(sector>>16)&0xFF,(sector>>8)&0xFF,sector&0xFF,0,0xFF);
	if(cardResponse(0x00))
	{
		if(cardResponse(0xFE))
		{
			for(count = 0; count < byteOffset; count++)
				spi_get();
			for(countRead = 0; countRead < bytesToRead; countRead++)
			{
				buf[countRead] = spi_get();
			}
			for(count = 0; count < leftover; count++)
				spi_get();
			spi_put(0xFF);
			spi_put(0xFF);
		}
	}
	MEM_PORT_OUT |= CS;
	spi_get();
	return countRead;
}

/**
 *	read partial content at the end of the sector1 indicated by the input and
 *	the begging of sector 2 and place it in the buffer
 *
 *	@param	sector1		first sector to be read
 *	@param	sector2		second sector to be read
 *	@paran	*buf		pointer to the buffer
 *	@param	bytesOffset	starting point in the sector for reading
 *	@param	bytesToRead	number of bytes to read
 *
 *	@return	...			number of bytes read
 **/
unsigned int readPartialMultiSector(unsigned long sector1,
                                    unsigned long sector2,
                                    unsigned int byteOffset,
                                    unsigned int bytesToRead,
                                    unsigned char *buf)
{
	int count = 0;
	int countRead = 0;
	sector1 += sectorZero;
	sector1 *= 2;	
	sector2 += sectorZero;
	sector2 *= 2;	
	MEM_PORT_OUT &= ~CS;
	sendCommand(CMD17,(sector1>>16)&0xFF,(sector1>>8)&0xFF,sector1&0xFF,0,0xFF);
	if(cardResponse(0x00))
	{
		if(cardResponse(0xFE))
		{
			for(count = 0; count < byteOffset; count++)
				spi_get();
			for(count = byteOffset; count < SECTOR_SIZE; count++, countRead++)
			{
				buf[countRead] = spi_get();
			}
			spi_put(0xFF);
			spi_put(0xFF);
		}
		else
		{
			return 0;
		}
	}
	else
	{
		return 0;
	}
	MEM_PORT_OUT |= CS;
	spi_get();
	spi_get();
	MEM_PORT_OUT &= ~CS;
	sendCommand(CMD17,(sector2>>16)&0xFF,(sector2>>8)&0xFF,sector2&0xFF,0,0xFF);
	if(cardResponse(0x00))
	{
		if(cardResponse(0xFE))
		{			
			for(count = 0; countRead < bytesToRead; count++, countRead++)
			{
				buf[countRead] = spi_get();
			}
			for(count = count; count < SECTOR_SIZE; count++)
				spi_get();
			spi_put(0xFF);
			spi_put(0xFF);
		}
		else
		{
			return 0;
		}
	}
	else
	{
		return 0;
	}
	MEM_PORT_OUT |= CS;
	spi_get();
    return countRead;
}

/**
 *	writes content of the buffer to the sector indicated by the input
 *
 *	@param	sector		sector to be written
 *	@param	*buf		pointer to the buffer
 *
 *	@return	...			number of bytes written
 **/
unsigned int writeSector(unsigned long sector, unsigned char *buf)
{
    unsigned int count = 0;
	sector += sectorZero;
	sector *= 2;	
	MEM_PORT_OUT &= ~CS;
	sendCommand(CMD24,(sector>>16)&0xFF,(sector>>8)&0xFF,sector&0xFF,0,0xFF);
	if(cardResponse(0x00))
	{
		spi_put(0xFF);
		spi_put(0xFE);
		for(count = 0; count < SECTOR_SIZE; count++)
		{
			spi_put(buf[count]);
		}
		spi_get();
		spi_get();
		checkWriteState();
	}
	MEM_PORT_OUT |= CS;
	spi_get();
	return count;
}

/**
 *	write the content of the buffer indicated by the input to the MMC/SD card location
 *	indicated by the input sector.
 *
 *	@param	sector		sector to be written to
 *	@paran	*buf		pointer to the buffer
 *	@param	bytesOffset	starting point in the sector for writing
 *	@param	bytesToRead	number of bytes to write
 *
 *	@return	...			number of bytes written
 **/
unsigned int writePartialSector(unsigned long sector,
                                unsigned int byteOffset,
                                unsigned int bytesToWrite,
                                unsigned char *buf)
{
    int count = 0;
	int countWrote = 0;	
	unsigned char readBuf[SECTOR_SIZE];
	readSector(sector,readBuf);
	sector += sectorZero;
	sector *= 2;	
	MEM_PORT_OUT &= ~CS;
	sendCommand(CMD24,(sector>>16)&0xFF,(sector>>8)&0xFF,sector&0xFF,0,0xFF);
	if(cardResponse(0x00))
	{
		spi_put(0xFF);
		spi_put(0xFE);
		for(count = 0; count < byteOffset; count++)		
			spi_put(readBuf[count]);
		for(countWrote = 0; countWrote < bytesToWrite; countWrote++, count++)
		{
			spi_put(buf[countWrote]);
		}
		for(count = count; count < SECTOR_SIZE; count++)
			spi_put(readBuf[count]);
		spi_get();
		spi_get();
		checkWriteState();
	}
	MEM_PORT_OUT |= CS;
	spi_get();
	return countWrote;
}

/**
 *	write the content of the buffer to the end of the sector1
 *	and the begging of sector 2
 *
 *	@param	sector1			first sector to be written to
 *	@param	sector2			second sector to be written to
 *	@paran	*buf			pointer to the buffer
 *	@param	bytesOffset		starting point in the sector for reading
 *	@param	bytesToWrite	number of bytes to write
 *
 *	@return	...				number of bytes written
 **/
unsigned int writePartialMultiSector(unsigned long sector1,
                                     unsigned long sector2,
                                     unsigned int byteOffset,
                                     unsigned int bytesToWrite,
                                     unsigned char *buf)
{
    unsigned int count = 0;
	unsigned int countWrote = 0;	
	unsigned int writeSector2 = bytesToWrite - SECTOR_SIZE + byteOffset;
	unsigned char readBuf[SECTOR_SIZE];
	readSector(sector1,readBuf);
	sector1 += sectorZero;
	sector1 *= 2;	
	MEM_PORT_OUT &= ~CS;
	sendCommand(CMD24,(sector1>>16)&0xFF,(sector1>>8)&0xFF,sector1&0xFF,0,0xFF);
	if(cardResponse(0x00))
	{
		spi_put(0xFF);
		spi_put(0xFE);
		for(count = 0; count < byteOffset; count++)		
			spi_put(readBuf[count]);
		for(count = byteOffset; count < SECTOR_SIZE; countWrote++, count++)
		{
			spi_put(buf[countWrote]);
		}
		spi_get();
		spi_get();
		checkWriteState();
	}
	MEM_PORT_OUT |= CS;
	spi_get();
	readSector(sector2,readBuf);
	sector2 += sectorZero;
	sector2 *= 2;
	MEM_PORT_OUT &= ~CS;
	sendCommand(CMD24,(sector2>>16)&0xFF,(sector2>>8)&0xFF,sector2&0xFF,0,0xFF);
	if(cardResponse(0x00))
	{
		spi_put(0xFF);
		spi_put(0xFE);
		for(count = 0; count < writeSector2; countWrote++, count++)
		{
			spi_put(buf[countWrote]);
		}
		for(count = writeSector2; count < SECTOR_SIZE; count++)
			spi_put(readBuf[count]);		
		spi_get();
		spi_get();
		checkWriteState();
	}
	MEM_PORT_OUT |= CS;
	spi_get();
	spi_get();
	return countWrote;
}

⌨️ 快捷键说明

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