DataFlash_APM2 - moved CS_inactive call (which disables the dataflash) from the beginning to the end of all methods. This means the dataflash does not monopolize the SPI bus.

Also formatting changes to use tab instead of space. Sorry, should have done this as a separate check-in to the above changes.
This commit is contained in:
rmackay9 2012-04-21 20:14:45 +09:00
parent 577f18a09c
commit 346ca5c865
1 changed files with 181 additions and 141 deletions

View File

@ -91,14 +91,16 @@ unsigned char DataFlash_APM2::SPI_transfer(unsigned char data)
return UDR3; return UDR3;
} }
// disable device
void DataFlash_APM2::CS_inactive() void DataFlash_APM2::CS_inactive()
{ {
digitalWrite(DF_SLAVESELECT,HIGH); //disable device digitalWrite(DF_SLAVESELECT,HIGH);
} }
// enable device
void DataFlash_APM2::CS_active() void DataFlash_APM2::CS_active()
{ {
digitalWrite(DF_SLAVESELECT,LOW); //enable device digitalWrite(DF_SLAVESELECT,LOW);
} }
// Constructors //////////////////////////////////////////////////////////////// // Constructors ////////////////////////////////////////////////////////////////
@ -109,223 +111,261 @@ DataFlash_APM2::DataFlash_APM2()
// Public Methods ////////////////////////////////////////////////////////////// // Public Methods //////////////////////////////////////////////////////////////
void DataFlash_APM2::Init(void) void DataFlash_APM2::Init(void)
{ {
pinMode(DF_DATAOUT, OUTPUT); pinMode(DF_DATAOUT, OUTPUT);
pinMode(DF_DATAIN, INPUT); pinMode(DF_DATAIN, INPUT);
pinMode(DF_SLAVESELECT,OUTPUT); pinMode(DF_SLAVESELECT,OUTPUT);
pinMode(DF_RESET,OUTPUT); pinMode(DF_RESET,OUTPUT);
pinMode(DF_CARDDETECT, INPUT); pinMode(DF_CARDDETECT, INPUT);
// Reset the chip // Reset the chip
digitalWrite(DF_RESET,LOW); digitalWrite(DF_RESET,LOW);
delay(1); delay(1);
digitalWrite(DF_RESET,HIGH); digitalWrite(DF_RESET,HIGH);
CS_inactive(); //disable device // disable device
CS_inactive();
// Setup Serial Port3 in SPI mode (MSPI), Mode 0, Clock: 8Mhz // Setup Serial Port3 in SPI mode (MSPI), Mode 0, Clock: 8Mhz
UBRR3 = 0; UBRR3 = 0;
DDRJ |= (1<<PJ2); // SPI clock XCK3 (PJ2) as output. This enable SPI Master mode DDRJ |= (1<<PJ2); // SPI clock XCK3 (PJ2) as output. This enable SPI Master mode
// Set MSPI mode of operation and SPI data mode 0. // Set MSPI mode of operation and SPI data mode 0.
UCSR3C = (1<<UMSEL31)|(1<<UMSEL30); //|(1<<1)|(1<<UCPOL3); UCSR3C = (1<<UMSEL31)|(1<<UMSEL30); //|(1<<1)|(1<<UCPOL3);
// Enable receiver and transmitter. // Enable receiver and transmitter.
UCSR3B = (1<<RXEN3)|(1<<TXEN3); UCSR3B = (1<<RXEN3)|(1<<TXEN3);
// Set Baud rate // Set Baud rate
UBRR3 = 0; // SPI running at 8Mhz UBRR3 = 0; // SPI running at 8Mhz
// get page size: 512 or 528 (by default: 528) // get page size: 512 or 528 (by default: 528)
df_PageSize=PageSize(); df_PageSize=PageSize();
ReadManufacturerID(); ReadManufacturerID();
// see page 22 of the spec for the density code // see page 22 of the spec for the density code
uint8_t density_code = (df_device >> 8) & 0x1F; uint8_t density_code = (df_device >> 8) & 0x1F;
// note that we set df_NumPages to one lower than the highest, as // note that we set df_NumPages to one lower than the highest, as
// the last page is reserved for a config page // the last page is reserved for a config page
if (density_code == 0x7) { if (density_code == 0x7) {
// 32 Mbit // 32 Mbit
df_NumPages = 8191; df_NumPages = 8191;
} else if (density_code == 0x6) { } else if (density_code == 0x6) {
// 16 Mbit // 16 Mbit
df_NumPages = 4095; df_NumPages = 4095;
} else { } else {
// what is this??? card not inserted perhaps? // what is this??? card not inserted perhaps?
df_NumPages = 0; df_NumPages = 0;
} }
} }
// This function is mainly to test the device // This function is mainly to test the device
void DataFlash_APM2::ReadManufacturerID() void DataFlash_APM2::ReadManufacturerID()
{ {
CS_inactive(); // Reset dataflash command decoder // activate dataflash command decoder
CS_active(); CS_active();
// Read manufacturer and ID command... // Read manufacturer and ID command...
SPI_transfer(DF_READ_MANUFACTURER_AND_DEVICE_ID); SPI_transfer(DF_READ_MANUFACTURER_AND_DEVICE_ID);
df_manufacturer = SPI_transfer(0xff); df_manufacturer = SPI_transfer(0xff);
df_device = SPI_transfer(0xff); df_device = SPI_transfer(0xff);
df_device = (df_device<<8) | SPI_transfer(0xff); df_device = (df_device<<8) | SPI_transfer(0xff);
SPI_transfer(0xff); SPI_transfer(0xff);
// release SPI bus for use by other sensors
CS_inactive();
} }
// This function return 1 if Card is inserted on SD slot // This function return 1 if Card is inserted on SD slot
bool DataFlash_APM2::CardInserted() bool DataFlash_APM2::CardInserted()
{ {
return (df_NumPages >= 4095 && digitalRead(DF_CARDDETECT) == 0); return (df_NumPages >= 4095 && digitalRead(DF_CARDDETECT) == 0);
} }
// Read the status register // Read the status register
byte DataFlash_APM2::ReadStatusReg() byte DataFlash_APM2::ReadStatusReg()
{ {
CS_inactive(); // Reset dataflash command decoder byte tmp;
CS_active();
// Read status command // activate dataflash command decoder
SPI_transfer(DF_STATUS_REGISTER_READ); CS_active();
return SPI_transfer(0x00); // We only want to extract the READY/BUSY bit
// Read status command
SPI_transfer(DF_STATUS_REGISTER_READ);
tmp = SPI_transfer(0x00); // We only want to extract the READY/BUSY bit
// release SPI bus for use by other sensors
CS_inactive();
return tmp;
} }
// Read the status of the DataFlash // Read the status of the DataFlash
inline inline
byte DataFlash_APM2::ReadStatus() byte DataFlash_APM2::ReadStatus()
{ {
return(ReadStatusReg()&0x80); // We only want to extract the READY/BUSY bit return(ReadStatusReg()&0x80); // We only want to extract the READY/BUSY bit
} }
inline inline
uint16_t DataFlash_APM2::PageSize() uint16_t DataFlash_APM2::PageSize()
{ {
return(528-((ReadStatusReg()&0x01)<<4)); // if first bit 1 trhen 512 else 528 bytes return(528-((ReadStatusReg()&0x01)<<4)); // if first bit 1 trhen 512 else 528 bytes
} }
// Wait until DataFlash is in ready state... // Wait until DataFlash is in ready state...
void DataFlash_APM2::WaitReady() void DataFlash_APM2::WaitReady()
{ {
while(!ReadStatus()); while(!ReadStatus());
} }
void DataFlash_APM2::PageToBuffer(unsigned char BufferNum, uint16_t PageAdr) void DataFlash_APM2::PageToBuffer(unsigned char BufferNum, uint16_t PageAdr)
{ {
CS_inactive(); // activate dataflash command decoder
CS_active(); CS_active();
if (BufferNum==1)
SPI_transfer(DF_TRANSFER_PAGE_TO_BUFFER_1);
else
SPI_transfer(DF_TRANSFER_PAGE_TO_BUFFER_2);
if(df_PageSize==512){ if (BufferNum==1)
SPI_transfer((unsigned char)(PageAdr >> 7)); SPI_transfer(DF_TRANSFER_PAGE_TO_BUFFER_1);
SPI_transfer((unsigned char)(PageAdr << 1)); else
}else{ SPI_transfer(DF_TRANSFER_PAGE_TO_BUFFER_2);
SPI_transfer((unsigned char)(PageAdr >> 6));
SPI_transfer((unsigned char)(PageAdr << 2));
}
SPI_transfer(0x00); // don´t care bytes
CS_inactive(); //initiate the transfer if(df_PageSize==512){
CS_active(); SPI_transfer((unsigned char)(PageAdr >> 7));
SPI_transfer((unsigned char)(PageAdr << 1));
}else{
SPI_transfer((unsigned char)(PageAdr >> 6));
SPI_transfer((unsigned char)(PageAdr << 2));
}
SPI_transfer(0x00); // don´t care bytes
while(!ReadStatus()); //monitor the status register, wait until busy-flag is high //initiate the transfer
CS_inactive();
CS_active();
while(!ReadStatus()); //monitor the status register, wait until busy-flag is high
// release SPI bus for use by other sensors
CS_inactive();
} }
void DataFlash_APM2::BufferToPage (unsigned char BufferNum, uint16_t PageAdr, unsigned char wait) void DataFlash_APM2::BufferToPage (unsigned char BufferNum, uint16_t PageAdr, unsigned char wait)
{ {
CS_inactive(); // Reset dataflash command decoder // activate dataflash command decoder
CS_active(); CS_active();
if (BufferNum==1) if (BufferNum==1)
SPI_transfer(DF_BUFFER_1_TO_PAGE_WITH_ERASE); SPI_transfer(DF_BUFFER_1_TO_PAGE_WITH_ERASE);
else else
SPI_transfer(DF_BUFFER_2_TO_PAGE_WITH_ERASE); SPI_transfer(DF_BUFFER_2_TO_PAGE_WITH_ERASE);
if(df_PageSize==512){ if(df_PageSize==512){
SPI_transfer((unsigned char)(PageAdr >> 7)); SPI_transfer((unsigned char)(PageAdr >> 7));
SPI_transfer((unsigned char)(PageAdr << 1)); SPI_transfer((unsigned char)(PageAdr << 1));
}else{ }else{
SPI_transfer((unsigned char)(PageAdr >> 6)); SPI_transfer((unsigned char)(PageAdr >> 6));
SPI_transfer((unsigned char)(PageAdr << 2)); SPI_transfer((unsigned char)(PageAdr << 2));
} }
SPI_transfer(0x00); // don´t care bytes SPI_transfer(0x00); // don´t care bytes
CS_inactive(); //initiate the transfer //initiate the transfer
CS_active(); CS_inactive();
CS_active();
// Check if we need to wait to write the buffer to memory or we can continue... // Check if we need to wait to write the buffer to memory or we can continue...
if (wait) if (wait)
while(!ReadStatus()); //monitor the status register, wait until busy-flag is high while(!ReadStatus()); //monitor the status register, wait until busy-flag is high
// release SPI bus for use by other sensors
CS_inactive();
} }
void DataFlash_APM2::BufferWrite (unsigned char BufferNum, uint16_t IntPageAdr, unsigned char Data) void DataFlash_APM2::BufferWrite (unsigned char BufferNum, uint16_t IntPageAdr, unsigned char Data)
{ {
CS_inactive(); // Reset dataflash command decoder // activate dataflash command decoder
CS_active(); CS_active();
if (BufferNum==1) if (BufferNum==1)
SPI_transfer(DF_BUFFER_1_WRITE); SPI_transfer(DF_BUFFER_1_WRITE);
else else
SPI_transfer(DF_BUFFER_2_WRITE); SPI_transfer(DF_BUFFER_2_WRITE);
SPI_transfer(0x00); //don't cares
SPI_transfer((unsigned char)(IntPageAdr>>8)); //upper part of internal buffer address SPI_transfer(0x00); // don't care
SPI_transfer((unsigned char)(IntPageAdr)); //lower part of internal buffer address SPI_transfer((unsigned char)(IntPageAdr>>8)); // upper part of internal buffer address
SPI_transfer(Data); //write data byte SPI_transfer((unsigned char)(IntPageAdr)); // lower part of internal buffer address
SPI_transfer(Data); // write data byte
// release SPI bus for use by other sensors
CS_inactive();
} }
unsigned char DataFlash_APM2::BufferRead (unsigned char BufferNum, uint16_t IntPageAdr) unsigned char DataFlash_APM2::BufferRead (unsigned char BufferNum, uint16_t IntPageAdr)
{ {
byte tmp; byte tmp;
CS_inactive(); // Reset dataflash command decoder // activate dataflash command decoder
CS_active(); CS_active();
if (BufferNum==1) if (BufferNum==1)
SPI_transfer(DF_BUFFER_1_READ); SPI_transfer(DF_BUFFER_1_READ);
else else
SPI_transfer(DF_BUFFER_2_READ); SPI_transfer(DF_BUFFER_2_READ);
SPI_transfer(0x00); //don't cares
SPI_transfer((unsigned char)(IntPageAdr>>8)); //upper part of internal buffer address
SPI_transfer((unsigned char)(IntPageAdr)); //lower part of internal buffer address
SPI_transfer(0x00); //don't cares
tmp = SPI_transfer(0x00); //read data byte
return (tmp); SPI_transfer(0x00);
SPI_transfer((unsigned char)(IntPageAdr>>8)); //upper part of internal buffer address
SPI_transfer((unsigned char)(IntPageAdr)); //lower part of internal buffer address
SPI_transfer(0x00); //don't cares
tmp = SPI_transfer(0x00); //read data byte
// release SPI bus for use by other sensors
CS_inactive();
return (tmp);
} }
// *** END OF INTERNAL FUNCTIONS *** // *** END OF INTERNAL FUNCTIONS ***
void DataFlash_APM2::PageErase (uint16_t PageAdr) void DataFlash_APM2::PageErase (uint16_t PageAdr)
{ {
CS_inactive(); //make sure to toggle CS signal in order // activate dataflash command decoder
CS_active(); //to reset Dataflash command decoder CS_active();
SPI_transfer(DF_PAGE_ERASE); // Command
if(df_PageSize==512){ // Send page erase command
SPI_transfer((unsigned char)(PageAdr >> 7)); SPI_transfer(DF_PAGE_ERASE);
SPI_transfer((unsigned char)(PageAdr << 1));
}else{
SPI_transfer((unsigned char)(PageAdr >> 6));
SPI_transfer((unsigned char)(PageAdr << 2));
}
SPI_transfer(0x00); // "dont cares" if(df_PageSize==512){
CS_inactive(); //initiate flash page erase SPI_transfer((unsigned char)(PageAdr >> 7));
CS_active(); SPI_transfer((unsigned char)(PageAdr << 1));
while(!ReadStatus()); }else{
SPI_transfer((unsigned char)(PageAdr >> 6));
SPI_transfer((unsigned char)(PageAdr << 2));
}
SPI_transfer(0x00);
//initiate flash page erase
CS_inactive();
CS_active();
while(!ReadStatus());
// release SPI bus for use by other sensors
CS_inactive();
} }
void DataFlash_APM2::ChipErase () void DataFlash_APM2::ChipErase ()
{ {
CS_inactive(); //make sure to toggle CS signal in order // activate dataflash command decoder
CS_active(); //to reset Dataflash command decoder CS_active();
// opcodes for chip erase
SPI_transfer(DF_CHIP_ERASE_0);
SPI_transfer(DF_CHIP_ERASE_1);
SPI_transfer(DF_CHIP_ERASE_2);
SPI_transfer(DF_CHIP_ERASE_3);
CS_inactive(); //initiate flash page erase // opcodes for chip erase
CS_active(); SPI_transfer(DF_CHIP_ERASE_0);
while(!ReadStatus()); SPI_transfer(DF_CHIP_ERASE_1);
SPI_transfer(DF_CHIP_ERASE_2);
SPI_transfer(DF_CHIP_ERASE_3);
//initiate flash page erase
CS_inactive();
CS_active();
while(!ReadStatus());
// release SPI bus for use by other sensors
CS_inactive();
} }