10 #include "epicsUnitTest.h" 11 #include "epicsString.h" 21 testDiag(
"testTimeout()");
26 testOk1(C.inc()==0.0);
27 testOk1(C.sofar()==0.0);
30 testOk1(C.inc()==0.1);
31 testOk(fabs(C.sofar()-0.1)<0.001,
"%f == 0.1", C.sofar());
34 testOk1(C.inc()==0.2);
35 testOk(fabs(C.sofar()-0.3)<0.001,
"%f == 0.3", C.sofar());
38 testOk1(C.inc()==0.4);
39 testOk(fabs(C.sofar()-0.7)<0.001,
"%f == 0.7", C.sofar());
42 testOk1(C.inc()==0.8);
43 testOk(fabs(C.sofar()-1.5)<0.001,
"%f == 1.5", C.sofar());
65 std::vector<epicsUInt8> ram;
67 TestDevice() :current(Idle), command(0), count(0), address(0), status(0), selected(false), WE(false) {}
69 virtual void select(
unsigned id)
71 testDiag(
"select %u",
id);
93 virtual epicsUInt8
cycle(epicsUInt8 in)
97 if(!selected)
throw std::logic_error(
"cycle() when not selected");
99 if((status&1) && current==Idle && in!=0x05)
100 throw std::logic_error(
"Only READ STATUS allowed while busy");
107 testDiag(
"Write Disable");
112 testDiag(
"Write Enable");
120 throw std::logic_error(
"Can't erase/program when !WE");
131 throw std::logic_error(
"Unknown command");
136 case 0: address = epicsUInt32(in)<<16;
break;
137 case 1: address |= epicsUInt32(in)<<8;
break;
139 address |= epicsUInt32(in)<<0;
145 testDiag(
"Erase sector %06x", (
unsigned)address);
147 for(epicsUInt32 cur=address, end=address+64*1024u; cur<end && cur<ram.size(); cur++)
152 testDiag(
"program page %06x", (
unsigned)address);
166 throw std::logic_error(
"Can't program more than one page");
168 if(address>=ram.size())
169 ram.resize(address+1, 0xff);
171 if(ram[address]!=0xff)
172 throw std::logic_error(
"Write w/ erase");
177 }
else if(command==0x05) {
178 epicsUInt8 ret = status;
180 testDiag(
"status -> %02x", ret);
183 }
else if(command==0x0b) {
185 if(address<ram.size())
186 return ram[address++];
188 }
else if(command==0x9f) {
200 case 10:
return 0x04;
201 case 11:
return 0x05;
202 case 12:
return 0x06;
203 case 13:
return 0x07;
204 case 14:
return 0x08;
205 case 15:
return 0x09;
206 case 16:
return 0x0a;
207 case 17:
return 0x0b;
208 case 18:
return 0x0c;
209 case 19:
return 0x0d;
210 case 20:
return 0x0e;
215 throw std::logic_error(
"Cycle during bad state");
224 testDiag(
"testReadID()");
234 testOk1(info.
vendor==0x20);
236 testOk1(info.
dev_id==0x17);
238 testOk1(info.
capacity==8*1024*1024);
245 testDiag(
"testRead");
249 iface.ram.resize(128);
250 for(
size_t i=0; i<iface.ram.size(); i++)
251 iface.ram[i] = i|0x80;
257 testDiag(
"Read one");
260 mem.read(0, 1, &val);
264 mem.read(0x23, 1, &val);
268 mem.read(0x256, 1, &val);
274 testDiag(
"Read many");
278 testOk1(val[0]==0x80);
279 testOk1(val[1]==0x81);
280 testOk1(val[2]==0x82);
281 testOk1(val[3]==0x83);
282 testOk1(val[4]==0x84);
283 testOk1(val[5]==0x85);
284 testOk1(val[6]==0x86);
285 testOk1(val[7]==0x87);
287 mem.read(16, 8, val);
288 testOk1(val[0]==0x90);
289 testOk1(val[1]==0x91);
290 testOk1(val[2]==0x92);
291 testOk1(val[3]==0x93);
292 testOk1(val[4]==0x94);
293 testOk1(val[5]==0x95);
294 testOk1(val[6]==0x96);
295 testOk1(val[7]==0x97);
301 static const epicsUInt8 helloworld[] =
"helloworld";
302 static const epicsUInt8 thisisatest[] =
"thisisatest";
303 testDiag(
"testWrite()");
309 testDiag(
"Write one page");
311 mem.write(0, 10, helloworld,
false);
313 testOk(iface.ram.size()==10,
"%zu == 10", iface.ram.size());
315 testOk1(memcmp(helloworld, &iface.ram[0], 10)==0);
317 testDiag(
"Write one page");
319 mem.write(2*64*1024, 11, thisisatest,
false);
321 testOk(iface.ram.size()==2*64*1024 + 11,
"%zu == 64kb + 11", iface.ram.size());
323 testOk1(memcmp(helloworld, &iface.ram[0], 10)==0);
324 testOk1(iface.ram[10]==0xff);
325 testOk1(iface.ram[2*64*1024 - 1]==0xff);
326 testOk1(memcmp(thisisatest, &iface.ram[2*64*1024], 11)==0);
328 testDiag(
"Write many pages");
330 std::vector<epicsUInt8> bigbuf(6*64*1024);
331 for(epicsUInt32 i=0, cnt=0; i<bigbuf.size(); i+=4, cnt++)
333 bigbuf[i+0] = cnt>>24;
334 bigbuf[i+1] = cnt>>16;
335 bigbuf[i+2] = cnt>> 8;
336 bigbuf[i+3] = cnt>> 0;
339 mem.write(0, bigbuf,
true);
341 testOk(iface.ram.size()==bigbuf.size(),
"%zu == %zu", iface.ram.size(), bigbuf.size());
344 for(
size_t i=0,
N=std::min(iface.ram.size(), bigbuf.size()); i<
N; i++)
346 bool ok = iface.ram[i]==bigbuf[i];
352 static const char xiheader[] =
"\x00\t\x0f\xf0\x0f\xf0\x0f\xf0\x0f\xf0\x00\x00\x01""a\x00/" 355 "rsion=2017.4.1\x00""b" 356 "\x00\r7k325tfbg900\x00""c" 357 "\x00\x0b""2018/07/23\x00""d\x00\t" 358 "08:57:10\x00""e\x00\xae\x9d\x9c\xff\xff";
362 testDiag(
"testStream()");
368 mem.write(0,
sizeof(xiheader)-1, (
const epicsUInt8*)xiheader,
false);
371 std::istream strm(&sbuf);
373 std::vector<char> cbuf(13);
375 testOk(strm.read(&cbuf[0], cbuf.size()).gcount()==std::streamsize(cbuf.size()),
376 "read %u == %u",
unsigned(strm.gcount()),
unsigned(cbuf.size()));
377 testOk1(!!strm.good());
378 testOk1(!!std::equal(cbuf.begin(), cbuf.end(), xiheader));
383 testOk1(!!strm.good());
384 testOk(strm.tellg()==0,
"tell -> %d", int(strm.tellg()));
387 std::fill(cbuf.begin(), cbuf.end(), 0);
389 testOk(strm.read(&cbuf[0], 6).gcount()==6,
390 "read %u == %u", unsigned(strm.gcount()), 6);
391 testOk1(!!strm.good());
392 testOk(strm.read(&cbuf[6], 7).gcount()==7,
393 "read %u == %u", unsigned(strm.gcount()), 7);
394 testOk1(!!strm.good());
395 testOk1(!!std::equal(cbuf.begin(), cbuf.end(), xiheader));
400 testDiag(
"testXilinx()");
402 std::istringstream strm(std::string(xiheader,
sizeof(xiheader)-1));
405 testOk1(!!info.
read(strm));
406 testOk(info.
project==
"mtcaeevm300;UserID=0XFFFFFFFF;Version=2017.4.1",
407 "project='%s'", info.
project.c_str());
408 testOk(info.
part==
"7k325tfbg900",
409 "part='%s'", info.
part.c_str());
410 testOk(info.
date==
"2018/07/23 08:57:10",
411 "date='%s'", info.
date.c_str());
426 }
catch(std::exception& e){
427 testAbort(
"Exception %s", e.what());
epicsUInt32 pageSize
PAGE PROGRAM (0x02) size in bytes. Always a power of 2.
virtual epicsUInt8 cycle(epicsUInt8 in)=0
epicsUInt32 capacity
total capacity in bytes
Attempt to read out the header of a Xilinx bitstream file.
Handling for Common Flash Interfafce compliant chips.
epicsUInt32 sectorSize
SECTOR ERASE (0xd8) size in bytes. Always a power of 2.
bool read(std::istream &strm)
virtual void select(unsigned id)=0
Select numbered device. 0 clears selection.
Interface for SPI Master.
Adapt CFIFlash for use with std::istream.