15 #include <epicsStdio.h> 16 #include <epicsThread.h> 35 epicsUInt8 cmd[7] = {0x9f, 0u, 0u, 0u},
40 ops[0].
out = response;
57 id->vendor = response[1];
58 id->dev_type = response[2];
59 id->dev_id = response[3];
61 id->vendorName =
"<Unknown>";
62 id->capacity =
id->sectorSize =
id->pageSize = 0u;
69 id->vendorName =
"Micron";
73 id->capacity = 1u<<(
id->dev_id);
74 id->sectorSize = 256*1024u;
79 id->capacity = 1u<<(
id->dev_id);
80 id->sectorSize = 64*1024u;
99 id->SN.resize(response[4]-2);
100 ops[1].
ncycles =
id->SN.size();
102 ops[1].
out = &
id->SN[0];
111 if((response[5]&0x3)!=0) {
121 id->capacity = 0x1000000;
126 if((start&0xff000000) || (count&0xff000000) || ((start+count)&0xff000000))
127 std::runtime_error(
"start/count exceeds 24-bit addressing");
136 cmd[1] = (start>>16)&0xff;
137 cmd[2] = (start>> 8)&0xff;
138 cmd[3] = (start>> 0)&0xff;
158 const epicsUInt32 count,
159 const epicsUInt8 *
const data,
162 if((start&0xff000000) || (count&0xff000000) || ((start+count)&0xff000000))
163 std::runtime_error(
"start/count exceeds 24-bit addressing");
168 throw std::runtime_error(
"Won't attempt to write when capacity isn't known");
171 throw std::runtime_error(
"Can't write beyond capacity");
174 throw std::runtime_error(
"Won't attempt to write to unsupported flash chip");
179 throw std::runtime_error(
"start address not aligned to page & sector sizes");
181 if(strict && ((start+count)&mask))
182 throw std::runtime_error(
"end address not aligned to page & sector sizes");
185 const epicsUInt32 end = start+count;
190 WriteEnabler WE(*
this);
202 cmd[1] = (
addr>>16)&0xff;
203 cmd[2] = (
addr>> 8)&0xff;
204 cmd[3] = (
addr>> 0)&0xff;
215 const epicsUInt8 *cur = data;
226 cmd[1] = (
addr>>16)&0xff;
227 cmd[2] = (
addr>> 8)&0xff;
228 cmd[3] = (
addr>> 0)&0xff;
252 std::vector<epicsUInt8> scratch;
254 const epicsUInt8 *cur = data;
264 if(memcmp(cur, &scratch[0], N)!=0) {
265 printf(
"FLASH readback mis-match in sector 0x%06x\n", (
unsigned)
addr);
271 throw std::runtime_error(
"FLASH readback error");
276 if((start&0xff000000) || (count&0xff000000) || ((start+count)&0xff000000))
277 std::runtime_error(
"start/count exceeds 24-bit addressing");
282 throw std::runtime_error(
"Won't attempt to write when capacity isn't known");
285 throw std::runtime_error(
"Can't write beyond capacity");
288 throw std::runtime_error(
"Won't attempt to write to unsupported flash chip");
293 throw std::runtime_error(
"start address not aligned to page & sector sizes");
295 if(strict && ((start+count)&mask))
296 throw std::runtime_error(
"end address not aligned to page & sector sizes");
299 const epicsUInt32 end = start+count;
303 WriteEnabler WE(*
this);
315 cmd[1] = (
addr>>16)&0xff;
316 cmd[2] = (
addr>> 8)&0xff;
317 cmd[3] = (
addr>> 0)&0xff;
327 void CFIFlash::check()
337 throw std::runtime_error(
"Invalid Flash vendor ID");
340 unsigned CFIFlash::status()
342 epicsUInt8 cmd[2] = {0x05, 0}, response[2] = {0,0};
348 return response[1]&0x03;
351 void CFIFlash::writeEnable(
bool e)
353 epicsUInt8 cmd = e ? 0x06 : 0x04;
360 void CFIFlash::busyWait(
double timeout,
unsigned n)
364 while(T.
ok() && (status()&1))
365 epicsThreadSleep(T.
inc());
368 throw std::runtime_error(
"Timeout waiting for operation to complete");
380 flash.
read(pos, buf.size(), (epicsUInt8*)&buf[0]);
381 setg(&buf[0], &buf[0], &buf[buf.size()]);
387 CFIStreamBuf::pos_type
390 if(dir==std::ios_base::cur)
392 else if(dir==std::ios_base::end)
397 CFIStreamBuf::pos_type
401 setg(&buf[0], &buf[0], &buf[0]);
407 static const char header[] =
"\0\x09\x0f\xf0\x0f\xf0\x0f\xf0\x0f\xf0\0\0\1";
409 std::vector<char> buf(
sizeof(header)-1);
411 if(strm.read(&buf[0], buf.size()).gcount()!=std::streamsize(buf.size()) || !std::equal(buf.begin(), buf.end(), header))
414 std::string project, part, date, time;
421 if(strm.read((
char*)&
id, 1).gcount()==0)
429 if(strm.read((
char*)&size, 2).gcount()!=2)
430 throw std::runtime_error(
"Truncated block header");
433 if(strm.read(&buf[0], buf.size()).gcount()!=std::streamsize(buf.size()))
434 throw std::runtime_error(
"Truncated block payload");
446 fprintf(stderr,
"Warning: attempting to ignore unknown block 0x%02x\n",
unsigned(
id));
451 std::string str(&buf[0]);
454 case 0x61: project.swap(str);
break;
455 case 0x62: part.swap(str);
break;
456 case 0x63: date.swap(str);
break;
457 case 0x64: time.swap(str);
break;
464 this->project.swap(project);
465 this->part.swap(part);
466 this->date.swap(date);
virtual int_type underflow() OVERRIDE FINAL
epicsUInt32 pageSize
PAGE PROGRAM (0x02) size in bytes. Always a power of 2.
void readID(ID *id)
execute command 0x9f JEDEC-ID read
double timeout() const
timeout in seconds for an individual cycle()
CFIFlash(const SPIDevice &dev)
virtual void cycles(size_t nops, const Operation *ops)
virtual pos_type seekpos(pos_type pos, std::ios_base::openmode mode) OVERRIDE FINAL
epicsUInt32 capacity
total capacity in bytes
Handling for Common Flash Interfafce compliant chips.
epicsUInt32 sectorSize
SECTOR ERASE (0xd8) size in bytes. Always a power of 2.
SPIInterface * interface() const
bool read(std::istream &strm)
void write(epicsUInt32 start, epicsUInt32 count, const epicsUInt8 *out, bool strict=true)
CFIStreamBuf(CFIFlash &flash)
void erase(epicsUInt32 start, epicsUInt32 count, bool strict=true)
void read(epicsUInt32 start, epicsUInt32 count, epicsUInt8 *in)
virtual pos_type seekoff(off_type off, std::ios_base::seekdir dir, std::ios_base::openmode mode) OVERRIDE FINAL