📄 mmc_datalogger.c
字号:
while(!(*pchar&0x80)); // Check the card busy bit of the OCR;
card_status.i = MMC_Command_Exec(SEND_STATUS,EMPTY,EMPTY);
// Get the Card Specific Data (CSD)
// register to determine the size of the
// MMC;
card_status.i = MMC_Command_Exec(SEND_CSD,EMPTY,pchar);
pchar += 9; // Size indicator is in the 9th byte of
// CSD register;
// Extract size indicator bits;
size = (unsigned int)((((*pchar) & 0x03) << 1) |
(((*(pchar+1)) & 0x80) >> 7));
switch(size) // Assign PHYSICAL_SIZE variable to
{ // appropriate size constant;
case 1: PHYSICAL_SIZE = PS_8MB; break;
case 2: PHYSICAL_SIZE = PS_16MB; break;
case 3: PHYSICAL_SIZE = PS_32MB; break;
case 4: PHYSICAL_SIZE = PS_64MB; break;
case 5: PHYSICAL_SIZE = PS_128MB; break;
default: break;
}
// Determine the number of MMC sectors;
PHYSICAL_BLOCKS = PHYSICAL_SIZE / PHYSICAL_BLOCK_SIZE;
LOG_SIZE = PHYSICAL_SIZE - LOG_ADDR;
}
//-----------------------------------------------------------------------------
// MMC_FLASH_Read
//-----------------------------------------------------------------------------
//
// This function reads <length> bytes of FLASH from MMC address <address>, and
// stores them in external RAM at the location pointed to by <pchar>.
// There are two cases that must be considered when performing a read. If the
// requested data is located entirely in a single FLASH block, the function
// sets the read length appropriately and issues a read command. If requested
// data crosses a FLASH block boundary, the read operation is broken into two
// parts. The first part reads data from the starting address to the end of
// the starting block, and then reads from the start of the next block to the
// end of the requested data. Before each read, the read length must be set
// to the proper value.
unsigned char MMC_FLASH_Read (unsigned long address, unsigned char *pchar,
unsigned int length)
{
idata unsigned long flash_page_1; // Stores address of first FLASH page;
idata unsigned long flash_page_2; // Stores address of second FLASH page;
idata unsigned int card_status; // Stores MMC status after each MMC
// command;
if(length > 512) return 0; // Test for valid data length; Length
// must be less than 512 bytes;
// Find address of first FLASH block;
flash_page_1 = address & ~(PHYSICAL_BLOCK_SIZE-1);
// Find address of second FLASH block;
flash_page_2 = (address+length-1) & ~(PHYSICAL_BLOCK_SIZE-1);
if(flash_page_1 == flash_page_2) // Execute the following if data is
{ // located within one FLASH block;
// Set read length to requested data
// length;
card_status = MMC_Command_Exec(SET_BLOCKLEN,(unsigned long)length,
EMPTY);
// Issue read command;
card_status = MMC_Command_Exec(READ_SINGLE_BLOCK,address,pchar);
}
else // Execute the following if data crosses
{ // MMC block boundary;
// Set the read length to the length
// from the starting address to the
// end of the first FLASH page;
card_status = MMC_Command_Exec(SET_BLOCKLEN,
(unsigned long)(flash_page_2 - address),
EMPTY);
// Issue read command;
card_status = MMC_Command_Exec(READ_SINGLE_BLOCK,address,pchar);
// Set read length to the length from
// the start of the second FLASH page
// to the end of the data;
card_status = MMC_Command_Exec(SET_BLOCKLEN,
(unsigned long)length -
(flash_page_2 - address),
EMPTY);
// Issue second read command; Notice
// that the incoming data stored in
// external RAM must be offset from the
// original pointer value by the length
// of data stored during the first read
// operation;
card_status = MMC_Command_Exec(READ_SINGLE_BLOCK,flash_page_2,
pchar + (flash_page_2 - address));
}
}
//-----------------------------------------------------------------------------
// MMC_FLASH_Clear
//-----------------------------------------------------------------------------
//
// This function erases <length> bytes of flash starting at address <address>.
// The <scratch> pointer points to a 512 byte area of XRAM that can
// be used as temporary storage space. The flow of this function is similar
// to the FLASH_Read function in that there are two possible cases. If the
// space to be cleared is contained within one MMC block, the block can be
// stored locally and erased from the MMC. Then the desired area can be
// cleared in the local copy and the block can be written back to the MMC. If
// the desired clear area crosses a FLASH block boundary, the previous steps
// must be executed seperately for both blocks.
unsigned char MMC_FLASH_Clear (unsigned long address, unsigned char *scratch,
unsigned int length)
{
idata unsigned long flash_page_1; // Stores address of first FLASH page;
idata unsigned long flash_page_2; // Stores address of second FLASH page;
idata unsigned int card_status; // Stores MMC status after each MMC
// command;
idata unsigned int counter; // Counter for clearing bytes in local
// block copy;
unsigned char xdata *index; // Index into local block used for
// clearing desired data;
if(length > 512) return 0; // Test desired clear length; If
// length > 512, break out and return
// zero;
// Calculate first FLASH page address;
flash_page_1 = address & ~(PHYSICAL_BLOCK_SIZE-1);
// Calculate second FLASH page address;
flash_page_2 = (address+length-1) & ~(PHYSICAL_BLOCK_SIZE-1);
if(flash_page_1 == flash_page_2) // Clear space all in one FLASH block
{ // condition;
// Read first FLASH block;
card_status = MMC_Command_Exec(SET_BLOCKLEN,
(unsigned long)PHYSICAL_BLOCK_SIZE,
EMPTY);
card_status = MMC_Command_Exec(READ_SINGLE_BLOCK,flash_page_1,scratch);
// Set index to address of area to clear
// in local block;
index = (unsigned int)(address % PHYSICAL_BLOCK_SIZE) + scratch;
counter = 0;
while(counter<length) // Clear desired area in local block;
{
*index++ = 0x00;
counter++;
}
// Tag first FLASH page for erase;
card_status = MMC_Command_Exec(TAG_SECTOR_START,flash_page_1,EMPTY);
card_status = MMC_Command_Exec(TAG_SECTOR_END,flash_page_1,EMPTY);
// Erase first FLASH page;
card_status = MMC_Command_Exec(ERASE,EMPTY,EMPTY);
// Write local copy of block back out
// to MMC;
card_status = MMC_Command_Exec(WRITE_BLOCK,flash_page_1,scratch);
}
else // Clear space crosses FLASH block
{ // boundaries condition;
// Follow same procedure as for single
// block case above; Read first block
// clear data from start address to end
// of block; Erase block in FLASH;
// Write local copy back out;
card_status = MMC_Command_Exec(SET_BLOCKLEN,
(unsigned long)PHYSICAL_BLOCK_SIZE,
EMPTY);
card_status = MMC_Command_Exec(READ_SINGLE_BLOCK,flash_page_1,scratch);
index = (unsigned int)(address % PHYSICAL_BLOCK_SIZE) + scratch;
counter = (unsigned int)(flash_page_2 - address);
while(counter > 0)
{
*index++ = 0xFF;
counter--;
}
card_status = MMC_Command_Exec(TAG_SECTOR_END,flash_page_1,EMPTY);
card_status = MMC_Command_Exec(ERASE,EMPTY,EMPTY);
card_status = MMC_Command_Exec(WRITE_BLOCK,flash_page_1,scratch);
// Same process as above, but using
// second FLASH block; Area to be
// cleared extends from beginning of
// second FLASH block to end of desired
// clear area;
card_status = MMC_Command_Exec(READ_SINGLE_BLOCK,flash_page_2,scratch);
index = scratch;
counter = (unsigned int)(length - (flash_page_2 - address));
while(counter > 0)
{
*index++ = 0xFF;
counter--;
}
card_status = MMC_Command_Exec(TAG_SECTOR_END,flash_page_2,EMPTY);
card_status = MMC_Command_Exec(ERASE,EMPTY,EMPTY);
card_status = MMC_Command_Exec(WRITE_BLOCK,flash_page_2,scratch);
}
}
//-----------------------------------------------------------------------------
// MMC_FLASH_Write
//-----------------------------------------------------------------------------
//
// This function operates much like the MMC_FLASH_Clear and MMC_FLASH_Read
// functions. As with the others, if the desired write space crosses a FLASH
// block boundary, the operation must be broken into two pieces.
// MMC_FLASH_Write uses the MMC_FLASH_Clear function to clear the write space
// before issuing any writes. The desired write space is cleared using
// MMC_FLASH_Clear, then the data is read in, the previously cleared write
// space is modified, and the data is written back out.
//
// While it would be more efficient to avoid the MMC_FLASH_Clear and simply
// perform a read-modify-write operation, using MMC_FLASH_Clear helps make the
// process easier to understand.
unsigned char MMC_FLASH_Write (unsigned long address, unsigned char *scratch,
unsigned char *wdata, unsigned int length)
{
idata unsigned long flash_page_1; // First FLASH page address;
idata unsigned long flash_page_2; // Second FLASH page address;
idata unsigned int card_status; // Stores status returned from MMC;
idata unsigned int counter; // Byte counter used for writes to
// local copy of data block;
unsigned char xdata *index; // Pointer into local copy of data
// block, used during modification;
MMC_FLASH_Clear(address,scratch,length); // Clear desired write space;
if(length > 512) return 0; // Check for valid data length;
// Calculate first FLASH page address;
flash_page_1 = address & ~(PHYSICAL_BLOCK_SIZE-1);
// Calculate second FLASH page address;
flash_page_2 = (address+length-1) & ~(PHYSICAL_BLOCK_SIZE-1);
if(flash_page_1 == flash_page_2) // Handle single FLASH block condition;
{
// Set block length to default block
// size (512 bytes);
card_status = MMC_Command_Exec(SET_BLOCKLEN,
(unsigned long)PHYSICAL_BLOCK_SIZE,
EMPTY);
// Read data block;
card_status = MMC_Command_Exec(READ_SINGLE_BLOCK,flash_page_1,scratch);
index = (unsigned int)(address % PHYSICAL_BLOCK_SIZE) + scratch;
counter = 0;
while(counter<length) // Modify write space in local copy;
{
*index++ = *wdata++;
counter++;
}
// Write modified block back to MMC;
card_status = MMC_Command_Exec(WRITE_BLOCK,flash_page_1,scratch);
}
else // Handle multiple FLASH block
{ // condition;
// Set block length to default block
// size (512 bytes);
card_status = MMC_Command_Exec(SET_BLOCKLEN,
(unsigned long)PHYSICAL_BLOCK_SIZE,
EMPTY);
// Read first data block;
card_status = MMC_Command_Exec(READ_SINGLE_BLOCK,flash_page_1,scratch);
index = (unsigned int)(address % PHYSICAL_BLOCK_SIZE) + scratch;
counter = (unsigned int)(flash_page_2 - address);
while(counter > 0) // Modify data in local copy of first
{ // block;
*index++ = *wdata++;
counter--;
}
// Write local copy back to MMC;
card_status = MMC_Command_Exec(WRITE_BLOCK,flash_page_1,scratch);
// Read second data block;
card_status = MMC_Command_Exec(READ_SINGLE_BLOCK,flash_page_2,scratch);
index = scratch;
counter = (unsigned int)(length - (flash_page_2 - address));
while(counter > 0) // Modify data in local copy of second
{ // block;
*index++ = *wdata++;
counter--;
}
// Write local copy back to MMC;
card_status = MMC_Command_Exec(WRITE_BLOCK,flash_page_2,scratch);
}
}
//-----------------------------------------------------------------------------
// MMC_FLASH_MassErase
//-----------------------------------------------------------------------------
//
// This function erases <length> bytes of flash starting with the block
// indicated by <address1>. This function only handles sector-si
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -