Part Number Hot Search : 
HC240 MC101 BZX55 MB90F BZX55 A1699 LBS15008 SI2337
Product Description
Full Text Search
 

To Download AN1203 Datasheet File

  If you can't view the Datasheet, Please click here to try to view without PDF Reader .  
 
 


  Datasheet File OCR Text:
  1/31 september 2001 AN1203 application note software drivers for the m28w800c, m28w160c and m28w320c flash memories contents n introduction n the m28wxxxc programming model n writing c code for the m28wxxxc n c library functions provided n porting the drivers to the target system n limitations of the software n conclusion n c1203_16.h listing n c1203_16.c listing introduction this application note provides library source code in c for the m28w800cb, m28w800ct, m28w160cb, m28w160ct, m28w320cb and m28w320ct flash memories. there are two types of each flash memory, a top boot block and a bot- tom boot block, both types are covered in the c code. the set of flash memories will be referred to as m28wxxxc throughout this document. listings of the source code can be found at the end of this doc- ument. the source code is also available in file form from the internet site http://www.st.com or from your stmicroelectronics distributor. the c1203_16.c and c1203_16.h files contain librar- ies for accessing the m28wxxxc flash memories. also included in this application note is an overview of the pro- gramming model for the m28wxxxc. this will familiarize the reader with the operation of the memory devices and provide a basis for understanding and modifying the accompanying source code. the source code is written to be as platform independent as possible and requires minimal changes by the user in order to compile and run. the application note explains how the user should modify the source code for their individual target hard- ware. all of the source code is backed up by comments explain- ing how it is used and why it has been written as it has. this application note does not replace the m28wxxxc datasheet. it refers to the datasheet throughout and it is neces- sary to have a copy in order to follow some of the explanations. the software and accompanying documentation has been fully tested on a target platform. it is small in size and can be applied to any target hardware. the m28wxxxc provides all the hardware and software func- tionality available on intels advanced boot block flash mem- ories. source code written for intels advanced boot block flash memories can easily be modified to use stmicroelec- tronics m28wxxxc memory instead. the m28wxxxc flash memory is compatible with the jedec common flash interface (cfi). this interface allows software to identify the physical memory layout and command set of the flash memory. software that is cfi compatible and includes the correct programming algorithm will automatically be able to
