mirror of https://github.com/ArduPilot/ardupilot
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:
parent
577f18a09c
commit
346ca5c865
|
@ -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();
|
||||||
}
|
}
|
Loading…
Reference in New Issue