📄 f34x_msd_mmc.c
字号:
//-----------------------------------------------------------------------------
// F34x_MSD_MMC.c
//-----------------------------------------------------------------------------
// Copyright 2006 Silicon Laboratories, Inc.
// http://www.silabs.com
//
// Program Description:
//
// MMC FLASH is used for storing the log entries. Each entry contains
// the temperature in hundredths of a degree C, the day, hour, minute, and
// second that the reading was taken. The LogUpdate function stores log
// entries in an external memory buffer and then writes that buffer out to the
// MMC when it is full. Communication with the MMC is performed through the
// MMC access functions. These functions provide transparent MMC access to
// the higher level functions (Logging functions). The MMC interface is broken
// into two pieces. The high level piece consists of the user callable MMC
// access functions (MMC_FLASH_Read, MMC_FLASH_Write, MMC_FLASH_Clear,
// MMC_FLASH_MassErase). These functions are called by the user to execute
// data operations on the MMC. They break down the data operations into MMC
// commands. The low level piece consists of a single command execution
// function (MMC_Command_Exec) which is called by the MMC data manipulation
// functions. This function is called every time a command must be sent to the
// MMC. It handles all of the required SPI traffic between the Silicon
// Laboratories device and the MMC.
//
//
// How To Test: See Readme.txt
//
//
// FID: 34X000043
// Target: C8051F34x
// Tool chain: Keil
// Command Line: See Readme.txt
// Project Name: F34x_USB_MSD
//
// Release 1.1
// -All changes by PKC
// -09 JUN 2006
// -Replaced SFR definitions file "c8051f320.h" with "c8051f340.h"
// -Corrected "SPIDAT" to "SPI0DAT" in function Write_Read_Spi_Byte
//
// Release 1.0
// -Initial Release
//
//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------
#include "F34x_MSD_Definitions.h"
#include "c8051f340.h" // SFR declarations
#include <stdio.h>
#include "F34x_MSD_USB_Main.h" // Has SYSCLK #define'd
#include "F34x_MSD_Physical_Settings.h"
#include "F34x_MSD_MMC.h"
#include <intrins.h>
// Constants that define available card sizes, 8MB through 128MB
#define PS_8MB 8388608L
#define PS_16MB 16777216L
#define PS_32MB 33554432L
#define PS_64MB 67108864L
#define PS_128MB 134217728L
#define ERROR_CODE 0xFFFF
#define BUFFER_SIZE 16
//#define NSSMD0 SLVSEL
// Erase group size = 16 MMC FLASH sectors
#define PHYSICAL_GROUP_SIZE (PHYSICAL_BLOCK_SIZE * 16)
// Command table value definitions
// Used in the MMC_Command_Exec function to
// decode and execute MMC command requests
#define EMPTY 0
#define YES 1
#define NO 0
#define CMD 0
#define RD 1
#define WR 2
#define R1 0
#define R1b 1
#define R2 2
#define R3 3
// Start and stop data tokens for single and multiple
// block MMC data operations
#define START_SBR 0xFE
#define START_MBR 0xFE
#define START_SBW 0xFE
#define START_MBW 0xFC
#define STOP_MBW 0xFD
// Mask for data response Token after an MMC write
#define DATA_RESP_MASK 0x11
// Mask for busy Token in R1b response
#define BUSY_BIT 0x80
// Command Table Index Constants:
// Definitions for each table entry in the command table.
// These allow the MMC_Command_Exec function to be called with a
// meaningful parameter rather than a number.
#define GO_IDLE_STATE 0
#define SEND_OP_COND 1
#define SEND_CSD 2
#define SEND_CID 3
#define STOP_TRANSMISSION 4
#define SEND_STATUS 5
#define SET_BLOCKLEN 6
#define READ_SINGLE_BLOCK 7
#define READ_MULTIPLE_BLOCK 8
#define WRITE_BLOCK 9
#define WRITE_MULTIPLE_BLOCK 10
#define PROGRAM_CSD 11
#define SET_WRITE_PROT 12
#define CLR_WRITE_PROT 13
#define SEND_WRITE_PROT 14
#define TAG_SECTOR_START 15
#define TAG_SECTOR_END 16
#define UNTAG_SECTOR 17
#define TAG_ERASE_GROUP_START 18
#define TAG_ERASE_GROUP_END 19
#define UNTAG_ERASE_GROUP 20
#define ERASE 21
#define LOCK_UNLOCK 22
#define READ_OCR 23
#define CRC_ON_OFF 24
//-----------------------------------------------------------------------------
// UNIONs, STRUCTUREs, and ENUMs
//-----------------------------------------------------------------------------
typedef union LONG { // byte-addressable LONG
long l;
unsigned char b[4];
} LONG;
typedef union INT { // byte-addressable INT
int i;
unsigned char b[2];
} INT;
typedef union { // byte-addressable unsigned long
unsigned long l;
unsigned char b[4];
} ULONG;
typedef union { // byte-addressable unsigned int
unsigned int i;
unsigned char b[2];
} UINT;
// This structure defines entries into the command table;
typedef struct {
unsigned char command_byte; // OpCode;
unsigned char arg_required; // Indicates argument requirement;
unsigned char CRC; // Holds CRC for command if necessary;
unsigned char trans_type; // Indicates command transfer type;
unsigned char response; // Indicates expected response;
unsigned char var_length; // Indicates varialble length transfer;
} COMMAND;
// Command table for MMC. This table contains all commands available in SPI
// mode; Format of command entries is described above in command structure
// definition;
COMMAND code command_list[25] = {
{ 0,NO ,0x95,CMD,R1 ,NO }, // CMD0; GO_IDLE_STATE: reset card;
{ 1,NO ,0xFF,CMD,R1 ,NO }, // CMD1; SEND_OP_COND: initialize card;
{ 9,NO ,0xFF,RD ,R1 ,NO }, // CMD9; SEND_CSD: get card specific data;
{10,NO ,0xFF,RD ,R1 ,NO }, // CMD10; SEND_CID: get card identifier;
{12,NO ,0xFF,CMD,R1 ,NO }, // CMD12; STOP_TRANSMISSION: end read;
{13,NO ,0xFF,CMD,R2 ,NO }, // CMD13; SEND_STATUS: read card status;
{16,YES,0xFF,CMD,R1 ,NO }, // CMD16; SET_BLOCKLEN: set block size;
{17,YES,0xFF,RD ,R1 ,NO }, // CMD17; READ_SINGLE_BLOCK: read 1 block;
{18,YES,0xFF,RD ,R1 ,YES}, // CMD18; READ_MULTIPLE_BLOCK: read > 1;
{24,YES,0xFF,WR ,R1 ,NO }, // CMD24; WRITE_BLOCK: write 1 block;
{25,YES,0xFF,WR ,R1 ,YES}, // CMD25; WRITE_MULTIPLE_BLOCK: write > 1;
{27,NO ,0xFF,CMD,R1 ,NO }, // CMD27; PROGRAM_CSD: program CSD;
{28,YES,0xFF,CMD,R1b,NO }, // CMD28; SET_WRITE_PROT: set wp for group;
{29,YES,0xFF,CMD,R1b,NO }, // CMD29; CLR_WRITE_PROT: clear group wp;
{30,YES,0xFF,CMD,R1 ,NO }, // CMD30; SEND_WRITE_PROT: check wp status;
{32,YES,0xFF,CMD,R1 ,NO }, // CMD32; TAG_SECTOR_START: tag 1st erase;
{33,YES,0xFF,CMD,R1 ,NO }, // CMD33; TAG_SECTOR_END: tag end(single);
{34,YES,0xFF,CMD,R1 ,NO }, // CMD34; UNTAG_SECTOR: deselect for erase;
{35,YES,0xFF,CMD,R1 ,NO }, // CMD35; TAG_ERASE_GROUP_START;
{36,YES,0xFF,CMD,R1 ,NO }, // CMD36; TAG_ERASE_GROUP_END;
{37,YES,0xFF,CMD,R1 ,NO }, // CMD37; UNTAG_ERASE_GROUP;
{38,YES,0xFF,CMD,R1b,NO }, // CMD38; ERASE: erase all tagged sectors;
{42,YES,0xFF,CMD,R1b,NO }, // CMD42; LOCK_UNLOCK;
{58,NO ,0xFF,CMD,R3 ,NO }, // CMD58; READ_OCR: read OCR register;
{59,YES,0xFF,CMD,R1 ,NO } // CMD59; CRC_ON_OFF: toggles CRC checking;
};
//-----------------------------------------------------------------------------
// Global VARIABLES
//-----------------------------------------------------------------------------
// Removed these. It doesn't work correctly on every MMC card, and we need
// all the resources we can get.
xdata unsigned long PHYSICAL_SIZE; // MMC size variable; Set during
// initialization;
xdata unsigned long PHYSICAL_BLOCKS; // MMC block number; Computed during
// initialization;
bdata bit Is_Initialized;
xdata char LOCAL_BLOCK[BUFFER_SIZE];
#define SEND__IN_FUNCTION
#ifdef __F326_VER__
static unsigned char Write_Read_Spi_Byte(unsigned char byte);
#endif
#ifdef SEND__IN_FUNCTION
static unsigned char Write_Read_Spi_Byte(unsigned char byte);
#endif
void Wait_ms(unsigned int count);
void Wait_ns(unsigned int count);
extern BYTE xdata Scratch[PHYSICAL_BLOCK_SIZE];
extern READ_BYTES(unsigned char* pchar,unsigned int len);
extern WRITE_BYTES(unsigned char* pchar,unsigned int len);
#ifdef __F326_VER__
#define BACK_FROM_ERROR \
{\
Write_Read_Spi_Byte(0xFF);\
SCS = 1;\
Write_Read_Spi_Byte(0xFF);\
return ERROR_CODE; \
}
#else
#define BACK_FROM_ERROR \
{\
SPI0DAT = 0xFF; \
while(!SPIF){} \
SPIF = 0; \
NSSMD0 = 1;\
SPI0DAT = 0xFF;\
while(!SPIF){} \
SPIF = 0; \
return ERROR_CODE; \
}
#endif
//----------------------------------------------------------------------------
// SPI0_Init
//----------------------------------------------------------------------------
//
// Configure SPI0 for 8-bit, 2MHz SCK, Master mode, polled operation, data
// sampled on 1st SCK rising edge.
//
// Parameters :
// Return Value :
//----------------------------------------------------------------------------
void SPI_Init (void)
{
#ifdef __F326_VER__
#else
Is_Initialized = 0;
SPI0CFG = 0x70; // data sampled on rising edge, clk
// active low,
// 8-bit data words, master mode;
SPI0CN = 0x0F; // 4-wire mode; SPI enabled; flags
// cleared
#ifdef __F340_VER__
SPI0CKR = 119;
NSSMD0 = 1;
#else
SPI0CKR = SYSCLK/2/10000000; //119; // SPI clock <= 10MHz
#endif
#endif
}
sbit Led1 = P2^2;
sbit Led2 = P2^3;
#define MMC_Show_Activity() { if(Led1) { Led1=0;Led2=1;} else { Led1=1;Led2=0; } }
//-----------------------------------------------------------------------------
// MMC_Command_Exec
//-----------------------------------------------------------------------------
//
// This function generates the necessary SPI traffic for all MMC SPI commands.
// The three parameters are described below:
//
// Cmd: This parameter is used to index into the command table and read
// the desired command. The Command Table Index Constants allow the
// caller to use a meaningful constant name in the Cmd parameter
// instead of a simple index number. For example, instead of calling
// MMC_Command_Exec (0, argument, pchar) to send the MMC into idle
// state, the user can call
// MMC_Command_Exec (GO_IDLE_STATE, argument, pchar);
//
// argument: This parameter is used for MMC commands that require an argument.
// MMC arguments are 32-bits long and can be values such as an
// an address, a block length setting, or register settings for the
// MMC.
//
// pchar: This parameter is a pointer to the local data location for MMC
// data operations. When a read or write occurs, data will be stored
// or retrieved from the location pointed to by pchar.
//
// The MMC_Command_Exec function indexes the command table using the Cmd
// parameter. It reads the command table entry into memory and uses information
// from that entry to determine how to proceed. Returns the 16-bit card
// response value;
//
unsigned int MMC_Command_Exec (unsigned char cmd_loc, unsigned long argument,
unsigned char *pchar)
{
xdata unsigned char loopguard;
idata COMMAND current_command; // Local space for the command table
// entry;
idata ULONG long_arg; // Union variable for easy byte
// transfers of the argument;
// Static variable that holds the
// current data block length;
static xdata unsigned int current_blklen = 512;
unsigned long xdata old_blklen = 512; // Temp variable to preserve data block
// length during temporary changes;
idata unsigned int counter = 0; // Byte counter for multi-byte fields;
idata UINT card_response; // Variable for storing card response;
idata unsigned char data_resp; // Variable for storing data response;
idata unsigned char dummy_CRC; // Dummy variable for storing CRC field;
unsigned char *plast;
// xdata unsigned char c;
current_command = command_list[cmd_loc]; // Retrieve desired command table entry
// from code space;
card_response.i = 0;
#ifdef __F326_VER__
Write_Read_Spi_Byte(0xFF);
SCS = 0;
Write_Read_Spi_Byte(0xFF);
Write_Read_Spi_Byte(current_command.command_byte | 0x40);
#else
#ifdef SEND__IN_FUNCTION
Write_Read_Spi_Byte(0xFF);
NSSMD0 = 0;
Write_Read_Spi_Byte(0xFF);
Write_Read_Spi_Byte(current_command.command_byte | 0x40);
#else
SPI0DAT = 0xFF; // Send buffer SPI clocks to ensure no
while(!SPIF){} // MMC operations are pending;
SPIF = 0;
NSSMD0 = 0; // Select MMC by pulling CS low;
SPI0DAT = 0xFF; // Send another byte of SPI clocks;
while(!SPIF){}
SPIF = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -