//------------------------------------------------------ // AT49BVxxxAx: XJEase device file // (c)2001-2008 XJTAG Limited Revision: 1.13 // // Disclaimer: XJTAG makes no guarantees whatsoever // about this code. You use it at your own risk ... // This file requires XJTAG version 1.4 or later. //------------------------------------------------------ DEVICE NAME := "AT49BVxxxAx" PINS /* //Byte Mode ADDR := 10, 9, 16, 17, 48, 1, 2, 3, 4, 5, 6, 7, 8, 18, 19, 20, 21, 22, 23, 24, 25, 45; DATA := 44, 42, 40, 38, 35, 33, 31, 29; */ //Word mode ADDR := 10, 9, 16, 17, 48, 1, 2, 3, 4, 5, 6, 7, 8, 18, 19, 20, 21, 22, 23, 24, 25; DATA := 45, 43, 41, 39, 36, 34, 32, 30, 44, 42, 40, 38, 35, 33, 31, 29; nOE := 28; nWE := 11; NRESET := 12; nCE := 26; RDY := 15; BYTE := 47; END; DISABLE DEVICE nCE := 1; nOE := 1; END; TEST COVERAGE ADDR := SHORTS OPEN HI LO; DATA := SHORTS OPEN HI LO; nCE := OPEN HI LO; nOE := OPEN HI LO; nWE := OPEN HI LO; END; FILES "memtestFlash.xje"; //"DataReader.xje"; END; END; // Commands: Word INT ADDR_UNLOCK_1 := 0x555; INT ADDR_UNLOCK_2 := 0xAAA; INT ADDR_AUTOSELECT := 0x555; INT ADDR_PROGRAM := 0x555; INT ADDR_ERASE_SETUP := 0x555; INT ADDR_ERASE := 0x555; INT ADDR_DEV_ID := 0x01; /* // Commands: Byte INT ADDR_UNLOCK_1 := 0xAAA; INT ADDR_UNLOCK_2 := 0x1554; INT ADDR_AUTOSELECT := 0xAAA; INT ADDR_PROGRAM := 0xAAA; INT ADDR_ERASE_SETUP := 0xAAA; INT ADDR_ERASE := 0xAAA; INT ADDR_DEV_ID := 0x02; */ // Commands: INT DATA_UNLOCK_1 := 0xAA; INT DATA_UNLOCK_2 := 0x55; INT DATA_AUTOSELECT := 0x90; INT DATA_PROGRAM := 0xA0; INT DATA_ERASE_SETUP := 0x80; INT DATA_ERASE_ALL := 0x10; INT DATA_ERASE_SEC := 0x30; INT ADDR_MAN_ID := 0x00; INT ADDR_SEC_PROTECT := 0x002; // IDs : INT MANUFACTURER_ID := 0x1F; INT DEVICE_ID := 0xC0; // AT49BV16xA //INT DEVICE_ID := 0xC2; // AT49BV16xAT //INT DEVICE_ID := 0xC8 // AT49BV32xA //INT DEVICE_ID := 0xC9 // AT49BV32xAT CONST INT DATA_BUS_WIDTH := WIDTHOF(DATA); CONST INT ADDR_BUS_WIDTH := WIDTHOF(ADDR); CONST INT FLASH_SIZE := (1<<ADDR_BUS_WIDTH)*DATA_BUS_WIDTH; CONST INT RESULT_PASS := FALSE; CONST INT RESULT_FAIL := TRUE; CONST INT DEBUG := FALSE; CONST INT BLOCK_LENGTH := (0x10000/DATA_BUS_WIDTH)*8; CONST INT FLASH_PROG_LEVEL_NONE := 0; // Flash erased everywhere CONST INT FLASH_PROG_LEVEL_SOME := 1; // Flash programmed enough to verify data/addr bus for opens/stucks and data bus // for shorts. Ie. Data written to a single block, or small number of blocks. CONST INT FLASH_PROG_LEVEL_LOTS := 2; // Flash programmed enough to data/addr bus for opens/stucks and shorts. // Ie. Data written to a large number of blocks. //------------------------------------------------------------------------ // The higher this level is set, the more test coverage will be attained. // The aim is to set the highest level possible with the test still passing. // If the flash is totally erased, the test will only pass if this variable // is set to FLASH_PROG_LEVEL_NONE. //------------------------------------------------------------------------ CONST INT FLASH_PROG_LEVEL := FLASH_PROG_LEVEL_NONE; // Globals INT ALL_ONES WIDTH FLASH_SIZE := ~0[(FLASH_SIZE-1)..0]; INT dataSet WIDTH FLASH_SIZE; //------------------------------------------------------------------------ // Includes Read ID test and optional Readonly Data and Address bus tests. // The optional test only be used if the flash has been sufficiently // programmed (by setting FlASH_PROGRAMMED to TRUE). // Much quicker alternative to Destructive test. //------------------------------------------------------------------------ TestNonDestructive()(INT result) INT tempResult; result := RESULT_PASS; IF (WRITEABLE(BYTE)) THEN SET BYTE := 1; END; IF (WRITEABLE(NRESET)) THEN SET NRESET := 0; SET NRESET := 1; END; PRINT("\n\nStarting Read ID test...\n"); ReadIDtest()(result); IF (FLASH_PROG_LEVEL > FLASH_PROG_LEVEL_NONE) THEN PRINT("\nStarting Non-Destructive memory test\n"); MemTestNonDestructive()(tempResult); IF tempResult = RESULT_FAIL THEN result := RESULT_FAIL; END; ELSE PRINT("FLASH_PROG_LEVEL currently set to FLASH_PROG_LEVEL_NONE\nAlthough the ReadID test excersises the data/addr bus and control lines,\na more comprehensive test can be done by changing FLASH_PROG_LEVEL\nThis can only be done if the flash is progammed (see device file for more information).\n\n"); END; IF result = RESULT_FAIL THEN PRINT("Non Destructive Memory Test FAILED...\n\n"); ELSE PRINT("Non Destructive Memory Test PASSED...\n\n"); END; END; //------------------------------------------------------------------------ // Includes Read ID test, and optimised destructive memory test. // Slower than non destructive test, but more reliable. //------------------------------------------------------------------------ TestDestructive()(INT result) INT tempResult; result := RESULT_PASS; IF (WRITEABLE(BYTE)) THEN SET BYTE := 1; END; PRINT("\n\nStarting Read ID test...\n"); ReadIDtest()(result); PRINT("\nStarting Destructive memory test\n"); IF (result = RESULT_PASS) THEN MemTestDestructive()(tempResult); IF tempResult = RESULT_FAIL THEN result := RESULT_FAIL; END; ELSE TestDetail(TRUE)(); END; IF ((result = RESULT_PASS) && WRITEABLE(nCE)) THEN PRINT("\nTesting Chip Enable\n"); TestChipEnable()(result); IF result = RESULT_FAIL THEN PRINT("Chip Enable - pin: ",PINNUM(nCE)," stuck low\n"); END; END; IF result = RESULT_FAIL THEN PRINT("Destructive Memory Test FAILED...\n"); ELSE PRINT("Destructive Memory Test PASSED...\n"); END; END; //------------------------------------------------------ // ReadIDTest //------------------------------------------------------ ReadIDtest()(INT result) INT manufacturer; INT device; PRINT ("Checking Flash ", DEVICE_REF, " ID codes... "); Init()(); result := RESULT_FAIL; // Read Flash IDs. ReadID()(manufacturer, device); ResetFlash()(); manufacturer := manufacturer[7..0]; IF DEBUG THEN PRINT("Manufacturer ID = 0x", HEX(manufacturer), "\n"); PRINT("Device ID = 0x", HEX(device), "\n"); END; // Check the IDs. IF ((manufacturer != MANUFACTURER_ID) || (device != DEVICE_ID)) THEN PRINT("Read Manufacturer ID : 0x", HEX(manufacturer), ", expected to read 0x",HEX(MANUFACTURER_ID),"\n"); PRINT("Read Device ID = 0x", HEX(device), ", expected to read 0x", HEX(DEVICE_ID),"\n"); PRINT("\nFlash ", DEVICE_REF, " ID codes Failed.\n\n"); result := RESULT_FAIL; RETURN; END; PRINT("\nFlash ", DEVICE_REF, " ID codes Passed.\n\n"); result := RESULT_PASS; END; //------------------------------------------------------ // Checks the chip enable pin isn't stuck low //------------------------------------------------------ TestChipEnable()(INT result) INT data; INT temp; result := RESULT_PASS; EraseBlock(0)(temp); WriteCycle(ADDR_UNLOCK_1, DATA_UNLOCK_1); WriteCycle(ADDR_UNLOCK_2, DATA_UNLOCK_2); WriteCycle(ADDR_PROGRAM, DATA_PROGRAM); // try programming with nCE held high SET ADDR := 0; SET nWE := 0, nCE := 1, nOE := 1, DATA := 0; SET nCE := 1, nOE := 1, DATA := I, nWE := 1; WaitReady(0, 0, 100)(temp); ReadWord(0)(data); IF data = 0 THEN result := RESULT_FAIL; END; END; //------------------------------------------------------ // EraseAll //------------------------------------------------------ EraseAll()(INT result) IF DEBUG THEN PRINT("Erasing all flash contents.\n"); END; Init()(); // Two unlock cycles WriteCycle(ADDR_UNLOCK_1, DATA_UNLOCK_1); WriteCycle(ADDR_UNLOCK_2, DATA_UNLOCK_2); // Set-up command WriteCycle(ADDR_ERASE_SETUP, DATA_ERASE_SETUP); // Two unlock write cycles WriteCycle(ADDR_UNLOCK_1, DATA_UNLOCK_1); WriteCycle(ADDR_UNLOCK_2, DATA_UNLOCK_2); // Chip erase command WriteCycle(ADDR_ERASE, DATA_ERASE_ALL); // Poll for erase complete. WaitReady(0x00, 0x80, 0xffff)(result); IF (result != RESULT_PASS) THEN PRINT("Flash not ready after EraseAll\n"); RETURN; END; Init()(); result := RESULT_PASS; IF DEBUG THEN PRINT("Erased all OK\n"); END; END; //------------------------------------------------------ // EraseBlock //------------------------------------------------------ EraseBlock(INT address)(INT result) INT bIsLocked; IsLocked(address)(bIsLocked); IF bIsLocked THEN PRINT("Erase failed: Block is protected"); result := RESULT_FAIL; RETURN; END; result := RESULT_FAIL; IF DEBUG THEN PRINT ("Erase flash block at 0x", HEX(address), "\n"); END; // Two unlock cycles WriteCycle(ADDR_UNLOCK_1, DATA_UNLOCK_1); WriteCycle(ADDR_UNLOCK_2, DATA_UNLOCK_2); // Set-up command WriteCycle(ADDR_ERASE_SETUP, DATA_ERASE_SETUP); // Two unlock write cycles WriteCycle(ADDR_UNLOCK_1, DATA_UNLOCK_1); WriteCycle(ADDR_UNLOCK_2, DATA_UNLOCK_2); // Chip erase command WriteCycle(address, DATA_ERASE_SEC); WaitReady(address, 0xFFFF, 5000)(result); // data is effectively FF, since erasing sets to 1s IF (result != RESULT_PASS) THEN PRINT("Flash not ready after erase.\n"); RETURN; END; result := RESULT_PASS; IF DEBUG THEN PRINT("Block erased.\n"); END; END; //------------------------------------------------------ // ProgramWord // Write a word to the flash //------------------------------------------------------ ProgramWord(INT address, INT data)(INT result) INT read_data; result := RESULT_FAIL; IF DEBUG THEN PRINT ("Program 0x", HEX(data), " to 0x", HEX(address), "\n"); END; WriteCycle(ADDR_UNLOCK_1, DATA_UNLOCK_1); WriteCycle(ADDR_UNLOCK_2, DATA_UNLOCK_2); WriteCycle(ADDR_PROGRAM, DATA_PROGRAM); WriteCycle(address, data); WaitReady(address, data, 200)(result); IF (result != RESULT_PASS) THEN PRINT("Flash not ready after program byte.\n"); RETURN; END; result := RESULT_PASS; IF DEBUG THEN PRINT("Word programmed OK.\n"); END; END; //------------------------------------------------------ // ReadWord // Read a word from the flash //------------------------------------------------------ ReadWord(INT address)(INT data) Init()(); ReadCycle(address)(data); IF DEBUG THEN PRINT ("Read addr 0x", HEX(address), " = 0x", HEX(data), "\n"); END; END; //------------------------------------------------------ // ResetFlash //------------------------------------------------------ ResetFlash()() WriteCycle(0, 0xF0); // Reset and switch to read array mode. END; //------------------------------------------------------ // Init //------------------------------------------------------ Init()() IF DEBUG THEN PRINT("\nInitialising flash...\n")(); END; ResetFlash()(); IF DEBUG THEN PRINT("Initialised\n"); END; END; //------------------------------------------------------ // ReadID // Read the manufacturer and device IDs. //------------------------------------------------------ ReadID()(INT manufacturer, INT device) INT timeout; // Go into autoselect mode. //HOLDOFF WriteCycle(ADDR_UNLOCK_1 , DATA_UNLOCK_1); WriteCycle(ADDR_UNLOCK_2, DATA_UNLOCK_2); WriteCycle(ADDR_AUTOSELECT, DATA_AUTOSELECT); //END; // Read the manufacturer ID. ReadCycle(ADDR_MAN_ID)(manufacturer); // Read the device ID. ReadCycle(ADDR_DEV_ID)(device); END; //------------------------------------------------------ // IsLocked // Check if a block is locked //------------------------------------------------------ IsLocked(INT address)(INT value) INT SA WIDTH 7; INT timeout; SA := address[18..12]; IF DEBUG THEN PRINT("Checking block protection....\n"); END; // Go into autoselect mode. WriteCycle(ADDR_UNLOCK_1, DATA_UNLOCK_1); WriteCycle(ADDR_UNLOCK_2, DATA_UNLOCK_2); WriteCycle(ADDR_AUTOSELECT, DATA_AUTOSELECT); // Is the sector locked? ReadCycle(SA:ADDR_SEC_PROTECT[11..0])(value); value := value[7..0]; // higher byte is xx // Reset the device. ResetFlash()(); // Wait 20 ms SLEEP(20); END; //------------------------------------------------------ // WaitReady // waits until DQ[7] matches passed data[7] or times out // when DQ[5] goes high // also times out after user defined time incase a more // serious failure //------------------------------------------------------ WaitReady (INT address, INT data, INT delay)(INT result) INT status; INT timeout := NOW() + delay; result := RESULT_FAIL; DO ReadCycle(address)(status); IF (status[7] = data[7]) THEN result := RESULT_PASS; RETURN; END; WHILE (status[5] != 1) IF delay != 0 THEN IF NOW() > timeout THEN PRINT("\n Timeout waiting for flash ready ***\n"); RETURN; END; END; END; ReadCycle(address)(status); IF (status[7] != data[7]) THEN PRINT("\n*** Timeout waiting for flash ready ***\n"); RETURN; END; result := RESULT_PASS; END; //------------------------------------------------------ // WriteCycle // Address latched on falling edge of nWE or nCE // Data latched on rising edge of nWE //------------------------------------------------------ WriteCycle(INT address, INT code)() SET ADDR := address[ADDR_BUS_WIDTH-1..0], nWE := 1, nCE := 1, nOE := 1; SET nWE := 0, nCE := 0, DATA := code[DATA_BUS_WIDTH-1..0]; SET nCE := 1, nWE := 1, DATA := I; END; //------------------------------------------------------ // ReadCycle // Address latched on falling edge of nCE // Data latched on rising edge of nCE //------------------------------------------------------ ReadCycle(INT address)(INT result) SET ADDR := address[ADDR_BUS_WIDTH-1..0], DATA := I, nWE := 1, nCE := 1, nOE := 1; SET nCE := 0, nOE := 0; SET result := DATA; SET nCE := 1, nOE := 1, nWE := 1; END; //---------------------------------------------------------------------------------- // Functions required for use of device file with memtestFlash.xje //---------------------------------------------------------------------------------- PrintData(INT i)() PRINT(PINNUM(DATA[i])); END; PrintAddr(INT i)() PRINT(PINNUM(ADDR[i])); END; /*********************FLASH PROGRAMMING*********************************** //------------------------------------------------------ // ProgramFromSRecordFile // Program the flash from an S Record file //------------------------------------------------------ ProgramFromSRecordFile(STRING fileName)(INT result) INT addrLow; INT addrHigh; INT address; PRINT("\n\nStarting flash programming from file ",fileName,"\n"); dataSet := ALL_ONES; ReadSRecordFile(fileName, 0, 0, 16, DATA_BUS_WIDTH)(dataSet, addrLow, addrHigh, result); ProgramFlash(addrLow, addrHigh - addrLow, dataSet)(result); // optional verification of memory written to flash VerifyFlash(dataSet, addrLow, addrHigh - addrLow)(result); END; //------------------------------------------------------ // ProgramFromHexFile // Program the flash from a HEX file //------------------------------------------------------ ProgramFromHexFile(STRING fileName)(INT result) INT addrLow; INT addrHigh; INT address; dataSet := ALL_ONES; ReadHEXFile(fileName, 0, 0, 16, DATA_BUS_WIDTH)(dataSet, addrLow, addrHigh, result); ProgramFlash(addrLow, addrHigh - addrLow, dataSet)(result); // optional verification of memory written to flash VerifyFlash(dataSet, addrLow, addrHigh - addrLow)(result); END; //------------------------------------------------------ // ProgramFromBinFile // Program the flash from a BIN file //------------------------------------------------------ ProgramFromBINFile(STRING fileName)(INT result) INT addrLow; INT addrHigh; INT address; dataSet := ALL_ONES; ReadBINFile(fileName, 0, 16, DATA_BUS_WIDTH)(dataSet, addrLow, addrHigh, result); ProgramFlash(addrLow, addrHigh - addrLow, dataSet)(result); // optional verification of memory written to flash VerifyFlash(dataSet, addrLow, addrHigh - addrLow)(result); END; //------------------------------------------------------ // Program Flash using "dataSet" variable. //------------------------------------------------------ ProgramFlash(INT addrLow, INT numAddresses, INT dataSet)(INT result) //------------------------------------------------------ INT address; INT count := 0; INT tempCount :=0; result := RESULT_FAIL; address := addrLow; FOR address := addrLow FOR numAddresses ProgramWord(address, dataSet[(address+1)*DATA_BUS_WIDTH -1..address*DATA_BUS_WIDTH])(result); IF (result != RESULT_PASS) THEN PRINT("ProgramWord failed in ProgramFile\n"); RETURN; END; tempCount := ((address - addrLow)*100)/numAddresses; IF (tempCount != count && tempCount%5 = 0) THEN PRINT(tempCount, " percent programming complete\r"); count := tempCount; END; END; PRINT("Programming complete \n"); END; //----------------------------------------------------------------- // VerifyFlash with a given dataSet //----------------------------------------------------------------- VerifyFlash(INT dataSet, INT addrLow, INT numAddresses)(INT result) //----------------------------------------------------------------- INT data WIDTH DATA_BUS_WIDTH; INT expectedData WIDTH DATA_BUS_WIDTH; INT address; INT count := 0; INT tempCount :=0; result := RESULT_FAIL; PRINT("Attempting to verify programmed data\n"); ResetFlash()(); FOR address := addrLow FOR numAddresses ReadCycle(address)(data); expectedData := dataSet[(address+1)*DATA_BUS_WIDTH-1..address*DATA_BUS_WIDTH]; IF (expectedData != data) THEN result := RESULT_FAIL; PRINT("\n*** Verify error at address 0x", HEX(address), ", data=0x", HEX(data), ", expected data=0x", HEX(expectedData), " ***\n"); RETURN; END; tempCount := ((address - addrLow)*100)/numAddresses; IF (tempCount != count && tempCount%5 = 0) THEN PRINT(tempCount, " percent verifying complete\r"); count := tempCount; END; END; PRINT("Verified OK. \n"); result := RESULT_PASS; END; //------------------------------------------------------ // Verify flash from a BIN file //------------------------------------------------------ VerifyFlashFromBINFile(STRING fileName)(INT result) //------------------------------------------------------ INT dataSet; INT addrLow; INT addrHigh; result := RESULT_FAIL; ReadBINFile(fileName, 0, 16, DATA_BUS_WIDTH)(dataSet, addrLow, addrHigh, result); IF (result = RESULT_FAIL) THEN PRINT("BIN file failed to be read\n"); END; VerifyFlash(dataSet, addrLow, addrHigh - addrLow)(result); END; //------------------------------------------------------ // Verify flash from a BIN file //------------------------------------------------------ VerifyFlashFromBINFile(STRING fileName)(INT result) //------------------------------------------------------ INT addrLow; INT addrHigh; result := RESULT_FAIL; dataSet := ALL_ONES; ReadBINFile(fileName, 0, 16, DATA_BUS_WIDTH)(dataSet, addrLow, addrHigh, result); IF (result = RESULT_FAIL) THEN PRINT("BIN file failed to be read\n"); END; VerifyFlash(dataSet, addrLow, addrHigh - addrLow)(result); END; //------------------------------------------------------ // Verify flash from a HEX file //------------------------------------------------------ VerifyFlashFromHEXFile(STRING fileName)(INT result) //------------------------------------------------------ INT addrLow; INT addrHigh; result := RESULT_FAIL; dataSet := ALL_ONES; ReadHEXFile(fileName, 0, 0, 16, DATA_BUS_WIDTH)(dataSet, addrLow, addrHigh, result); IF (result = RESULT_FAIL) THEN PRINT("HEX file failed to be read\n"); END; VerifyFlash(dataSet, addrLow, addrHigh - addrLow)(result); END; //------------------------------------------------------ // Verify flash from an S Record file //------------------------------------------------------ VerifyFlashFromSRecordFile(STRING fileName)(INT result) //------------------------------------------------------ INT addrLow; INT addrHigh; result := RESULT_FAIL; dataSet := ALL_ONES; ReadSRecordFile(fileName, 0, 0, 16, DATA_BUS_WIDTH)(dataSet, addrLow, addrHigh, result); IF (result = RESULT_FAIL) THEN PRINT("S-Record file failed to be read\n"); END; VerifyFlash(dataSet, addrLow, addrHigh - addrLow)(result); END; //------------------------------------------------------ // ReadFlash // Read the flash and write contents in binary // format to an open file //------------------------------------------------------ ReadFlash(FILE fp, INT address, INT length)(INT result) INT endAddress := address + length; INT data; IF DEBUG THEN PRINT("Reading Flash\n"); END; ResetFlash()(); result := RESULT_FAIL; DO WHILE address <= endAddress ReadCycle(address)(data); FWRITE(fp, data[0..(DATA_BUS_WIDTH-1)])(); address := address + 1; END; result := RESULT_PASS; IF DEBUG THEN PRINT("Read completed OK\n"); END; END; *************************************************************************/