SE 746-NT Embedded Software Systems Development


Published on

  • Be the first to comment

  • Be the first to like this

No Downloads
Total views
On SlideShare
From Embeds
Number of Embeds
Embeds 0
No embeds

No notes for slide

SE 746-NT Embedded Software Systems Development

  1. 1. SE 746-NT Embedded Software Systems Development Robert Oshana Lecture # 6 For more information, please contact: NTU Tape Orders: NTU Media Services: (970) 495-6455 [email_address] [email_address]
  2. 2. Lecture 6 More Hardware fundamentals - Memory
  3. 3. Agenda <ul><li>Memory testing </li></ul><ul><li>Validating memory contents </li></ul><ul><li>Flash memory </li></ul>
  4. 4. Electrical wiring problems <ul><li>Data line problems </li></ul><ul><ul><li>Bits might appear to be stuck </li></ul></ul><ul><ul><li>Two or more bits contain the same value regardless of the data being transferred </li></ul></ul><ul><ul><li>“ stuck high” (always 1) </li></ul></ul><ul><ul><li>“ stuck low” (always 0) </li></ul></ul><ul><li>Detected by writing a sequence of data values designed to test each data pin can be set to 0 and 1, independently of all others </li></ul>
  5. 5. Electrical wiring problems <ul><li>Address wiring problems </li></ul><ul><ul><li>Contents of two memory locations may appear to overlap </li></ul></ul><ul><ul><ul><li>Data written to one address will overwrite the contents of another address </li></ul></ul></ul><ul><ul><li>Memory device is “seeing” an address different from the one the processor has selected </li></ul></ul>
  6. 6. Electrical wiring problems <ul><li>Control lines </li></ul><ul><ul><li>Hard to describe a general test for testing for control lines open or closed </li></ul></ul><ul><ul><li>Operation specific to processor or memory architecture </li></ul></ul><ul><ul><li>Problems here usually indicate that memory will not work at all </li></ul></ul><ul><ul><li>Seek advice of designer for how to test </li></ul></ul>
  7. 7. Missing memory chips <ul><li>Missing memory chips may not be detected! </li></ul><ul><ul><li>Capacitance nature of unconnected electrical wires </li></ul></ul><ul><ul><li>Some memory tests do write followed immediately by a read </li></ul></ul><ul><ul><li>This could result in reading remaining voltage from the previous write </li></ul></ul><ul><ul><li>If read to quickly, it appears there is data being stored when there is nothing there! </li></ul></ul>
  8. 8. Missing memory chips <ul><ul><li>Perform several consecutive writes followed by the same number of reads </li></ul></ul><ul><ul><ul><li>Write value 1 to memory location A </li></ul></ul></ul><ul><ul><ul><li>Write value 2 to memory location B </li></ul></ul></ul><ul><ul><ul><li>Write value 3 to memory location C </li></ul></ul></ul><ul><ul><ul><li>Read from location A </li></ul></ul></ul><ul><ul><ul><li>Read from location B </li></ul></ul></ul><ul><ul><ul><li>Read from location C </li></ul></ul></ul><ul><ul><ul><li>If no memory, first value read will correspond to last value written instead of first </li></ul></ul></ul>
  9. 9. Improperly inserted chips <ul><li>Symptom is that system will behave as though there is a wiring problem or a missing chip </li></ul><ul><ul><li>Some number of pins not connected at all or connected to the wrong locations </li></ul></ul><ul><ul><li>Could be part of the address, data, or control lines </li></ul></ul><ul><li>Tests for missing chips and wiring problems will catch this problem as well </li></ul>
  10. 10. Developing a test strategy <ul><li>Carefully select the test data </li></ul><ul><li>Carefully select the order in which addresses are tested </li></ul><ul><li>Break your memory into small testable pieces </li></ul><ul><ul><li>Improves efficiency of test </li></ul></ul><ul><ul><li>Improves readability of code </li></ul></ul><ul><li>More specific tests can provide more detailed information if desired </li></ul>
  11. 11. Developing a test strategy <ul><li>Three individual tests </li></ul><ul><ul><li>Data bus test (wiring and improperly inserted chip test) </li></ul></ul><ul><ul><li>Address bus test (wiring and improperly inserted chip test) </li></ul></ul><ul><ul><li>Device test (missing chips and catastrophic failures) </li></ul></ul>
  12. 12. Developing a test strategy <ul><li>Order to execute tests </li></ul><ul><ul><li>1. Data bus test; </li></ul></ul><ul><ul><li>2. Address bus test; assumes a working data bus </li></ul></ul><ul><ul><li>3. Device test; assumes working address and data bus </li></ul></ul><ul><li>Most of the problems can be found by looking at the data </li></ul>
  13. 13. Data bus test <ul><li>Verify that the value placed on the bus is correctly received by the memory device on the other end </li></ul><ul><li>Test the bus one bit at a time </li></ul><ul><ul><li>Passes if each data bit can be set to 0 and 1, independently of the other data bits </li></ul></ul><ul><li>“walking 1’s test” </li></ul>
  14. 14. Data bus test <ul><li>Reduces number of test patterns from 2**n to n, where n is the width of the data bus </li></ul><ul><li>Because we are testing the data bus, all data values can be written to the same address (any address will do) </li></ul><ul><li>If data bus splits you must test one address within each chip </li></ul>
  15. 15. Data bus test <ul><li>Write the first value to memory </li></ul><ul><li>Verify it by reading it back </li></ul><ul><li>Write the second value </li></ul><ul><li>Etc </li></ul><ul><li>Ok to read back immediately (not looking for missing chips yet) </li></ul><ul><li>00000001 </li></ul><ul><li>00000010 </li></ul><ul><li>00000100 </li></ul><ul><li>00001000 </li></ul><ul><li>00010000 </li></ul><ul><li>00100000 </li></ul><ul><li>01000000 </li></ul><ul><li>10000000 </li></ul>
  16. 16. <ul><li>/******************************************************** </li></ul><ul><li>* </li></ul><ul><li>*Function: memTestDataBus() </li></ul><ul><li>* </li></ul><ul><li>*Decription: Test the data bus wiring in a memory region by </li></ul><ul><li>* performing a walking 1’s test at a fixed address </li></ul><ul><li>* within that region. The address (and hence the </li></ul><ul><li>* memory region) is selected by the caller. </li></ul><ul><li>* </li></ul><ul><li>* </li></ul><ul><li>* Returns: 0 if the test succeeds </li></ul><ul><li>* A nonzero result is the first pattern that failed </li></ul><ul><li>* </li></ul><ul><li>*********************************************************/ </li></ul><ul><li>datum </li></ul><ul><li>memTestDataBus(volatile datum * address) </li></ul><ul><li>{ </li></ul><ul><li>datum pattern; </li></ul><ul><li>/* </li></ul><ul><li>* perform a walking 1’s test at the given address </li></ul><ul><li>*/ </li></ul>
  17. 17. <ul><li>memTestDataBus(volatile datum * address) </li></ul><ul><li>{ </li></ul><ul><li>datum pattern; </li></ul><ul><li>/* </li></ul><ul><li>* perform a walking 1’s test at the given address </li></ul><ul><li>*/ </li></ul><ul><li>for (pattern = 1; pattern != 0; pattern <<= 1) </li></ul><ul><li>{ </li></ul><ul><li>/* </li></ul><ul><li>* write the test pattern </li></ul><ul><li>*/ </li></ul><ul><li>*address = pattern; </li></ul><ul><li>/* </li></ul><ul><li>* read it back (immediately is ok for this test) </li></ul><ul><li>*/ </li></ul><ul><li>if (*address != pattern) </li></ul><ul><li>{ </li></ul><ul><li>return (pattern); </li></ul><ul><li>} </li></ul>
  18. 18. <ul><li>} </li></ul><ul><li>return (0); </li></ul><ul><li>} /* memTestDataBus() */ </li></ul>
  19. 19. Address bus test <ul><li>Next test to run after confirming that the data test passes </li></ul><ul><li>Many possible addresses that could overlap </li></ul><ul><ul><li>Try to isolate each address bit during testing (like the data test) </li></ul></ul><ul><ul><li>Confirm each address pin can be set to 0 and 1 </li></ul></ul>
  20. 20. Address bus test <ul><li>Use “power of 2” address </li></ul><ul><ul><li>00001h, 00002h, 00004h, 00008h, 00010h, 00020h, etc </li></ul></ul><ul><ul><li>Also test 00000h </li></ul></ul><ul><li>Possibility of overlapping locations makes this test harder to implement </li></ul><ul><ul><li>After writing to one of the addresses, must check that none of the others have been over written </li></ul></ul>
  21. 21. Address bus test <ul><li>Not all addresses can be tested this way </li></ul><ul><ul><li>Leftmost bits select the memory chip </li></ul></ul><ul><ul><li>Rightmost bits may not be significant if data bus width greater than 8 bits </li></ul></ul><ul><ul><li>These bits will remain constant throughout the test and reduce the number of test addresses </li></ul></ul>
  22. 22. Address bus test <ul><li>Example; for 20 bit address range </li></ul><ul><ul><li>Can address 1 M of memory </li></ul></ul><ul><ul><li>128K byte block test implies three MSBs will remain constant (128K byte is 1/8 th of the total 1M address range) </li></ul></ul><ul><ul><li>Only 17 rightmost bits of the address bus can actually be tested </li></ul></ul>
  23. 23. Address bus test <ul><li>To confirm no 2 memory addresses overlap </li></ul><ul><ul><li>Write an initial data value at each power of 2 offset within the device </li></ul></ul><ul><ul><li>Write an inverted data value to the first test offset </li></ul></ul><ul><ul><li>Verify initial data value is still stored at every other power of 2 location </li></ul></ul><ul><ul><li>Problem with current address bit if any other power of 2 location is not right </li></ul></ul><ul><ul><li>Repeat for remaining offsets </li></ul></ul>
  24. 24. <ul><li>/******************************************************** </li></ul><ul><li>* </li></ul><ul><li>*Function: memTestAddressBus() </li></ul><ul><li>* </li></ul><ul><li>*Decription: Test the address bus wiring in memory region by </li></ul><ul><li>* performing a walking 1’s test on the relevant bits </li></ul><ul><li>* of the address and checking for aliasing. The </li></ul><ul><li>* base address and size of the region are selected </li></ul><ul><li>* by the user. </li></ul><ul><li>* </li></ul><ul><li>* Notes: For best results, the selected base address should </li></ul><ul><li>* enough LSB 0’s to guarantee single address bit </li></ul><ul><li>* changes (to test a 64 KB region, select a base </li></ul><ul><li>* address on a 64 KB boundary </li></ul><ul><li>* </li></ul><ul><li>* </li></ul><ul><li>* Returns: NULL if the test succeeds </li></ul><ul><li>* A nonzero result is the first address that failed </li></ul><ul><li>* </li></ul><ul><li>*********************************************************/ </li></ul><ul><li>datum * </li></ul><ul><li>memTestAddressBus(volatile datum * baseAddress, unsigned long nBytes) </li></ul><ul><li>{ </li></ul>
  25. 25. <ul><li>memTestAddressBus(volatile datum * baseAddress, unsigned long nBytes) </li></ul><ul><li>{ </li></ul><ul><li>unsigned long addressMask = (nBytes –1); </li></ul><ul><li>unsigned long offset; </li></ul><ul><li>unsigned long testOffset; </li></ul><ul><li>datum pattern = (datum) 0xAAAAAAAA; </li></ul><ul><li>datum antipattern = (datum) 0x55555555; </li></ul><ul><li>/* </li></ul><ul><li>* write the default pattern at each of the power of two offsets </li></ul><ul><li>*/ </li></ul><ul><li>for (offset = sizeof(datum); (offset & addressMask) != 0; offset <<=1) </li></ul><ul><li>{ </li></ul><ul><li>baseAddress[offset] = pattern; </li></ul><ul><li>/* </li></ul><ul><li>* check for address bits stuck high </li></ul><ul><li>*/ </li></ul><ul><li>testOffset = 0; </li></ul><ul><li>baseAddress[testOffset] = antipattern; </li></ul><ul><li>for (offset = sizeof(datum); (offset & addressMask) != 0; offset <<=1) </li></ul><ul><li>{ </li></ul>
  26. 26. <ul><li>if (baseAddress[offset] != antipattern </li></ul><ul><li>{ </li></ul><ul><li>return ((datum *) &baseAddress[offset] ); </li></ul><ul><li>} </li></ul><ul><li>} </li></ul><ul><li>baseAddress[testOffset] = pattern; </li></ul><ul><li>/* </li></ul><ul><li>* check for address bits stuck low or shorted </li></ul><ul><li>*/ </li></ul><ul><li>for (offset = sizeof(datum); (offset & addressMask) != 0; testOffset <<=1) </li></ul><ul><li>{ </li></ul><ul><li>baseAddress[testOffset] = antipattern; </li></ul><ul><li>for (offset = sizeof(datum); (offset & addressMask) != 0; offset <<=1) </li></ul><ul><li>{ </li></ul><ul><li>if ((baseAddress[offset] != pattern) && (offset != testOffset)) </li></ul><ul><li>{ </li></ul><ul><li>return ((datum *) &baseAddress[testOffset] ); </li></ul><ul><li>} </li></ul><ul><li>} </li></ul><ul><li>baseAddress[testOffset] = pattern; </li></ul><ul><li>} </li></ul><ul><li>return (NULL); </li></ul><ul><li>} /* memTestAddressBus() */ </li></ul>
  27. 27. <ul><li>baseAddress[testOffset] = pattern; </li></ul><ul><li>} </li></ul><ul><li>return (NULL); </li></ul><ul><li>} /* memTestAddressBus() */ </li></ul>
  28. 28. Device test <ul><li>Used to test the integrity of the memory device itself </li></ul><ul><li>Test every bit in device is capable of holding a 1 and a 0 </li></ul><ul><li>Easy to implement but harder to execute </li></ul><ul><li>Must write and verify every location twice </li></ul><ul><li>Any value for the first half – invert for the second half </li></ul>
  29. 29. Device test <ul><li>First do an increment test </li></ul><ul><li>Second pass is a decrement test </li></ul><ul><li>Incrementing data pattern is adequate and easy to compute </li></ul>
  30. 30. Device test 11111111 00000000 0FFh 00000000 11111111 0FEh …… . …… .. …… .. 11111011 00000100 003h 11111100 00000011 002h 11111101 00000010 001h 11111110 00000001 00h Inverted value Binary value Memory offset
  31. 31. Example <ul><li>Test the second 64K byte chunk of SRAM on an embedded device (Arcom board) </li></ul><ul><li>Recall the memory map talked about earlier; </li></ul>
  32. 32. Memory map for example EPROM (128K) Flash memory (128K) Unused Zilog SCC Unused SRAM (128K) FFFFFh E0000h C0000h 72000h 70000h 20000h 00000h 2 nd 64K byte Segment is 10000h
  33. 33. Example <ul><li>Width of data bus (80188EB) is 8 bits </li></ul><ul><li>Total of 64K bytes to be tested </li></ul><ul><ul><li>Rightmost 16 bits of address bus </li></ul></ul><ul><li>If any of the tests return nonzero value (error) then turn on red LED to indicate error (and return useful information) </li></ul><ul><li>If all tests pass turn on green LED </li></ul>
  34. 34. <ul><li>/******************************************************** </li></ul><ul><li>*Function: main() </li></ul><ul><li>* </li></ul><ul><li>*Decription: Test the 2 nd 64K byte bank of SRAM </li></ul><ul><li>* </li></ul><ul><li>* Returns: 0 on success </li></ul><ul><li>* Otherwise –1 indicates error </li></ul><ul><li>* </li></ul><ul><li>*********************************************************/ </li></ul><ul><li>main(void) </li></ul><ul><li>( </li></ul><ul><ul><li>if ((memTestDataBus(BASE_ADDRESS) != 0) || </li></ul></ul><ul><ul><li>(memTestAddressBus(BASE_ADDRESS, NUM_BYTES) != NULL || </li></ul></ul><ul><ul><li>(memTestDevice(BASE_ADDRESS, NUM_BYTES) != NULL)) </li></ul></ul><ul><ul><li>{ </li></ul></ul><ul><ul><ul><li>toggleLed(LED_RED); </li></ul></ul></ul><ul><ul><ul><li>return(-1); </li></ul></ul></ul><ul><ul><li>} </li></ul></ul><ul><ul><li>else </li></ul></ul><ul><ul><li>{ </li></ul></ul><ul><ul><ul><li>toggleLed(LED_GREEN); </li></ul></ul></ul><ul><ul><ul><li>return(0); </li></ul></ul></ul><ul><ul><li>} </li></ul></ul><ul><li>} /* main() */ </li></ul>
  35. 35. Example <ul><li>Not always possible to test memory in HOL </li></ul><ul><ul><li>C/C++ require a stack </li></ul></ul><ul><ul><li>Stack required working memory </li></ul></ul><ul><ul><li>Create stack in an area known to be working – test it from assembly </li></ul></ul><ul><li>Or, the memory test can be run from an emulator </li></ul><ul><ul><li>Place the stack in emulator memory </li></ul></ul><ul><ul><li>Move the emulator to different areas in the target memory map to test all locations </li></ul></ul>
  36. 36. Example <ul><li>Memory testing most useful during product development when design is unproven </li></ul><ul><li>Memory is so important it might make sense to always test it </li></ul><ul><ul><li>Run during power on or reset </li></ul></ul><ul><ul><li>Forms part of a hardware diagnostics </li></ul></ul>
  37. 37. Validating memory contents <ul><li>Memory tests do not make much sense for Rom devices and some hybrid devices that have programs that cannot be overwritten </li></ul><ul><li>However same memory problems can occur! </li></ul><ul><ul><li>Improper insertion, etc </li></ul></ul><ul><li>Need a confirmation for these devices as well </li></ul>
  38. 38. Validating memory contents <ul><li>Confirmation techniques </li></ul><ul><ul><li>Checksum </li></ul></ul><ul><ul><li>Cyclic redundancy checks </li></ul></ul>
  39. 39. Checksums <ul><li>Way to tell if a program stored in a non-volatile device is still good </li></ul><ul><li>Compute a checksum of the program when you know its good </li></ul><ul><ul><li>E.g. prior to programming the ROM </li></ul></ul><ul><li>Re-calculate the checksum each time you wan to verify contents are still good </li></ul><ul><ul><li>Compare to previous value </li></ul></ul>
  40. 40. Checksums <ul><li>Careful selection of the checksum algorithm can increase the probability of reducing specific types of errors </li></ul><ul><li>Simplest </li></ul><ul><ul><li>Add up all the data bytes (or words for a 16 bit checksum) </li></ul></ul><ul><ul><li>Discard the carries </li></ul></ul><ul><ul><li>If all data (including stored checksum) is overwritten with 0’s, this data corruption will be hard to detect </li></ul></ul>
  41. 41. Checksums <ul><li>Overcome this weakness by inverting the result as a final step </li></ul><ul><li>This approach still cannot detect many of the common data errors </li></ul><ul><ul><li>If one bit changed from 0 to 1 and another bit in the same column changed from 1 to 0, the algorithm would still compute the same checksum </li></ul></ul>
  42. 42. Checksums <ul><li>Where to store checksums? </li></ul><ul><ul><li>Define it as a constant in the routine that verifies the data (must compute ahead of time) </li></ul></ul><ul><ul><ul><li>Good for the programmer </li></ul></ul></ul><ul><ul><ul><li>May change many times </li></ul></ul></ul><ul><ul><li>Store in a fixed checksum in memory (like the very last location of the memory device being verified) </li></ul></ul><ul><ul><li>Store in another non-volatile device </li></ul></ul>
  43. 43. Cyclic redundancy check <ul><li>A specific checksum algorithm designed to detect the most common data errors </li></ul><ul><li>Has mathematical origins </li></ul><ul><li>Used often in embedded applications that require storage or transmission of large blocks of data </li></ul>
  44. 44. Cyclic redundancy check <ul><li>Some math; </li></ul><ul><ul><li>Consider the data to be a long string of 1’s and 0’s (called the message) </li></ul></ul><ul><ul><li>Binary string is divided by a smaller string called the generator polynomial </li></ul></ul><ul><ul><li>The remainder is the CRC checksum </li></ul></ul><ul><ul><li>Careful selection of the generator polynomial will produce a checksum that can detect most errors within a message, including up to 99.99% of all burst errors </li></ul></ul>
  45. 45. Cyclic redundancy check <ul><li>Best generator polynomials are adapted as international standards </li></ul><ul><li>Parameters of a CRC standard </li></ul><ul><ul><li>Width (in bits) </li></ul></ul><ul><ul><li>Generator polynomial </li></ul></ul><ul><ul><li>Divisor (binary representation of the polynomial) </li></ul></ul><ul><ul><li>Initial value for the remainder </li></ul></ul><ul><ul><li>Value to XOR with the final remainder </li></ul></ul>
  46. 46. Cyclic redundancy check <ul><li>Example standard; CCITT </li></ul><ul><ul><li>Checksum size (width) 16 bits </li></ul></ul><ul><ul><li>Generator polynomial; x**16 + x**12 + x**5 + 1 </li></ul></ul><ul><ul><li>Divisor (polynomial); 0x1021 </li></ul></ul><ul><ul><li>Initial remainder; 0xFFFF </li></ul></ul><ul><ul><li>Final XOR value; 0x0000 </li></ul></ul>
  47. 47. Flash memory <ul><li>Complicated from the programmers point of view </li></ul><ul><li>Reading is the same as reading from any other device (for the most part) </li></ul><ul><li>Flash devices enter a “read” mode during initialization </li></ul><ul><li>Writing is harder </li></ul><ul><ul><li>Each memory location must be erased before it is written </li></ul></ul><ul><ul><li>If not, result is some logical combo </li></ul></ul>
  48. 48. Flash memory <ul><ul><li>Only one sector, or block, can be erased at a time </li></ul></ul><ul><ul><ul><li>Cannot erase a single byte </li></ul></ul></ul><ul><ul><ul><li>Size of sector varies by device (16Kbytes) </li></ul></ul></ul><ul><ul><li>Process of erasing varies by device </li></ul></ul><ul><ul><ul><li>Usually best to add a layer (API) </li></ul></ul></ul><ul><ul><ul><li>Called the Flash driver </li></ul></ul></ul>
  49. 49. Flash driver <ul><li>Purpose is to hide the details of the chip from the software </li></ul><ul><li>Simple API </li></ul><ul><ul><li>erase </li></ul></ul><ul><ul><li>Write </li></ul></ul><ul><li>S/W calls the API </li></ul><ul><ul><li>More portable (if flash devices change) </li></ul></ul>
  50. 50. <ul><li>#include “tgt188eb.h” </li></ul><ul><li>/* </li></ul><ul><li>*Features of the AMD 29F010 flash memory device </li></ul><ul><li>*/ </li></ul><ul><li>#define FLASH_SIZE 0x20000 </li></ul><ul><li>#define FLASH_BLOCK_SIZE 0x04000 </li></ul><ul><li>#define UNLOCK1_OFFSET 0x5555 </li></ul><ul><li>#define UNLOCK2_OFFSET 0x2AAA </li></ul><ul><li>#define COMMAND_OFFSET 0x5555 </li></ul><ul><li>#define FLASH_CMD_UNLOCK1 0xAA </li></ul><ul><li>#define FLASH_CMD_UNLOCK2 0x55 </li></ul><ul><li>#define FLASH_CMD_READ_RESET 0xF0 </li></ul><ul><li>#define FLASH_CMD_AUTOSELECT 0x90 </li></ul><ul><li>#define FLASH_CMD_BYTE_PROGRAM 0xA0 </li></ul><ul><li>#define FLASH_CMD_ERASE_SETUP 0x80 </li></ul><ul><li>#define FLASH_CMD_CHIP ERASE 0x30 </li></ul><ul><li>#define FLASH_CMD_SECTOR_ERASE 0x30 </li></ul><ul><li>#define DQ7 0x80 </li></ul><ul><li>#define DQ5 0x20 </li></ul>
  51. 51. <ul><li>/********************************************************** </li></ul><ul><li>* </li></ul><ul><li>Function: flashWrite() </li></ul><ul><li>* </li></ul><ul><li>* Description; write data to consecutive locations in the flash </li></ul><ul><li>* </li></ul><ul><li>* Notes; This function is specific to the AMD 29F1020 Flash </li></ul><ul><li>* memory. In that device, a byte that has been </li></ul><ul><li>* previously written must be erased before it can be </li></ul><ul><li>* rewritten successfully </li></ul><ul><li>* </li></ul><ul><li>* Returns; Number of bytes successfully written </li></ul><ul><li>**********************************************************/ </li></ul><ul><li>int </li></ul><ul><li>flashWrite(unsigned char * baseAddress, </li></ul><ul><li>const unsigned char data[] </li></ul><ul><li>unsigned int nBYtes) </li></ul><ul><li>{ </li></ul><ul><li>unsigned char * flashBase = FLASH_BASE; </li></ul><ul><li>unsigned int offset; </li></ul><ul><li>for (offset = 0; offset < nBytes; offset++) </li></ul><ul><li>{ </li></ul>
  52. 52. /* * issue the command sequence for byte program */ flashBase[UNLOCK1_OFFSET] = FLASH_CMD_UNLOCK1; flashBase[UNLOCK2_OFFSET] = FLASH_CMD_UNLOCK2; flashBase[COMMAND_OFFSET] = FLASH_CMD_BYTE_PROGRAM; /* * perform the actual write operation */ baseAddress[offeset] = data[offset]; /* * wait for the operation to complete or time out */ while ((baseAddress[offset] & DQ7 != (data[offset] & DQ7)) && ! (baseAddress[offset] & DQ5)); if ((baseAddress[offset] & DQ7) != data[offset] & DQ7)) { break; } } return(offset); } /* flashWrite() */
  53. 53. Flash driver <ul><li>There are more robust implementations that handle errors </li></ul><ul><ul><li>The point is – this can be complicated! </li></ul></ul><ul><li>Flash can also be used as a small file system because of nonvolatility </li></ul><ul><li>API can handle this as well </li></ul><ul><ul><li>Open </li></ul></ul><ul><ul><li>Close </li></ul></ul><ul><ul><li>Read </li></ul></ul><ul><ul><li>write </li></ul></ul>
  54. 54. SE 746-NT Embedded Software Systems Development Robert Oshana End of Lecture For more information, please contact: NTU Tape Orders: NTU Media Services: (970) 495-6455 [email_address] [email_address]