VirtualBox

source: vbox/trunk/src/VBox/Devices/Network/testcase/tstDevEEPROM.cpp@ 31880

最後變更 在這個檔案從31880是 31880,由 vboxsync 提交於 14 年 前

export some testcases to OSE

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 12.8 KB
 
1/* $Id: tstDevEEPROM.cpp 31880 2010-08-24 07:08:41Z vboxsync $ */
2/** @file
3 * EEPROM 93C46 unit tests.
4 */
5
6/*
7 * Copyright (C) 2007-2010 Oracle Corporation
8 *
9 * Oracle Corporation confidential
10 * All rights reserved
11 */
12
13#include <cppunit/ui/text/TestRunner.h>
14#include <cppunit/extensions/HelperMacros.h>
15
16#include "../DevEEPROM.h"
17
18static const uint16_t initialContent[] = {
19 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
20 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
21 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
22 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
23 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
24 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
25 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
26 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f
27};
28
29/**
30 * Test fixture for 93C46-compatible EEPROM device emulation.
31 */
32class EEPROMTest : public CppUnit::TestFixture {
33 CPPUNIT_TEST_SUITE( EEPROMTest );
34
35 CPPUNIT_TEST( testRead );
36 CPPUNIT_TEST( testSequentialRead );
37 CPPUNIT_TEST( testWrite );
38 CPPUNIT_TEST( testWriteAll );
39 CPPUNIT_TEST( testWriteDisabled );
40 CPPUNIT_TEST( testErase );
41 CPPUNIT_TEST( testEraseAll );
42
43 CPPUNIT_TEST_SUITE_END();
44
45private:
46 enum Wires { DO=8, DI=4, CS=2, SK=0x01 };
47 enum OpCodes {
48 READ_OPCODE = 0x6,
49 WRITE_OPCODE = 0x5,
50 ERASE_OPCODE = 0x7,
51 EWDS_OPCODE = 0x10, // erase/write disable
52 WRAL_OPCODE = 0x11, // write all
53 ERAL_OPCODE = 0x12, // erase all
54 EWEN_OPCODE = 0x13 // erase/write enable
55 };
56 enum BitWidths {
57 READ_OPCODE_BITS = 3,
58 WRITE_OPCODE_BITS = 3,
59 ERASE_OPCODE_BITS = 3,
60 EWDS_OPCODE_BITS = 5,
61 WRAL_OPCODE_BITS = 5,
62 ERAL_OPCODE_BITS = 5,
63 EWEN_OPCODE_BITS = 5,
64 READ_ADDR_BITS = 6,
65 WRITE_ADDR_BITS = 6,
66 ERASE_ADDR_BITS = 6,
67 EWDS_ADDR_BITS = 4,
68 WRAL_ADDR_BITS = 4,
69 ERAL_ADDR_BITS = 4,
70 EWEN_ADDR_BITS = 4,
71 DATA_BITS = 16
72 };
73
74 EEPROM93C46 *eeprom;
75
76 // Helper methods
77 void shiftOutBits(uint16_t data, uint16_t count);
78 uint16_t shiftInBits(uint16_t count);
79 void getReady();
80 void standby();
81 void stop();
82 uint16_t readAt(uint16_t addr);
83 bool writeTo(uint16_t addr, uint16_t value);
84 void writeOpAddr(int opCode, int opCodeBits, uint16_t addr, int addrBits);
85 void writeData(uint16_t value) { shiftOutBits(value, DATA_BITS); }
86 bool waitForCompletion();
87
88public:
89 void setUp()
90 {
91 eeprom = new EEPROM93C46;
92 eeprom->init(initialContent);
93 }
94
95 void tearDown()
96 {
97 delete eeprom;
98 }
99
100 void testSize()
101 {
102 CPPUNIT_ASSERT_EQUAL( sizeof(initialContent), (size_t)EEPROM93C46::SIZE );
103 }
104
105 void testRead()
106 {
107 getReady();
108 for ( uint32_t wordAddr=0; wordAddr < EEPROM93C46::SIZE; wordAddr++ ) {
109 shiftOutBits(READ_OPCODE, READ_OPCODE_BITS);
110 shiftOutBits(wordAddr, READ_ADDR_BITS);
111
112 CPPUNIT_ASSERT_EQUAL( initialContent[wordAddr], (uint16_t)wordAddr );
113 CPPUNIT_ASSERT_EQUAL( initialContent[wordAddr], shiftInBits(DATA_BITS) );
114 standby();
115 }
116 stop();
117 }
118
119 void testSequentialRead()
120 {
121 getReady();
122 shiftOutBits(READ_OPCODE, READ_OPCODE_BITS);
123 shiftOutBits(0, READ_ADDR_BITS);
124 for ( int wordAddr=0; wordAddr < EEPROM93C46::SIZE; wordAddr++ ) {
125 CPPUNIT_ASSERT_EQUAL( initialContent[wordAddr], shiftInBits(DATA_BITS) );
126 }
127 stop();
128 }
129
130 void testWrite()
131 {
132 //unused: int i;
133 uint16_t wordAddr;
134
135 getReady();
136 // Enable write
137 writeOpAddr(EWEN_OPCODE, EWEN_OPCODE_BITS, 0, EWEN_ADDR_BITS);
138 standby();
139
140 for ( wordAddr=0; wordAddr < EEPROM93C46::SIZE; wordAddr++ ) {
141 //writeOpAddr(WRITE_OPCODE, WRITE_OPCODE_BITS, (uint16_t)wordAddr, WRITE_ADDR_BITS);
142 writeTo(wordAddr, 0x3F00 - (wordAddr<<8));
143 standby();
144
145 if (!waitForCompletion()) {
146 CPPUNIT_FAIL("EEPROM write was not completed");
147 stop();
148 return;
149 }
150 standby();
151 }
152
153 // Disable write
154 writeOpAddr(EWDS_OPCODE, EWDS_OPCODE_BITS, 0, EWDS_ADDR_BITS);
155
156 stop();
157
158 // Now check the result
159 getReady();
160 writeOpAddr(READ_OPCODE, READ_OPCODE_BITS, 0, READ_ADDR_BITS);
161 for ( wordAddr=0; wordAddr < EEPROM93C46::SIZE; wordAddr++ ) {
162 CPPUNIT_ASSERT_EQUAL((uint16_t)(0x3F00 - (wordAddr<<8)), shiftInBits(DATA_BITS) );
163 }
164 stop();
165 }
166
167 void testWriteDisabled()
168 {
169 getReady();
170
171 uint16_t addr = 0;
172 uint16_t oldValue = readAt(addr);
173 stop();
174 getReady();
175 if (writeTo(addr, ~oldValue)) {
176 // Write appears to be successful -- continue
177 CPPUNIT_ASSERT_EQUAL(oldValue, readAt(addr));
178 }
179 else {
180 CPPUNIT_FAIL("EEPROM write was not completed");
181 }
182 stop();
183 }
184
185 void testErase()
186 {
187 int i;
188 uint16_t addr = 0x1F;
189
190 getReady();
191 // Enable write
192 shiftOutBits(EWEN_OPCODE, EWEN_OPCODE_BITS);
193 shiftOutBits(0, EWEN_ADDR_BITS);
194 standby();
195
196 if (writeTo(addr, addr)) {
197 stop();
198 getReady();
199 // Write successful -- continue
200 CPPUNIT_ASSERT_EQUAL(addr, readAt(addr));
201 stop();
202 getReady();
203
204 shiftOutBits(ERASE_OPCODE, ERASE_OPCODE_BITS);
205 shiftOutBits(addr, ERASE_ADDR_BITS);
206
207 standby();
208
209 for (i = 0; i < 200; i++) {
210 if (eeprom->read() & DO)
211 break;
212 //usec_delay(50);
213 }
214
215 if (i == 200) {
216 CPPUNIT_FAIL("EEPROM erase was not completed");
217 stop();
218 return;
219 }
220
221 standby();
222
223 shiftOutBits(EWDS_OPCODE, EWDS_OPCODE_BITS);
224 shiftOutBits(0, EWDS_ADDR_BITS);
225
226 stop();
227 getReady();
228 CPPUNIT_ASSERT_EQUAL((uint16_t)0xFFFF, readAt(addr));
229 }
230 else {
231 CPPUNIT_FAIL("EEPROM write was not completed");
232 }
233 stop();
234 }
235
236 void testWriteAll()
237 {
238 uint16_t addr;
239
240 getReady();
241 // Enable write
242 writeOpAddr(EWEN_OPCODE, EWEN_OPCODE_BITS, 0, EWEN_ADDR_BITS);
243 standby();
244 // Fill all memory
245 writeOpAddr(WRAL_OPCODE, WRAL_OPCODE_BITS, 0, WRAL_ADDR_BITS);
246 writeData(0xABBA);
247 standby();
248
249 if (waitForCompletion()) {
250 stop();
251 getReady();
252 // Write successful -- verify all memory
253 for ( addr=0; addr < EEPROM93C46::SIZE; addr++ ) {
254 CPPUNIT_ASSERT_EQUAL((uint16_t)0xABBA, readAt(addr));
255 }
256 }
257 else {
258 CPPUNIT_FAIL("EEPROM write was not completed");
259 }
260 stop();
261 }
262
263 void testEraseAll()
264 {
265 //unused: int i;
266 uint16_t addr = 0x1F;
267
268 getReady();
269 // Enable write
270 writeOpAddr(EWEN_OPCODE, EWEN_OPCODE_BITS, 0, EWEN_ADDR_BITS);
271 standby();
272 // Fill all memory
273 writeOpAddr(WRITE_OPCODE, WRITE_OPCODE_BITS, addr, WRITE_ADDR_BITS);
274 writeData(0);
275 standby();
276
277 if (waitForCompletion()) {
278 stop();
279 getReady();
280 // Write successful -- verify random location
281 CPPUNIT_ASSERT_EQUAL((uint16_t)0, readAt(addr));
282 stop();
283 getReady();
284
285 writeOpAddr(ERAL_OPCODE, ERAL_OPCODE_BITS, addr, ERAL_ADDR_BITS);
286 standby();
287
288 if (!waitForCompletion()) {
289 CPPUNIT_FAIL("EEPROM erase was not completed");
290 stop();
291 return;
292 }
293
294 standby();
295
296 writeOpAddr(EWDS_OPCODE, EWDS_OPCODE_BITS, 0, EWDS_ADDR_BITS);
297 stop();
298
299 getReady();
300 for ( addr=0; addr < EEPROM93C46::SIZE; addr++ ) {
301 CPPUNIT_ASSERT_EQUAL((uint16_t)0xFFFF, readAt(addr));
302 }
303 }
304 else {
305 CPPUNIT_FAIL("EEPROM write was not completed");
306 }
307 stop();
308 }
309};
310
311/**
312 * shiftOutBits - Shift data bits our to the EEPROM
313 * @hw: pointer to the EEPROM object
314 * @data: data to send to the EEPROM
315 * @count: number of bits to shift out
316 *
317 * We need to shift 'count' bits out to the EEPROM. So, the value in the
318 * "data" parameter will be shifted out to the EEPROM one bit at a time.
319 * In order to do this, "data" must be broken down into bits.
320 **/
321void EEPROMTest::shiftOutBits(uint16_t data, uint16_t count) {
322 uint32_t wires = eeprom->read();
323 uint32_t mask;
324
325 mask = 0x01 << (count - 1);
326 wires &= ~DO;
327
328 do {
329 wires &= ~DI;
330
331 if (data & mask)
332 wires |= DI;
333
334 eeprom->write(wires);
335
336 // Raise clock
337 eeprom->write(wires |= SK);
338 // Lower clock
339 eeprom->write(wires &= ~SK);
340
341 mask >>= 1;
342 } while (mask);
343
344 wires &= ~DI;
345 eeprom->write(wires);
346}
347
348/**
349 * shiftInBits - Shift data bits in from the EEPROM
350 * @count: number of bits to shift in
351 *
352 * In order to read a register from the EEPROM, we need to shift 'count' bits
353 * in from the EEPROM. Bits are "shifted in" by raising the clock input to
354 * the EEPROM (setting the SK bit), and then reading the value of the data out
355 * "DO" bit. During this "shifting in" process the data in "DI" bit should
356 * always be clear.
357 **/
358uint16_t EEPROMTest::shiftInBits(uint16_t count)
359{
360 uint32_t wires;
361 uint32_t i;
362 uint16_t data;
363
364 wires = eeprom->read();
365
366 wires &= ~(DO | DI);
367 data = 0;
368
369 for (i = 0; i < count; i++) {
370 data <<= 1;
371 // Raise clock
372 eeprom->write(wires |= SK);
373
374 wires = eeprom->read();
375
376 wires &= ~DI;
377 if (wires & DO)
378 data |= 1;
379
380 // Lower clock
381 eeprom->write(wires &= ~SK);
382 }
383
384 return data;
385}
386
387/**
388 * getReady - Prepares EEPROM for read/write
389 *
390 * Setups the EEPROM for reading and writing.
391 **/
392void EEPROMTest::getReady()
393{
394 unsigned wires = eeprom->read();
395 /* Clear SK and DI */
396 eeprom->write(wires &= ~(DI | SK));
397 /* Set CS */
398 eeprom->write(wires | CS);
399}
400
401/**
402 * standby - Return EEPROM to standby state
403 *
404 * Return the EEPROM to a standby state.
405 **/
406void EEPROMTest::standby()
407{
408 unsigned wires = eeprom->read();
409
410 eeprom->write(wires &= ~(CS | SK));
411
412 // Raise clock
413 eeprom->write(wires |= SK);
414
415 // Select EEPROM
416 eeprom->write(wires |= CS);
417
418 // Lower clock
419 eeprom->write(wires &= ~SK);
420}
421
422/**
423 * stop - Terminate EEPROM command
424 *
425 * Terminates the current command by inverting the EEPROM's chip select pin.
426 **/
427void EEPROMTest::stop()
428{
429 unsigned wires = eeprom->read();
430
431 eeprom->write(wires &= ~(CS | DI));
432 // Raise clock
433 eeprom->write(wires |= SK);
434 // Lower clock
435 eeprom->write(wires &= ~SK);
436}
437
438/**
439 * readAt - Read a word at specified address
440 * @addr: address to read
441 *
442 * Returns the value of the word specified in 'addr' parameter.
443 **/
444uint16_t EEPROMTest::readAt(uint16_t addr)
445{
446 getReady();
447 shiftOutBits(READ_OPCODE, READ_OPCODE_BITS);
448 shiftOutBits(addr, READ_ADDR_BITS);
449
450 uint16_t value = shiftInBits(DATA_BITS);
451 stop();
452
453 return value;
454}
455
456/**
457 * writeTo - Write a word to specified address
458 * @addr: address to write to
459 * @value: value to store
460 *
461 * Returns false if write did not complete.
462 *
463 * Note: Make sure EEPROM is selected and writable before attempting
464 * to write. Use getReady() and stop() to select/deselect
465 * EEPROM.
466 **/
467bool EEPROMTest::writeTo(uint16_t addr, uint16_t value)
468{
469 writeOpAddr(WRITE_OPCODE, WRITE_OPCODE_BITS, addr, WRITE_ADDR_BITS);
470 writeData(value);
471 standby();
472 return waitForCompletion();
473}
474
475
476/**
477 * waitForCompletion - Wait until EEPROM clears the busy bit
478 *
479 * Returns false if the EEPROM is still busy.
480 */
481bool EEPROMTest::waitForCompletion() {
482 for (int i = 0; i < 200; i++) {
483 if (eeprom->read() & DO) {
484 standby();
485 return true;
486 }
487 // Wait 50 usec;
488 }
489
490 return false;
491}
492
493/**
494 * writeOpAddr - Write an opcode and address
495 * @opCode: operation code
496 * @opCodeBits: number of bits in opCode
497 * @addr: address to write to
498 * @addrBits: number of bits in address
499 **/
500void EEPROMTest::writeOpAddr(int opCode, int opCodeBits, uint16_t addr, int addrBits)
501{
502 shiftOutBits(opCode, opCodeBits);
503 shiftOutBits(addr, addrBits);
504}
505
506// Create text test runner and run all tests.
507int main( int argc, char **argv)
508{
509 CppUnit::TextUi::TestRunner runner;
510 runner.addTest( EEPROMTest::suite() );
511 return runner.run() ? 0 : 1;
512}
513
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette