📄 halayer.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 + -