AN1203 - application note 2/31 identify and operate the memory. in this case the software drivers accompanying this application note will not be required. note that the software drivers provided with this application note are not cfi drivers and that they are targeted solely at the m28wxxxc flash memory. the m28wxxxc programming model the m28wxxxc can be electrically erased and programmed through special coded command sequences on most standard microprocessor buses. the device is broken down into different blocks of varying sizes. the main blocks are 32kb x16 in size, whereas the parameter blocks are 4kb x16 in size. each block can be protected and unprotected to prevent or allow progam or erase commands from affecting the memory, the protection state is volatile. the m28wxxxc is a smart voltage device. it differs from first generation devices which require a 12v sup- ply to program or erase. the m28wxxxc is therefore easier to use since the hardware does not need to cater for special bus signal levels. the voltages needed to erase the device are generated by charge pumps inside the device. three power supply pins are used to give the optimal supply voltage conditions. in the simplest model all three voltage supply pins can be supplied with 2.7 to 3.6v. all operations are available in this mode. alternatively the input/output driver section (supplied by v ccq ) can be supplied down to 1.65v to interface to 1.8v microcontrollers. the program/erase section can be supplied with 12v to speed up programming in the factory; this mode is not to be used as a permanent solution. included in the device is a program/erase controller. with first generation flash memory devices the soft- ware had to manually program all of the words to 0000h before erasing to ffffh using special program- ming sequences. the program/erase controller in the m28wxxxc allows a simpler programming model to be used, by taking care of all the necessary steps required to erase and program the memory. this has led to improved reliability so that in excess of 100,000 program/erase cycles are guaranteed per block on the device. bus operations and commands most of the functionality of the m28wxxxc is available via the two standard bus operations: read and write. read operations retrieve data or status information from the device. write operations are interpreted by the device as commands, which modify the data stored or the behavior of the device. only certain special sequences of write operations are recognized as commands by the m28wxxxc. the various commands recognized by the m28wxxxc are listed in the instructions table of the datasheet; the main commands can be grouped as follows: 1. read 2. read electronic signature 3. erase 4. program 5. program/erase suspend 6. common flash interface query 7. block protect/unprotect the read command returns the m28wxxxc to its reset state where it behaves as a rom. in this state, a read operation outputs onto the data bus the data stored at the specified address of the device. the read electronic signature command places the device in a mode which allows the user to read the electronic signature and block protection status of the device. the electronic signature (manufacturer and device codes) and the block protection status are accessed by reading different addresses whilst in the auto select mode. in the library of software drivers this mode is known as the auto select mode to make the m28wxxxc compatible with the m29 series flash memories. the erase command is used to set all the bits to 1 in every memory location in the selected block. all data previously stored in the erased block will be lost. the erase command takes longer to execute than
3/31 AN1203 - application note the other commands, because an entire block is erased at once. attempts to erase or program a protected block generate an error and do not modify the contents of the memory. the program command is used to modify the data stored at the specified address of the device. note that programming can only change bits from 1 to 0. attempting to change a 0 to a 1 using the program command will fail. it may therefore be necessary to erase the block before programming to addresses within it. programming modifies a single word at a time. programming larger amounts of data must be done one word at a time, by issuing a program command, waiting for the command to complete, then is- suing the next program command, and so on. issuing the program/erase suspend command during a program or erase operation will temporarily place the m28wxxxc in program/erase suspend mode. while an erase operation is being suspended the blocks not being erased may be read or programmed as if in the reset state of the device. while a program operation is being suspended the rest of the device may be read. this allows the user to access informa- tion stored in the device immediately rather than waiting until the program or erase operation completes, typically 10 m s for programming and 1s for erasing on the m28wxxxc. the program or erase operation is resumed when the device receives the program/erase resume command. the common flash interface query command of the device allows the user to identify the number of blocks and the addresses of the blocks in the flash. the interface also contains information relating to the typical and maximum program and erase durations. this allows the user to implement software timeouts instead of waiting indefinitely for a defective flash to finish programming or erasing. for further information about the cfi, please refer to the cfi specification available from the internet site (http://www.st.com) or from your stmicroelectronics distributor. blocks can be protected against accidental or malicious program and erase operations changing their contents. block protection is volatile; after power up or a hardware reset all blocks are protected, but not locked. the boot code can lock blocks that require additional security and unlock user data blocks before the application runs, giving full flexible control over block protection. the status register while the m28wxxxc is programming or erasing, a read from the device will output the status register of the program/erase controller. the status register, which can also be accessed by issuing the read sta- tus register command, provides valuable information about the most recent program or erase command. the status register bits are described in the status register bits table of the m28wxxxc datasheet. their main use is to determine when programming or erasing is complete and whether it is successful or not. completion of the program or erase operation is indicated by the program/erase controller status bit (status register bit dq7) becoming 1. programming or erasing errors are then indicated by one or more of the various error bits (status register bits dq1, dq3, dq4 and dq5) being 1. if a failure occurs the status register error bits will remain set until a clear status register command is issued to the device. this should be done before performing any further operations or it will not be possible to determine wheth- er the following operation resulted in an error or not. a detailed example the instructions table of the m28wxxxc datasheet describes the sequences of write operations that will be recognized by the program/erase controller as valid commands. for example programming 9465h to the address 03e2h requires the user to write the following sequence (in c): *(unsigned int*)(0x0000) = 0x0040; *(unsigned int*)(0x03e2) = 0x9465; the first of the two addresses (0000h) is arbitrary, so long as it is inside the flash address space. this example assumes that address 0000h of the m28wxxxc is mapped to address 0000h in the microproces-
AN1203 - application note 4/31 sor address space. in practice it is likely that the flash will have a base offset which needs to be added to the address. while the device is programming the specified address, read operations will access the status register bits. status register bit dq7 will be 0 while programming is on-going and will become 1 on completion. if status register bits dq1, dq3 or dq4 are set on completion then the program command will have failed. the status register bits do not always indicate an error when an attempt to change a 0 to a 1 has been made; it is recommended that the value in the memory after programming is compared to the desired value to trap this error. writing c code for the m28wxxxc the low-level functions (drivers) described in this application note have been provided to simplify the pro- cess of developing application code in c for the stmicroelectronics flash memories (m28wxxxc). this enables users to concentrate on writing the high level functions required for their particular applications. these high level functions can access the flash memories by calling the low level drivers, hence keeping details of special command sequences away from the users' high level code: this will result in source code both simpler and easier to maintain. code developed using the drivers provided can be decomposed into three layers: 1. the hardware specific bus operations 2. the low-level drivers 3. the high level functions written by the user the implementation in c of the hardware specific read and write bus operations is required by the low- level drivers in order to communicate with the m28wxxxc. this implementation is hardware platform de- pendent as it is affected by which microprocessor the c code runs on and by where in the microproces- sor's address space the memory device is located. the user will have to write the c functions appropriate to his hardware platform (see flashread() and flashwrite() in the next section). the low-level drivers take care of issuing the correct sequences of write operations for each command and of interpreting the information received from the device during programming or erasing. these drivers encode all the specific details of how to issue commands and how to interpret the status register bits. the high level functions written by the user will access the memory device by calling the low-level func- tions. by keeping the specific details of how to access the m28wxxxc away from the high level functions, the user is left with code which is simple and easier to maintain. it also makes the user's high level func- tions easier to apply to other stmicroelectronics flash memories. when developing an application, the user is advised to proceed as follows: C first write a simple program to test the low level drivers provided and verify that these operate as ex- pected on the user's target hardware and software environments. C then the user should write the high level code for his application, which will access the flash memories by calling the low level drivers provided. C finally test the complete application source code thoroughly. c library functions provided the software library provided with this application note provides the user with source code for the following functions: flashreadreset() is used to reset the device into the read array mode. note that there should be no need to call this function under normal operation as all of the other software library functions leave the device in this mode.
5/31 AN1203 - application note flashautoselect() is used to identify the manufacturer code, device code and block protection sta- tus of the device. the function uses the read electronic signature mode of the device. the function is called flashautoselect() to make it compatible with the m29 series flash memories. flashreadcfi() is used to read a word from the cfi area of the memory. after reading the cfi word the memory is returned to read mode. flashblockerase() is used to erase a block in the device. protected blocks cannot be erased and the function returns an error when the user attempts to erase a protected block. similarly, the blocks cannot be erased when v pp is invalid: attempting to do so generates an error and leaves the flash in an indeter- minate state. flashchiperase() is used to erase the entire chip. it cannot erase any protected blocks. if some of the blocks are protected an error is returned. the unprotected blocks are still erased. flashprogram() is used to program data arrays into the flash. only previously erased words can be programmed reliably. again, protected blocks cannot be programmed, nor can programming take place when v pp is invalid. flashblockprotect() is used to protect a block, preventing program and erase operations from changing the contents. flashblockunprotect() is used to unprotect a block, allowing program and erase operations to change the contents. flashblocklock() is used to lock a block, see the protection states table of the datasheet. once locked the lock state of a block can only be removed through a hardware reset. the functions provided in the software library rely on the user implementing the hardware specific bus op- erations. this is to be done by writing two functions as follows: C flashread() must be written to read a value from the flash. C flashwrite() must be written to write a value to the flash. an example of these functions is provided in the source code. in many instances these functions can be written as macros and therefore will not incur the function call time overhead. the two functions which perform the basic i/o to the device have been provided for users who have awkward systems. for example where the addressing system is peculiar or the data bus has d0..d15 of the device on d16..d31 of the microprocessor. they allow any user to quickly adapt the code to virtually any target system. throughout the functions assumptions have been made on the data types. these are: a char is 8 bits (1 byte). this is not the case in all microcontrollers. where it is not it will be necessary to mask the unused bits of the word. an int is 16 bits (2 bytes). again, like the char , if this is not the case it will be necessary to use a variable type which is 16 bits or longer and mask bits above 16 bits (particularly in the users flashread() func- tion). a long is 32 bits (4 bytes). it is necessary to have arithmetic greater than 16 bits in order to address the entire device. two approaches to the addressing are available: the desired address in the flash can be specified by a 32 bit linear pointer or a 32 bit offset into the device could be provided by the user. the flashread() functions in each case would declared as: unsigned int flashread( unsigned int *addr); unsigned int flashread( unsigned long uloff); the pointer option has the advantage that it runs faster. the 32 bit offset needs to be changed to an ad- dress for each access and this involves 32 bit arithmetic. using a 32 bit offset is, however, more portable
AN1203 - application note 6/31 since the resulting software can easily be changed to run on microprocessors with segmented memory spaces (such as the 8086). for maximum portability all the functions in this application note use a 32 bit unsigned long offset, rather than a pointer. porting the drivers to the target system before using the software in the target system the user needs to do the following: 1. define one of the following depending on which part is fitted. the top of the source file provided defines use_m28w800ct as an example. use_m28w800cb use_m28w800ct use_m28w160cb use_m28w160ct use_m28w320cb use_m28w320ct 2. write flashread() and flashwrite() functions appropriate to the target hardware. the example flashread() and flashwrite() functions provided in the source code should give the user a good idea of what is required and can be used in many instances without much modification. to test the source code in the target system start by simply reading from the m28wxxxc. if it is erased then only ffffh data should be read. next read the manufacturer and device codes and check they are correct. if these functions work then it is likely that all of the functions will work but they should all be tested thoroughly. the programmer needs to take extra care when the device is accessed during an interrupt service routine. two situations exist which must be considered: 1. when the device is in read mode interrupts can freely read from the device. 2. interrupts which do not access the device may be used during all the functions. the programmer should also take care when a hardware reset is applied during program or erase oper- ations. the flash will be left in an indeterminate state and data could be lost. limitations of the software the software provided does not implement a full set of the m28wxxxc's functionality. it is left to the user to implement the program/erase suspend command of the device. the double word program and the protection register program commands are intended for use but programming equipment and have not been included in these embedded drivers. the standby mode is a hardware feature of the device and can- not be controlled through software. care should be taken in some of the while() loops. no time-outs have been implemented. software ex- ecution may stop in one of the loops due to a hardware error. a /* timeout! */ comment has been put at these places and the user can add a timer to them to prevent the software failing. the software only caters for one device in the system. to add software for more devices a mechanism for selecting the devices will be required. when an error occurs the software simply returns the error message. it is left to the user to decide what to do. either the command can be tried again or, if necessary the device may need to be replaced. conclusion the m28wxxxc single voltage flash memory is an ideal product for embedded and other computer sys- tems, able to be easily interfaced to microprocessors and driven with simple software drivers written in the c language.
7/31 AN1203 - application note revision history date version revision details december - 2000 -01 first issue 18-sep-2001 -02 changes to pages 12, 13 and 14. top boot block numbers reversed to correspond to datasheet.
AN1203 - application note 8/31 /**** c1203_16.h header file for flash memory ********************************** filename: c1203_16.h description: header file for c1203_16.c v1.01. consult the c file for details copyright (c) 2000 stmicroelectronics. this program is provided as is without warranty of any kind,either expressed or implied, including but not limited to, the implied warranty of merchantability and fitness for a particular purpose. the entire risk as to the quality and performance of the program is with you. should the program prove defective, you assume the cost of all necessary servicing, repair or correction. *******************************************************************************/ /******************************************************************************* commands for the various functions *******************************************************************************/ #define flash_block_locked_protected (0x03) #define flash_block_locked (0x02) #define flash_block_protected (0x01) #define flash_block_unprotected (0x00) #define flash_read_manufacturer (-2) #define flash_read_device_code (-1) /******************************************************************************* error conditions and return values. see end of c file for explanations and help *******************************************************************************/ #define flash_success (-1) #define flash_block_invalid (-5) #define flash_program_fail (-6) #define flash_offset_out_of_range (-7) #define flash_wrong_type (-8) #define flash_block_failed_erase (-9) #define flash_unprotected (-10) #define flash_protected (-11) #define flash_function_not_supported (-12) #define flash_vpp_invalid (-13) #define flash_erase_fail (-14) #define flash_unprotect_fail (-16) #define flash_protect_fail (-18) #define flash_cfi_fail (-19) #define flash_locked (-20) #define flash_lock_fail (-21) /******************************************************************************* function prototypes *******************************************************************************/ extern unsigned int flashread( unsigned long uloff ); extern void flashreadreset( void ); extern int flashautoselect( int ifunc ); extern int flashreadcfi( int icfifunc, unsigned int *ucfivalue ); extern int flashblockerase( unsigned char ucblock ); extern int flashchiperase( int *iresults ); extern int flashblockprotect(unsigned char ucblock); extern int flashblocklock(unsigned char ucblock);
9/31 AN1203 - application note extern int flashblockunprotect(unsigned char ucblock); extern int flashprogram( unsigned long uloff, size_t numwords, void *array ); extern char *flasherrorstr( int ierrnum );
AN1203 - application note 10/31 /**** c1203_16.c m28wxxxc flash memory driver ********************************* filename: c1203_16.c description: library routines for the m28wxxxc flash memory. version: 1.00 initial release. date: 10/11/2000 author: tim webster, oxford technical solutions (www.ots.ndirect.co.uk) copyright (c) 2000 stmicroelectronics. this program is provided as is without warranty of any kind, either expressed or implied, including but not limited to, the implied warranty of merchantability and fitness for a particular purpose. the entire risk as to the quality and performance of the program is with you. should the program prove defective, you assume the cost of all necessary servicing, repair or correction. ******************************************************************************** version history. ver. date comments 0.00 18/09/2000 initial creation 1.00 25/09/2000 software tested using m28w032cb. ******************************************************************************** this source file provides library c code for using the m28wxxxc devices. the following devices are supported in the code: m28w800ct m28w800cb m28w160ct m28w160cb m28w320ct m28w320cb the following functions are available in this library: flashreadreset() to reset the flash for normal memory access flashautoselect() to get information about the device flashreadcfi() to read cfi information from the flash flashblockerase() to erase a single block flashchiperase() to erase the whole chip flashblockprotect() to protect a block in the flash flashblocklock() to lock a block and prevent it being unprotected flashblockunprotect() to unprotect a block in the flash flashprogram() to program a word or an array flasherrorstr() to return the error string of an error for further information consult the data sheet and the application note. the application note gives information about how to modify this code for a specific application. the hardware specific functions which need to be modified by the user are: flashwrite() for writing a word to the flash flashread() for reading a word from the flash
11/31 AN1203 - application note a list of the error conditions is at the end of the code. there are no timeouts implemented in the loops in the code. at each point where an infinite loop is implemented a comment /# timeout! #/ has been placed. it is up to the user to implement these to avoid the code hanging instead of timing out. the source code assumes that the compiler implements the numerical types as unsigned char 8 bits unsigned int 16 bits unsigned long 32 bits additional changes to the code will be necessary if these are not correct. *******************************************************************************/ #include #include c1203_16.h /* header file with global prototypes */ #define use_m28w320cb /******************************************************************************* constants *******************************************************************************/ #define manufacturer_st (0x0020) /* st rsig for manufacturer is always 0x20 */ #define base_addr ((volatile unsigned int*)0x0000) /* base_addr is the base address of the flash, see the functions flashread and flashwrite(). some applications which require a more complicated flashread() or flashwrite() may not use base_addr */ #define any_addr (0x0000l) /* any address offset within the flash memory will do */ #ifdef use_m28w800ct #define expected_device (0x88cc) /* device code for the m28w800ct */ #define flash_size (0x80000l) /* 512k */ #endif #ifdef use_m28w800cb #define expected_device (0x88cd) /* device code for the m28w800cb */ #define flash_size (0x80000l) /* 512k */ #endif #ifdef use_m28w160ct #define expected_device (0x88ce) /* device code for the m28w160ct */ #define flash_size (0x100000l) /* 1m */ #endif #ifdef use_m28w160cb #define expected_device (0x88cf) /* device code for the m28w160cb */ #define flash_size (0x100000l) /* 1m */ #endif #ifdef use_m28w320ct #define expected_device (0x88ba) /* device code for the m28w160ct */ #define flash_size (0x200000l) /* 2m */ #endif
AN1203 - application note 12/31 #ifdef use_m28w320cb #define expected_device (0x88bb) /* device code for the m28w160cb */ #define flash_size (0x200000l) /* 2m */ #endif #ifdef use_m28w800ct /* block organisation for top boot block devices */ static const unsigned long blockoffset[] = { 0x00000l, /* start offset of block 22 */ 0x08000l, /* start offset of block 21 */ 0x10000l, /* start offset of block 20 */ 0x18000l, /* start offset of block 19 */ 0x20000l, /* start offset of block 18 */ 0x28000l, /* start offset of block 17 */ 0x30000l, /* start offset of block 16 */ 0x38000l, /* start offset of block 15 */ 0x40000l, /* start offset of block 14 */ 0x48000l, /* start offset of block 13 */ 0x50000l, /* start offset of block 12 */ 0x58000l, /* start offset of block 11 */ 0x60000l, /* start offset of block 10 */ 0x68000l, /* start offset of block 9 */ 0x70000l, /* start offset of block 8 */ 0x78000l, /* start offset of block 7 */ 0x79000l, /* start offset of block 6 */ 0x7a000l, /* start offset of block 5 */ 0x7b000l, /* start offset of block 4 */ 0x7c000l, /* start offset of block 3 */ 0x7d000l, /* start offset of block 2 */ 0x7e000l, /* start offset of block 1 */ 0x7f000l /* start offset of block 0 */ }; #endif /* use_m28w800ct */ #ifdef use_m28w800cb /* block organisation for bottom boot block devices */ static const unsigned long blockoffset[] = { 0x00000l, /* start offset of block 0 */ 0x01000l, /* start offset of block 1 */ 0x02000l, /* start offset of block 2 */ 0x03000l, /* start offset of block 3 */ 0x04000l, /* start offset of block 4 */ 0x05000l, /* start offset of block 5 */ 0x06000l, /* start offset of block 6 */ 0x07000l, /* start offset of block 7 */ 0x08000l, /* start offset of block 8 */ 0x10000l, /* start offset of block 9 */ 0x18000l, /* start offset of block 10 */ 0x20000l, /* start offset of block 11 */ 0x28000l, /* start offset of block 12 */ 0x30000l, /* start offset of block 13 */ 0x38000l, /* start offset of block 14 */ 0x40000l, /* start offset of block 15 */ 0x48000l, /* start offset of block 16 */ 0x50000l, /* start offset of block 17 */ 0x58000l, /* start offset of block 18 */
13/31 AN1203 - application note 0x60000l, /* start offset of block 19 */ 0x68000l, /* start offset of block 20 */ 0x70000l, /* start offset of block 21 */ 0x78000l /* start offset of block 22 */ }; #endif /* use_m28w800cb */ #ifdef use_m28w160ct /* block organisation for top boot block devices */ static const unsigned long blockoffset[] = { 0x00000l, /* start offset of block 38 */ 0x08000l, /* start offset of block 37 */ 0x10000l, /* start offset of block 36 */ 0x18000l, /* start offset of block 35 */ 0x20000l, /* start offset of block 34 */ 0x28000l, /* start offset of block 33 */ 0x30000l, /* start offset of block 32 */ 0x38000l, /* start offset of block 31 */ 0x40000l, /* start offset of block 30 */ 0x48000l, /* start offset of block 29 */ 0x50000l, /* start offset of block 28 */ 0x58000l, /* start offset of block 27 */ 0x60000l, /* start offset of block 26 */ 0x68000l, /* start offset of block 25 */ 0x70000l, /* start offset of block 24 */ 0x78000l, /* start offset of block 23 */ 0x80000l, /* start offset of block 22 */ 0x88000l, /* start offset of block 21 */ 0x90000l, /* start offset of block 20 */ 0x98000l, /* start offset of block 19 */ 0xa0000l, /* start offset of block 18 */ 0xa8000l, /* start offset of block 17 */ 0xb0000l, /* start offset of block 16 */ 0xb8000l, /* start offset of block 15 */ 0xc0000l, /* start offset of block 14 */ 0xc8000l, /* start offset of block 13 */ 0xd0000l, /* start offset of block 12 */ 0xd8000l, /* start offset of block 11 */ 0xe0000l, /* start offset of block 10 */ 0xe8000l, /* start offset of block 9 */ 0xf0000l, /* start offset of block 8 */ 0xf8000l, /* start offset of block 7 */ 0xf9000l, /* start offset of block 6 */ 0xfa000l, /* start offset of block 5 */ 0xfb000l, /* start offset of block 4 */ 0xfc000l, /* start offset of block 3 */ 0xfd000l, /* start offset of block 2 */ 0xfe000l, /* start offset of block 1 */ 0xff000l /* start offset of block 0 */ }; #endif /* use_m28w160ct */ #ifdef use_m28w160cb /* block organisation for bottom boot block devices */ static const unsigned long blockoffset[] = { 0x00000l, /* start offset of block 0 */ 0x01000l, /* start offset of block 1 */
AN1203 - application note 14/31 0x02000l, /* start offset of block 2 */ 0x03000l, /* start offset of block 3 */ 0x04000l, /* start offset of block 4 */ 0x05000l, /* start offset of block 5 */ 0x06000l, /* start offset of block 6 */ 0x07000l, /* start offset of block 7 */ 0x08000l, /* start offset of block 8 */ 0x10000l, /* start offset of block 9 */ 0x18000l, /* start offset of block 10 */ 0x20000l, /* start offset of block 11 */ 0x28000l, /* start offset of block 12 */ 0x30000l, /* start offset of block 13 */ 0x38000l, /* start offset of block 14 */ 0x40000l, /* start offset of block 15 */ 0x48000l, /* start offset of block 16 */ 0x50000l, /* start offset of block 17 */ 0x58000l, /* start offset of block 18 */ 0x60000l, /* start offset of block 19 */ 0x68000l, /* start offset of block 20 */ 0x70000l, /* start offset of block 21 */ 0x78000l, /* start offset of block 22 */ 0x80000l, /* start offset of block 23 */ 0x88000l, /* start offset of block 24 */ 0x90000l, /* start offset of block 25 */ 0x98000l, /* start offset of block 26 */ 0xa0000l, /* start offset of block 27 */ 0xa8000l, /* start offset of block 28 */ 0xb0000l, /* start offset of block 29 */ 0xb8000l, /* start offset of block 30 */ 0xc0000l, /* start offset of block 31 */ 0xc8000l, /* start offset of block 32 */ 0xd0000l, /* start offset of block 33 */ 0xd8000l, /* start offset of block 34 */ 0xe0000l, /* start offset of block 35 */ 0xe8000l, /* start offset of block 36 */ 0xf0000l, /* start offset of block 37 */ 0xf8000l /* start offset of block 38 */ }; #endif /* use_m28w160cb */ #ifdef use_m28w320ct /* block organisation for top boot block devices */ static const unsigned long blockoffset[] = { 0x000000l, /* start offset of block 70 */ 0x008000l, /* start offset of block 69 */ 0x010000l, /* start offset of block 68 */ 0x018000l, /* start offset of block 67 */ 0x020000l, /* start offset of block 66 */ 0x028000l, /* start offset of block 65 */ 0x030000l, /* start offset of block 64 */ 0x038000l, /* start offset of block 63 */ 0x040000l, /* start offset of block 62 */ 0x048000l, /* start offset of block 61 */ 0x050000l, /* start offset of block 60 */ 0x058000l, /* start offset of block 59 */ 0x060000l, /* start offset of block 58 */ 0x068000l, /* start offset of block 57 */ 0x070000l, /* start offset of block 56 */
15/31 AN1203 - application note 0x078000l, /* start offset of block 55 */ 0x080000l, /* start offset of block 54 */ 0x088000l, /* start offset of block 53 */ 0x090000l, /* start offset of block 52 */ 0x098000l, /* start offset of block 51 */ 0x0a0000l, /* start offset of block 50 */ 0x0a8000l, /* start offset of block 49 */ 0x0b0000l, /* start offset of block 48 */ 0x0b8000l, /* start offset of block 47 */ 0x0c0000l, /* start offset of block 46 */ 0x0c8000l, /* start offset of block 45 */ 0x0d0000l, /* start offset of block 44 */ 0x0d8000l, /* start offset of block 43 */ 0x0e0000l, /* start offset of block 42 */ 0x0e8000l, /* start offset of block 41 */ 0x0f0000l, /* start offset of block 40 */ 0x0f8000l, /* start offset of block 39 */ 0xf00000l, /* start offset of block 38 */ 0x108000l, /* start offset of block 37 */ 0x110000l, /* start offset of block 36 */ 0x118000l, /* start offset of block 35 */ 0x120000l, /* start offset of block 34 */ 0x128000l, /* start offset of block 33 */ 0x130000l, /* start offset of block 32 */ 0x138000l, /* start offset of block 31 */ 0x140000l, /* start offset of block 30 */ 0x148000l, /* start offset of block 29 */ 0x150000l, /* start offset of block 28 */ 0x158000l, /* start offset of block 27 */ 0x160000l, /* start offset of block 26 */ 0x168000l, /* start offset of block 25 */ 0x170000l, /* start offset of block 24 */ 0x178000l, /* start offset of block 23 */ 0x180000l, /* start offset of block 22 */ 0x188000l, /* start offset of block 21 */ 0x190000l, /* start offset of block 20 */ 0x198000l, /* start offset of block 19 */ 0x1a0000l, /* start offset of block 18 */ 0x1a8000l, /* start offset of block 17 */ 0x1b0000l, /* start offset of block 16 */ 0x1b8000l, /* start offset of block 15 */ 0x1c0000l, /* start offset of block 14 */ 0x1c8000l, /* start offset of block 13 */ 0x1d0000l, /* start offset of block 12 */ 0x1d8000l, /* start offset of block 11 */ 0x1e0000l, /* start offset of block 10 */ 0x1e8000l, /* start offset of block 9 */ 0x1f0000l, /* start offset of block 8 */ 0x1f8000l, /* start offset of block 7 */ 0x1f9000l, /* start offset of block 6 */ 0x1fa000l, /* start offset of block 5 */ 0x1fb000l, /* start offset of block 4 */ 0x1fc000l, /* start offset of block 3 */ 0x1fd000l, /* start offset of block 2 */ 0x1fe000l, /* start offset of block 1 */ 0x1ff000l /* start offset of block 0 */ }; #endif /* use_m28w320ct */
AN1203 - application note 16/31 #ifdef use_m28w320cb /* block organisation for bottom boot block devices */ static const unsigned long blockoffset[] = { 0x000000l, /* start offset of block 0 */ 0x001000l, /* start offset of block 1 */ 0x002000l, /* start offset of block 2 */ 0x003000l, /* start offset of block 3 */ 0x004000l, /* start offset of block 4 */ 0x005000l, /* start offset of block 5 */ 0x006000l, /* start offset of block 6 */ 0x007000l, /* start offset of block 7 */ 0x008000l, /* start offset of block 8 */ 0x010000l, /* start offset of block 9 */ 0x018000l, /* start offset of block 10 */ 0x020000l, /* start offset of block 11 */ 0x028000l, /* start offset of block 12 */ 0x030000l, /* start offset of block 13 */ 0x038000l, /* start offset of block 14 */ 0x040000l, /* start offset of block 15 */ 0x048000l, /* start offset of block 16 */ 0x050000l, /* start offset of block 17 */ 0x058000l, /* start offset of block 18 */ 0x060000l, /* start offset of block 19 */ 0x068000l, /* start offset of block 20 */ 0x070000l, /* start offset of block 21 */ 0x078000l, /* start offset of block 22 */ 0x080000l, /* start offset of block 23 */ 0x088000l, /* start offset of block 24 */ 0x090000l, /* start offset of block 25 */ 0x098000l, /* start offset of block 26 */ 0x0a0000l, /* start offset of block 27 */ 0x0a8000l, /* start offset of block 28 */ 0x0b0000l, /* start offset of block 29 */ 0x0b8000l, /* start offset of block 30 */ 0x0c0000l, /* start offset of block 31 */ 0x0c8000l, /* start offset of block 32 */ 0x0d0000l, /* start offset of block 33 */ 0x0d8000l, /* start offset of block 34 */ 0x0e0000l, /* start offset of block 35 */ 0x0e8000l, /* start offset of block 36 */ 0x0f0000l, /* start offset of block 37 */ 0x0f8000l, /* start offset of block 38 */ 0x100000l, /* start offset of block 39 */ 0x108000l, /* start offset of block 40 */ 0x110000l, /* start offset of block 41 */ 0x118000l, /* start offset of block 42 */ 0x120000l, /* start offset of block 43 */ 0x128000l, /* start offset of block 44 */ 0x130000l, /* start offset of block 45 */ 0x138000l, /* start offset of block 46 */ 0x140000l, /* start offset of block 47 */ 0x148000l, /* start offset of block 48 */ 0x150000l, /* start offset of block 49 */ 0x158000l, /* start offset of block 50 */ 0x160000l, /* start offset of block 51 */ 0x168000l, /* start offset of block 52 */ 0x170000l, /* start offset of block 53 */ 0x178000l, /* start offset of block 54 */
17/31 AN1203 - application note 0x180000l, /* start offset of block 55 */ 0x188000l, /* start offset of block 56 */ 0x190000l, /* start offset of block 57 */ 0x198000l, /* start offset of block 58 */ 0x1a0000l, /* start offset of block 59 */ 0x1a8000l, /* start offset of block 60 */ 0x1b0000l, /* start offset of block 61 */ 0x1b8000l, /* start offset of block 62 */ 0x1c0000l, /* start offset of block 63 */ 0x1c8000l, /* start offset of block 64 */ 0x1d0000l, /* start offset of block 65 */ 0x1d8000l, /* start offset of block 66 */ 0x1e0000l, /* start offset of block 67 */ 0x1e8000l, /* start offset of block 68 */ 0x1f0000l, /* start offset of block 69 */ 0x1f8000l /* start offset of block 70 */ }; #endif /* use_m28w320cb */ #define num_blocks (sizeof(blockoffset)/sizeof(blockoffset[0])) /******************************************************************************* static prototypes the following function is only needed in this module. *******************************************************************************/ static unsigned int flashwrite( unsigned long uloff, unsigned int uval ); /******************************************************************************* function: unsigned int flashwrite( unsigned long uloff, unsigned int uval ) arguments: uloff is word offset in the flash to write to. uval is the value to be written returns: uval description: this function is used to write a word to the flash. on many microprocessor systems a macro can be used instead, increasing the speed of the flash routines. for example: #define flashwrite( uloff, uval ) ( base_addr[uloff] = (unsigned int) uval ) a function is used here instead to allow the user to expand it if necessary. the function is made to return uval so that it is compatible with the macro. pseudo code: step 1: write uval to the word offset in the flash step 2: return uval *******************************************************************************/ static unsigned int flashwrite( unsigned long uloff, unsigned int uval ) { /* step1, 2: write uval to the word offset in the flash and return it */ return base_addr[uloff] = uval; } /******************************************************************************* function: unsigned int flashread( unsigned long uloff ) arguments: uloff is the word offset into the flash to read from. returns: the unsigned int at the word offset description: this function is used to read a word from the flash. on many microprocessor systems a macro can be used instead, increasing the speed of the flash routines. for example:
AN1203 - application note 18/31 #define flashread( uloff ) ( base_addr[uloff] ) a function is used here instead to allow the user to expand it if necessary. pseudo code: step 1: return the value at word offset uloff *******************************************************************************/ unsigned int flashread( unsigned long uloff ) { /* step 1 return the value at word offset uloff */ return base_addr[uloff]; } /******************************************************************************* function: void flashreadreset( void ) arguments: none return value: none description: this function places the flash in the read array mode described in the data sheet. in this mode the flash can be read as normal memory. all of the other functions leave the flash in the read array mode so this is not strictly necessary. it is provided for completeness. pseudo code: step 1: write command sequence (see instructions table of the data sheet) *******************************************************************************/ void flashreadreset( void ) { /* step 1: write command sequence */ flashwrite( any_addr, 0x00ff ); } /******************************************************************************* function: int flashautoselect( int ifunc ) arguments: ifunc should be set to one of the read signature values. the header file defines the values for reading the signature. return value: when ifunc is flash_read_manufacturer (-2) the function returns the manufacturers code. the manufacturer code for st is 0020h. when ifunc is flash_read_device_code (-1) the function returns the device code. the device codes for the parts are: m28w800ct 88cch m28w800cb 88cdh m28w160ct 88ceh m28w160cb 88cfh m28w320ct 88bah m28w320cb 88bbh when ifunc is invalid the function returns flash_function_not_supported (-12) description: this function can be used to read the electronic signature of the device or the manufacturer code. note: the command sequence given here is not described in the data sheet. the addresses and commands are applicable to the m29 series flash devices. the only command required for the m28wxxxc is the final one, the 0x0090 command (read electronic signature command). the other writes to the command interface will be ignored by the m28wxxxc. the advantage of this is that the flashautoselect() function will be able to identify the m29 series flash devices as well as the m28 series flash devices. unlike many other flash memories, it is important to ensure a1 to a7 are
19/31 AN1203 - application note low when reading the manufacturer and device codes as m28wxxxc uses bits a1 to a7 to access the protection register. pseudo code: step 1: send the auto select instruction to the device or rsig instruction step 2: read the required function from the device step 3: return the device to read array mode *******************************************************************************/ int flashautoselect( int ifunc ) { int iretval; /* holds the return value */ /* step 1: send the read electronic signature instruction */ flashwrite( 0x5555l, 0x00aa ); /* 1st cycle, ignored by m28 series devices */ flashwrite( 0x2aaal, 0x0055 ); /* 2nd cycle, ignored by m28 series devices */ flashwrite( 0x5555l, 0x0090 ); /* 3rd cycle */ /* step 2: read the required function */ if( ifunc == flash_read_manufacturer ) iretval = flashread( 0x0000l ); /* a0 = a1 = 0 */ else if( ifunc == flash_read_device_code ) iretval = flashread( 0x0001l ); /* a0 = 1, a1 = 0 */ else if( (ifunc >= 0) && (ifunc < num_blocks) ) iretval = (flashread( blockoffset[ifunc] + 0x0002l )); /* a0 = 0, a1 = 1 */ else iretval = flash_block_invalid; /* step 3: return to read array mode */ flashwrite( any_addr, 0x00ff ); return iretval; } /******************************************************************************* function: int flashreadcfi( int icfifunc, unsigned int *ucfivalue ) arguments: icfifunc is set to the offset of the cfi parameter to be read. the cfi value read from offset icfifunc is passed back to the calling function by *ucfivalue. return value: on success returns flash_success (-1) or if the cfi cannot be identified by reading the chracters qry from locations 0x10, 0x11 and 0x12, the function returns flash_cfi_fail (-19) description: this function checks that the flash cfi is present and operable, then reads the cfi value at the specified offset. the cfi value requested is then passed back to the calling function. note: pseudo code: step 1: send the read cfi instruction step 2: check that the cfi interface is operable step 3: if cfi is operable read the required cfi value step 4: return the flash to read array mode *******************************************************************************/ int flashreadcfi( int icfifunc, unsigned int *ucfivalue ) { int iretval = flash_success; /* holds the return value */ unsigned long ulcfiaddr; /* holds cfi address */
AN1203 - application note 20/31 /* step 1: send the read cfi instruction */ flashwrite( 0x0055l, 0x0098 ); /* step 2: check that the cfi interface is operable */ if( (flashread( 0x0010l ) != q ) || (flashread( 0x0011l ) !=r ) || (flashread( 0x0012l ) != y )) iretval=flash_cfi_fail; else { /* step 3: read the required cfi */ ulcfiaddr = (unsigned long)icfifunc; *ucfivalue = flashread( ulcfiaddr & 0x00ffl ); } /* step 4: return to read array mode */ flashwrite( any_addr, 0x00ff ); return iretval; } /******************************************************************************* function: int flashblockerase( unsigned char ucblock ) arguments: ucblock is the number of the block to be erased. return value: the function returns the following conditions: flash_success (-1) flash_wrong_type (-8) flash_block_invalid (-5) flash_protected (-11) flash_vpp_invalid (-13) flash_block_failed_erase (-9) description: this function can be used to erase the block specified in ucblock. the function checks that the block is valid before issuing the erase command. once the erase has completed the function checks the status register for errors. any errors are returned, otherwise flash_success is returned. pseudo code: step 1: check for correct flash type step 2: check that the block is valid step 3: issue erase command step 4: wait until program/erase controller is ready step 5: check for any errors step 6: return to read array mode step 7: return error condition *******************************************************************************/ int flashblockerase( unsigned char ucblock ) { int iretval = flash_success; /* holds return value: optimistic initially! */ unsigned int ustatus; /* holds the status register reads */ /* step 1: check for correct flash type */ if( !(flashautoselect( flash_read_manufacturer ) == manufacturer_st) || !(flashautoselect( flash_read_device_code ) == expected_device ) ) return flash_wrong_type; /* step 2: check that the block is valid */ if( ucblock >= num_blocks ) return flash_block_invalid;
21/31 AN1203 - application note /* step 3: issue erase command */ flashwrite( any_addr, 0x0050 ); /* clear status register */ /* note ! csr also clears b1 bps as well as b3,4 and 5 */ flashwrite( any_addr, 0x0020 ); /* 1st cycle */ flashwrite( blockoffset[ucblock], 0x00d0 ); /* 2nd cycle */ /* step 4: wait until program/erase controller is ready */ /* timeout! */ do ustatus = flashread(any_addr); while( (ustatus&0x0080) == 0x0000 ); /* step 5: check for any errors */ if( ustatus&0x0002 ) iretval = flash_protected; else if( ustatus&0x0008 ) iretval = flash_vpp_invalid; else if( ustatus&0x0020 ) iretval = flash_block_failed_erase; /* step 6: return to read array mode */ flashwrite( any_addr, 0x0050 ); /* clear status register */ /* note ! csr also clears b1 bps as well as b3,4 and 5 */ flashwrite( any_addr, 0x00ff ); /* read array command */ /* step 7: return error condition */ return iretval; } /******************************************************************************* function: int flashchiperase( int *iresults ) arguments: iresults is a pointer to an array where the results will be stored. if iresults == null then no results are stored. return value: the function returns the following conditions: flash_success (-1) flash_wrong_type (-8) flash_erase_fail (-14) if flash_success is returned then results is left unchanged. if flash_erase_fail is returned then results will be filled with the error conditions for each block. the possible error conditions are: flash_success (-1) flash_protected (-11) flash_vpp_invalid (-13) flash_erase_fail (-14) description: the function can be used to erase the whole flash chip. each block is erased in turn. the function only returns when all of the blocks have been erased or have generated an error, except if the flash_vpp_invalid is encountered, in which case the function aborts and reports all remaining blocks as having flash_vpp_invalid. if vpp is invalid for one block then it follows that it will be invalid for subsequent blocks (battery failure?). pseudo code: step 1: check for correct flash type step 2: for each block
AN1203 - application note 22/31 step 3: send block erase command step 4: register the errors in the array step 5: if flash_vpp_invalid returned fill rest of results array & abort step 6: return error condition *******************************************************************************/ int flashchiperase( int *iresults ) { unsigned char uccurblock; /* used to track the current block in a range */ int iretval = flash_success; /* return value: initially optimistic */ int ierror; /* holds the latest error */ /* step 1: check for correct flash type */ if( !(flashautoselect( flash_read_manufacturer ) == manufacturer_st) || !(flashautoselect( flash_read_device_code ) == expected_device ) ) return flash_wrong_type; /* step 2: for each block */ for( uccurblock = 0; uccurblock < num_blocks; uccurblock++ ) { /* step 3: send block erase command */ ierror = flashblockerase( uccurblock ); if( ierror != flash_success ) iretval = flash_erase_fail; /* step 4: register the errors in the array */ if( iresults != null ) iresults[uccurblock] = ierror; /* step 5: if flash_vpp_invalid returned fill rest of results array & abort */ if( ierror == flash_vpp_invalid ) { if( iresults != null ) while( ++uccurblock < num_blocks ) /* on remaining blocks */ iresults[uccurblock] = ierror; /* fill in vpp error */ /* the for() loop will now terminate since uccurblock == num_blocks */ } } /* step 6: return error condition */ return iretval; } /******************************************************************************* function: int flashblockunprotect(unsigned char ucblock) arguments: ucblock holds the block number to unprotect return value: the function returns the following conditons: flash_wrong_type (-8) flash_success (-1) flash_unprotect_fail (-16) flash_unprotected (-10) flash_block_invalid (-5) description: this function unprotects a block selected by ucblock but only if that particular block is protected and valid. the block unprotect command is then written and then checked to ensure that it was successful. pseudo code: step 1: check for correct flash type step 2: check to see if the block number ucblock is valid
23/31 AN1203 - application note step 3: check is the block really needs unprotecting as it may already be unprotected step 4: unprotect the block step 5: check the block ucblock for protection status step 6: check for errors *******************************************************************************/ int flashblockunprotect(unsigned char ucblock) { int iretval; /* store result */ /* step 1: check for correct flash type */ if( !(flashautoselect( flash_read_manufacturer ) == manufacturer_st) || !(flashautoselect( flash_read_device_code ) == expected_device ) ) return flash_wrong_type; iretval = flashautoselect( (int)ucblock ); /* step 2 */ if (iretval == flash_block_invalid) return flash_block_invalid; /* step 3 */ else if (iretval == flash_block_unprotected) return flash_unprotected; /* step 4 unprotect the block */ flashwrite(any_addr,0x0060); flashwrite(blockoffset[ucblock], 0x00d0); /* step 5 check block ucblock for protection status */ iretval = flashautoselect( (int)ucblock ); /* step 6: check for any errors */ if ((iretval == flash_block_protected) || (iretval == flash_block_locked_protected)) return flash_unprotect_fail; else return flash_success; } /******************************************************************************* function: int flashblockprotect(unsigned char ucblock) arguments: ucblock holds the block number to protect return value: the function returns the following conditons: flash_wrong_type (-8) flash_success (-1) flash_protect_fail (-18) flash_protected (-11) flash_block_invalid (-5) description: this function protects a block selected by ucblock but only if that particular block is unprotected and valid. the block protect command is then written and then checked to ensure that it was successful. pseudo code: step 1: check for correct flash type step 2: check to see if the block number ucblock is valid step 3: check is the block really needs unprotecting as it may already be unprotected step 4: unprotect the block step 5: read the block ucblock to check protection status step 6: check for error condition
AN1203 - application note 24/31 *******************************************************************************/ int flashblockprotect(unsigned char ucblock) { int iretval; /* store result */ /* step 1: check for correct flash type */ if( !(flashautoselect( flash_read_manufacturer ) == manufacturer_st) || !(flashautoselect( flash_read_device_code ) == expected_device ) ) return flash_wrong_type; iretval = flashautoselect( (int)ucblock ); /* step 2 */ if (iretval == flash_block_invalid) return flash_block_invalid; /* step 3 */ else if((iretval == flash_block_protected) || (iretval == flash_block_locked_protected)) return flash_protected; /* step 4 protect the block */ flashwrite(any_addr,0x0060); flashwrite(blockoffset[ucblock], 0x0001); /* step 5 check block ucblock for protection status */ iretval = flashautoselect( (int)ucblock ); /* step 6: check for any errors */ if (iretval < flash_block_protected) return flash_protect_fail; else return flash_success; } /******************************************************************************* function: int flashblocklock(unsigned char ucblock) arguments: ucblock holds the block number to lock return value: the function returns the following conditons: flash_locked (-20) on success flash_lock_fail (-21) if the locking was unsuccessful flash_block_invalid (-5) if the block is not valid description: this function locks a block selected by ucblock but only if that particular block is valid. it then tests to see if the lock command was successful. pseudo code: step 1: check for correct flash type step 2: check to see if the block number ucblock is valid step 3: check is the block really needs locking as it may already be locked step 4: lock the block step 5: check that it locked *******************************************************************************/ int flashblocklock(unsigned char ucblock) { /* step 1: check for correct flash type */ if ( !(flashautoselect( flash_read_manufacturer ) == manufacturer_st) || !(flashautoselect( flash_read_device_code ) == expected_device ) ) return flash_wrong_type;
25/31 AN1203 - application note /* step 2: is the block valid ? */ if (flashautoselect( (int)ucblock ) == flash_block_invalid) return flash_block_invalid; /* step 3: do not lock if the block is already locked */ if (((flashautoselect( (int)ucblock )) & 0x02) == flash_block_locked) return flash_locked; /* step 4: lock the block */ flashwrite(any_addr,0x0060); flashwrite(blockoffset[ucblock], 0x002f); /* step 5: check that it locked */ if (((flashautoselect( (int)ucblock )) & 0x02) == flash_block_locked) return flash_success; else return flash_lock_fail; } /******************************************************************************* function: int flashprogram( unsigned long uloff, size_t numwords, void *array ) arguments: uloff is the word offset into the flash to be programmed numwords holds the number of words in the array. array is a pointer to the array to be programmed. return value: on success the function returns flash_success (-1). if a protected address is given the function returns flash_protected (-11). if vpp is invalid then the function returns flash_vpp_invalid (-13) on failure the function returns flash_program_fail (-6). if the address range to be programmed exceeds the address range of the flash device the function returns flash_address_out_of_range (-7) and nothing is programmed. if the wrong type of flash is detected then flash_wrong_type (-8) is returned and nothing is programmed. description: this function is used to program an array into the flash. it does not erase the flash first and will fail if the block(s) are not erased first. pseudo code: step 1: check for correct flash type step 2: check the offset range is valid step 3: while there is more to be programmed step 4: program the next word step 5: wait until the program/erase controller is ready step 6: check for any errors step 7: update pointers step 8: step 8: clear status register and return to read array mode step 9: return the error condition *******************************************************************************/ int flashprogram( unsigned long uloff, size_t numwords, void *array ) { unsigned int *uarraypointer; /* use an unsigned int to access the array */ unsigned long ullastoff; /* holds the last offset to be programmed */ unsigned int ustatus; /* holds the status register reads */ int iretval = flash_success; /* return value: initially optimistic */ /* step 1: check that the flash is of the correct type */ if( !(flashautoselect( flash_read_manufacturer ) == manufacturer_st) || !(flashautoselect( flash_read_device_code ) == expected_device ) )
AN1203 - application note 26/31 return flash_wrong_type; /* step 2: check the offset range is valid */ ullastoff = uloff + numwords - 1; if( ullastoff >= flash_size ) return flash_offset_out_of_range; /* step 3: while there is more to be programmed */ uarraypointer = (unsigned int *)array; while( uloff <= ullastoff && iretval == flash_success ) { /* step 4: program the next word */ flashwrite( any_addr, 0x0050 ); /* clear status register */ flashwrite( any_addr, 0x0040 ); /* program set-up */ flashwrite( uloff, *uarraypointer ); /* program value */ /* step 5: wait until program/erase controller is ready */ /* timeout! */ do ustatus = flashread(any_addr); while( (ustatus&0x0080) == 0x0000 ); /* step 6: check for any errors */ if( ustatus&0x0002 ) iretval = flash_protected; else if( ustatus&0x0008 ) iretval = flash_vpp_invalid; else if( ustatus&0x0010 ) iretval = flash_program_fail; /* step 7: update pointers */ uloff++; /* next word offset */ uarraypointer++; /* next word in array */ } /* step 8: clear status register and return to read array mode */ flashwrite( any_addr, 0x0050 ); /* clear status register */ /* note ! csr also clears b1 bps as well as b3,4 and 5 */ flashwrite( any_addr, 0x00ff ); /* read array command */ /* step 9: return the error condition */ return iretval; } /******************************************************************************* function: char *flasherrorstr( int ierrnum ); arguments: ierrnum is the error number returned from another flash routine return value: a pointer to a string with the error message description: this function is used to generate a text string describing the error from the flash. call with the return value from another flash routine. pseudo code: step 1: check the error message range. step 2: return the correct string. *******************************************************************************/ char *flasherrorstr( int ierrnum ) {
27/31 AN1203 - application note static char *str[] = { flash success, flash poll failure, flash too many blocks, mpu is too slow to erase all the blocks, flash block selected is invalid, flash program failure, flash address offset out of range, flash is wrong type, flash block failed erase, flash is unprotected, flash is protected, flash function not supported, flash vpp invalid, flash erase fail, flash toggle flow chart failure, flash unprotect failed, flash bank invalid, flash protect failed, flash cfi query failed, flash locked, flash lock failed }; /* step 1: check the error message range */ ierrnum = -ierrnum - 1; /* all errors are negative: make +ve & adjust */ if( ierrnum < 0 || ierrnum >= sizeof(str)/sizeof(str[0])) /* check range */ return unknown error\n; /* step 2: return the correct string */ else return str[ierrnum]; } /******************************************************************************* list of errors and return values, explanations and help. ******************************************************************************** return name: flash_success return value: -1 description: this value indicates that the flash command has executed correctly. ******************************************************************************** error name: flash_poll_fail notes: applies to m29 series flash only. this error condition should not occur when using this library. return value: -2 description: the program/erase controller algorithm has not managed to complete the command operation successfully. this may be because the device is damaged solution: try the command again. if it fails a second time then it is likely that the device will need to be replaced. ******************************************************************************** error name: flash_too_many_blocks notes: applies to m29 series flash only. this error condition should not occur when using this library. return value: -3 description: the user has chosen to erase more blocks than the device has.
AN1203 - application note 28/31 this may be because the array of blocks to erase contains the same block more than once. solutions: check that the program is trying to erase valid blocks. the device will only have num_blocks blocks (defined at the top of the file). also check that the same block has not been added twice or more to the array. ******************************************************************************** error name: flash_mpu_too_slow notes: applies to m29 series flash only. this error condition should not occur when using this library. return value: -4 description: the mpu has not managed to write all of the selected blocks to the device before the timeout period expired. see block erase command section of the data sheet for details. solutions: if this occurs occasionally then it may be because an interrupt is occuring between writing the blocks to be erased. search for dsi! in the code and disable interrupts during the time critical sections. if this error condition always occurs then it may be time for a faster microprocessor, a better optimising c compiler or, worse still, learn assembly. the immediate solution is to only erase one block at a time. disable the test (by #defineing out the code) and always call the function with one block at a time. ******************************************************************************** error name: flash_block_invalid return value: -5 description: a request for an invalid block has been made. valid blocks number from 0 to num_blocks-1. solution: check that the block is in the valid range. ******************************************************************************** error name: flash_program_fail return value: -6 description: the programmed value has not been programmed correctly. solutions: make sure that the block containing the value was erased before programming. try erasing the block and re-programming the value. if it fails again then the device may have blocks protected. it is also possible for the block to be locked but is unlikely if /wp pin is kept high. if the program fail still results it is likely that the flash is suspect. ******************************************************************************** error name: flash_offset_out_of_range return value: -7 description: the address offset given is out of the range of the device. solution: check the address offset is in the valid range. ******************************************************************************** error name: flash_wrong_type return value: -8 description: the source code has been used to access the wrong type of flash. solutions: use a different flash chip with the target hardware or contact stmicroelectronics for a different source code library. ******************************************************************************** error name: flash_block_failed_erase return value: -9 description: the previous erase to this block has not managed to successfully erase the block. solution: the block may be protected/locked or the flash is suspect.
29/31 AN1203 - application note ******************************************************************************** return name: flash_unprotected return value: -10 description: the user has requested to unprotect a block that is already unprotected. this is just a warning to the user that their operation did not make any changes and was not necessary. ******************************************************************************** error name: flash_protected return value: -11 description: the user has attempted to erase, program or protect a block of the flash that is protected. the operation failed because the block was protected. solutions: choose another (unprotected) block for erasing or programming. alternatively change the block protection status of the current block. (see datasheet for more details). in the case of the user protecting a block that is already protected, this warning notifies the user that the command had no effect. ******************************************************************************** return name: flash_function_not_supported return value: -12 description: the user has attempted to make use of functionality not available on this flash device (and thus not provided by the software drivers). this is simply a warning to the user. ******************************************************************************** error name: flash_vpp_invalid notes: applies to m28 series flash only. return value: -13 description: a program or a block erase has been attempted with the vpp supply voltage outside the allowed ranges. this command had no effect since an invalid vpp has the effect of protecting the whole of the flash device. solution: the (hardware) configuration of vpp will need to be modified to make programming or erasing the device possible. ******************************************************************************** error name: flash_erase_fail return value: -14 description: this indicates that the previous erasure of the whole device has failed. solution: investigate this failure further by attempting to erase each block individually. if erasing a single block still causes failure, then the flash sadly needs replacing. ******************************************************************************** error name: flash_toggle_fail return value: -15 notes: applies to m29 series flash only. this error condition should not occur when using this library. description: the program/erase controller algorithm has not managed to complete the command operation successfully. this may be because the device is damaged. solution: try the command again. if it fails a second time then it is likely that the device will need to be replaced. ******************************************************************************** error name: flash_unprotect_fail
AN1203 - application note 30/31 return value: -16 description: this error return value indicates that a block unprotect command was unsuccessful. solution: try the command again. if it fails a second time then it is likely that the device is either locked or will need to be replaced. (part is unlocked but protected on power-up with /wp pin at v_high). ******************************************************************************** error name: flash_bank_invalid return value: -17 notes: this applies to m59drxxx series flash only. description: this error return value indicates that a bank does not exist. ******************************************************************************** error name: flash_protect_fail return value: -18 description: this error return value indicates that a block protect command was unsuccessful. solution: try the command again. if it fails a second time then it is likely that the device is either locked or will need to be replaced. (part is unlocked but protected on power-up with /wp pin at v_high). ******************************************************************************** error name: flash_cfi_fail return value: -19 description: this error return value indicates that a cfi read was unsuccessful solution: try an autoselect command if this fails it is likely that the device is faulty or the interface to the flash is not correct. ******************************************************************************** error name: flash_locked return value: -20 description: this error return value indicates that the flash block selected was already locked. this is not an error but a method of informing the user that the command had no effect. solution: the block was already locked. was the right block selected ? ******************************************************************************** error name: flash_lock_fail return value: -21 description: this error return value indicates that the flash lock command on the selected block failed. solution: try an autoselect command if this fails it is likely that the device is faulty or the interface to the flash is not correct. *******************************************************************************/
31/31 AN1203 - application note if you have any questions or suggestion concerning the matters raised in this document please send them to the following electronic mail address: ask.memory@st.com (for general enquiries) please remember to include your name, company, location, telephone number and fax number. information furnished is believed to be accurate and reliable. however, stmicroelectronics assumes no responsibility for the co nsequences of use of such information nor for any infringement of patents or other rights of third parties which may result from its use. no license is granted by implication or otherwise under any patent or patent rights of stmicroelectronics. specifications mentioned in this publicati on are subject to change without notice. this publication supersedes and replaces all information previously supplied. stmicroelectronics prod ucts are not authorized for use as critical components in life support devices or systems without express written approval of stmicroelectro nics. the st logo is registered trademark of stmicroelectronics all other names are the property of their respective owners ? 2001 stmicroelectronics - all rights reserved stmicroelectronics group of companies australia - brazil - china - finland - france - germany - hong kong - india - italy - japan - malaysia - malta - morocco - singapore - spain - sweden - switzerland - united kingdom - u.s.a. www.st.com


▲Up To Search▲   

 
Price & Availability of AN1203

All Rights Reserved © IC-ON-LINE 2003 - 2022  

[Add Bookmark] [Contact Us] [Link exchange] [Privacy policy]
Mirror Sites :  [www.datasheet.hk]   [www.maxim4u.com]  [www.ic-on-line.cn] [www.ic-on-line.com] [www.ic-on-line.net] [www.alldatasheet.com.cn] [www.gdcy.com]  [www.gdcy.net]


 . . . . .
  We use cookies to deliver the best possible web experience and assist with our advertising efforts. By continuing to use this site, you consent to the use of cookies. For more information on cookies, please take a look at our Privacy Policy. X