#include "FlashRam.hxx" #include "sysLib.h" #include "iostream.h" #include "stdio.h" // This macro is used to make sure that the reads and writes go in // the right order #if (CPU==PPC604) #define EIEIO __asm__ volatile ("eieio") #else #define EIEIO #endif // VME Constructor FlashRam::FlashRam(UINT32 A32_Addr, UINT32 A32_AmCode) : m_pBase(getBase(A32_Addr,A32_AmCode)) {} // get base pointer volatile UINT32* FlashRam::getBase(UINT32 A32_Addr, UINT32 A32_AmCode) { volatile UINT32* Base; // get Dsp Base Address if (sysBusToLocalAdrs(A32_AmCode, (char*)(A32_Addr+FLASH_RAM_BASE_ADDR), (char**)&Base)==ERROR) { printf("ERROR: in getting FlashRam base Address\n"); Base = NULL; } return Base; } // Program (address is 0 for first byte of flash,etc) STATUS FlashRam::Program(UINT32 FlashAddress, UINT8 DataToWrite) { // Unlock for programming // (explained in the Am29F040B manual, table 4 page 12) *(m_pBase+0x555) = 0xaa; *(m_pBase+0x2aa) = 0x55; *(m_pBase+0x555) = 0xa0; // write the DataToWrite into that address *(m_pBase+FlashAddress) = DataToWrite; // Wait for completion and check status return CheckToggle(DataToWrite,FlashAddress); } // Erase Entire Chip STATUS FlashRam::ChipErase() { // "Magic" Chip Erase Sequence // (explained in the Am29F040B manual, table 4 page 12) *(m_pBase+0x555) = 0xaa; *(m_pBase+0x2aa) = 0x55; *(m_pBase+0x555) = 0x80; *(m_pBase+0x555) = 0xaa; *(m_pBase+0x2aa) = 0x55; *(m_pBase+0x555) = 0x10; // Wait for completion and check status return CheckToggle(0xff); } // Erase Sector of Chip (Sector = 0-7) STATUS FlashRam::SectorErase(int Sector) { // check if the sector number is valid if(Sector<0||Sector>NUMBER_OF_SECTORS_IN_FLASH_RAM) { printf("flashRamSectorErase: Sector=%d unknown\n",Sector); return ERROR; } // then switch the chip into sector erase mode // (explained in the Am29F040B manual, table 4 page 12) *(m_pBase+0x555) = 0xaa; *(m_pBase+0x2aa) = 0x55; *(m_pBase+0x555) = 0x80; *(m_pBase+0x555) = 0xaa; *(m_pBase+0x2aa) = 0x55; // Now write the sector to be erased *(m_pBase+(Sector<<16)) = 0x30; // Wait for completion and check status return CheckToggle(0xff); } // Check the toggle bits to wait for operation completion STATUS FlashRam::CheckToggle(UINT8 Data,UINT32 FlashAddress) { EIEIO; // DQ refers to what the flash ram currently reads bit 0-7 int Data7 = (Data>>7)&(0x1); // Data7 for reference // Loop will no time out int DQ5 = 0; int DQ6old = -1; int toggleNum = 0; int toggleStopped = 0; while(DQ5!=1) { // Get Current State UINT32 CurrentState = *(m_pBase+FlashAddress); // get DQ bits int DQ7 = (CurrentState>>7)&(0x1); // DQ7 != Data7 until done if(DQ7 == Data7) { // operation complete // reset for go measure Reset(); return OK; } else { // read DQ5 DQ5 = (CurrentState>>5)&(0x1); // print toggle bit, DQ6 // printf("%1.1x",(CurrentState>>6)&(0x1)); int DQ6 = (CurrentState>>6)&(0x1); if(DQ6 != DQ6old) { DQ6old = DQ6; if((++toggleNum)%10000 == 0) cout << "." << flush; } else { if(toggleStopped!=0) cout << "Error toggle stopped " << toggleStopped << endl; if(toggleStopped++ > 10) return ERROR; } } } // Check if DQ7 flipped at the same time as DQ5 // Get Current State UINT32 CurrentState = *(m_pBase+FlashAddress); // get DQ bits int DQ7 = (CurrentState>>7)&(0x1); // DQ7 != Data7 until done if(DQ7 == Data7) { // write complete // reset for go measure Reset(); return OK; } else { Reset(); return ERROR; } } // Verify Erase STATUS FlashRam::VerifyErase(int Sector) { UINT32 startAddr = 0; UINT32 endAddr = 0; int numErrs = 0; // Find start and stop addresses to check if(Sector == FLASH_RAM_ALL_SECTORS) { startAddr = 0; endAddr = FLASH_RAM_SIZE; } else { startAddr = Sector * FLASH_RAM_SECTOR_SIZE; endAddr = (Sector+1) * FLASH_RAM_SECTOR_SIZE; } // Read all addresses while(startAddr < endAddr) { if(Read(startAddr++)!=0xff) { cout << "Error in erase" << endl; if(numErrs++ > 10) { cout << "Max Errors, exiting..." << endl; return ERROR; } } } // return status if(numErrs >0) {return ERROR;} else {return OK;} } // Perform a write and then read back of flash // (this destroys all the data in the flash!!!) STATUS FlashRam::ReadWriteTest(int Sector) { UINT32 startAddr = 0; UINT32 endAddr = 0; int numErrs = 0; // Erase Chip and setup addresses if (Sector == FLASH_RAM_ALL_SECTORS) { // Test whole chip if(ChipErase()==ERROR) { cout << "Chip Erase Error" << endl; return ERROR; } startAddr = 0; endAddr = FLASH_RAM_SIZE; } else { // Test Sector if(SectorErase(Sector)==ERROR) { cout << "Sector Erase Error" << endl; return ERROR; } startAddr = Sector * FLASH_RAM_SECTOR_SIZE; endAddr = (Sector+1) * FLASH_RAM_SECTOR_SIZE; } // Verify Erase if(VerifyErase(Sector)==ERROR) { cout << "Erase verify failed" << endl; return ERROR; } else { cout << "Erase verifed" << endl; } // Write All Addresses int currentAddr = startAddr; while(currentAddr < endAddr) { if(Program(currentAddr,(currentAddr&0xff))) { cout << "Error in Program" << endl; if(numErrs++ > 10) { cout << "Max Errors, exiting..." << endl; return ERROR; } } currentAddr++; } // Read back/ Check currentAddr = startAddr; while(currentAddr < endAddr) { if(Read(currentAddr)!=(currentAddr&0xff)) { cout << "Error in Read Back" << endl; if(numErrs++ > 10) { cout << "Max Errors, exiting..." << endl; return ERROR; } } currentAddr++; } // Report status if(numErrs>0) { cout << numErrs << " Flash Ram Errors" << endl; return ERROR; } else { cout << "Flash Ram checks out" << endl; return OK; } } // Get Id UINT32 FlashRam::getManufacturerId() { // go into auto select mode setAutoSelect(); // read and return return *(m_pBase+0xf00); } UINT32 FlashRam::getDeviceId() { // go into auto select mode setAutoSelect(); // read and return return *(m_pBase+0xf01); } void FlashRam::setAutoSelect() { // write 3 magic numbers into 3 magic adddresses // then you will be in autoselect mode *(m_pBase+0x555) = 0xaa; *(m_pBase+0x2aa) = 0x55; *(m_pBase+0x555) = 0x90; EIEIO; // that is all return; }