mrfioc2  2.3.0
flashiocsh.cpp
Go to the documentation of this file.
1 /*************************************************************************\
2 * Copyright (c) 2017 Michael Davidsaver
3 * mrfioc2 is distributed subject to a Software License Agreement found
4 * in file LICENSE that is included with this distribution.
5 \*************************************************************************/
6 
7 #include <stdexcept>
8 #include <vector>
9 #include <fstream>
10 #include <iostream>
11 
12 #include <stdlib.h>
13 #include <stdio.h>
14 #include <errno.h>
15 #include <string.h>
16 
17 #include <iocsh.h>
18 #include <epicsThread.h>
19 #include <epicsStdio.h>
20 
21 // defines macros for printf() so that output is captured
22 // for iocsh when redirecting to file.
23 #include <epicsStdio.h>
24 
25 #include "mrfCommon.h"
26 #include "mrf/spi.h"
27 #include "mrf/flash.h"
28 
29 #include <epicsExport.h>
30 
31 extern "C" {
33 }
34 
35 extern "C" {
36 void flashinfo(const char *name)
37 {
38  try {
39  mrf::SPIDevice dev;
40  if(!mrf::SPIDevice::lookupDev(name, &dev)) {
41  printf("No such device");
42  return;
43  }
44 
45  mrf::CFIFlash mem(dev);
46 
47  mrf::CFIFlash::ID info;
48 
49  mem.readID(&info);
50 
51  printf("Vendor: %02x (%s)\nDevice: %02x\nID: %02x\n",
52  info.vendor, info.vendorName, info.dev_type, info.dev_id);
53  if(info.capacity)
54  printf("Capacity: 0x%x\n", (unsigned)info.capacity);
55  if(info.sectorSize)
56  printf("Sector: 0x%x\n", (unsigned)info.sectorSize);
57  if(info.pageSize)
58  printf("Page: 0x%x\n", (unsigned)info.pageSize);
59  if(!info.SN.empty()) {
60  printf("S/N: ");
61  for(size_t i=0; i<info.SN.size(); i++)
62  printf(" %02x", unsigned(info.SN[i]));
63  printf("\n");
64  }
65 
66  if(!info.capacity || !info.sectorSize || !info.pageSize) {
67  printf("Warning: Some information about this flash chip is not known.\n"
68  " Please open an issue and include this output of flashinfo()\n"
69  " and if known the flash chip vendor and part number.\n"
70  " https://github.com/epics-modules/mrfioc2/issues\n");
71  }
72 
73  {
74  mrf::CFIStreamBuf sbuf(mem);
75  std::istream strm(&sbuf);
76  mrf::XilinxBitInfo image;
77  if(image.read(strm)) {
78  printf("Bit Stream found\n Project: %s\n Part: %s\n Build: %s\n",
79  image.project.c_str(), image.part.c_str(), image.date.c_str());
80  }
81  }
82 
83  }catch(std::exception& e){
84  printf("Error: %s\n", e.what());
85  }
86 }
87 }
88 
89 extern "C" {
90 void flashread(const char *name, int addrraw, int countraw, const char *outfile)
91 {
92  try {
93  mrf::SPIDevice dev;
94  if(!mrf::SPIDevice::lookupDev(name, &dev)) {
95  printf("No such device");
96  return;
97  }
98  epicsUInt32 addr = addrraw, count = countraw;
99 
100  mrf::CFIFlash mem(dev);
101 
102  std::ostream *strm = &std::cout;
103  std::ofstream fstrm;
104  if(outfile) {
105  fstrm.open(outfile, std::ios_base::out|std::ios_base::binary);
106  if(fstrm.fail())
107  throw std::runtime_error("Unable to open output file");
108  strm = &fstrm;
109  }
110 
111  while(count) {
112  const epicsUInt32 N = std::min(count, mem.blockSize());
113  std::vector<epicsUInt8> buf(N);
114 
115  mem.read(addr, buf);
116 
117  if(outfile) {
118  (*strm).write((const char*)&buf[0], buf.size());
119 
120  } else {
121  for(size_t i=0; i<buf.size(); i++) {
122  printf("%02x", int(buf[i]));
123  if(i%16==15)
124  printf("\n");
125  else if(i%4==3)
126  printf(" ");
127  }
128  }
129 
130  addr += N;
131  count -= N;
132  if(outfile)
133  printf("| %u\n", unsigned(count));
134  }
135 
136  printf("\nDone\n");
137 
138  }catch(std::exception& e){
139  printf("Error: %s\n", e.what());
140  }
141 }
142 }
143 
144 extern "C" {
145 void flashwrite(const char *name, int addrraw, const char *infile)
146 {
147  if(!infile || infile[0]=='\0') {
148  printf("Usage: flashwrite <name> <start_address> <filename>\n");
149  return;
150  }
151 
152  try {
153  mrf::SPIDevice dev;
154  if(!mrf::SPIDevice::lookupDev(name, &dev)) {
155  printf("No such device");
156  return;
157  }
158  epicsUInt32 addr = addrraw;
159 
160  mrf::CFIFlash mem(dev);
161  if(!mem.writable()) {
162  printf("Device not writable\n");
163  return;
164  }
165 
166  std::ifstream strm(infile, std::ios_base::in|std::ios_base::binary);
167  if(strm.fail())
168  throw std::runtime_error("Unable to open output file");
169 
170  strm.seekg(0, std::ios_base::end);
171  const long fsize = strm.tellg();
172  strm.seekg(0);
173 
174  if(flashAcknowledgeMismatch!=2) {
175  mrf::XilinxBitInfo infile, inmem;
176 
177  infile.read(strm);
178  strm.seekg(0);
179 
180  mrf::CFIStreamBuf sbuf(mem);
181  std::istream mstrm(&sbuf);
182  mstrm.seekg(addr);
183  inmem.read(mstrm);
184 
185  bool match = true;
186  match &= infile.project.empty() || infile.project==inmem.project;
187  match &= infile.part.empty() || infile.part==inmem.part;
188  if(!match) {
189  fprintf(stderr, "Bitstream header mis-match.\nFile: \"%s\", \"%s\"\nROM: \"%s\", \"%s\"\n",
190  infile.part.c_str(), infile.project.c_str(),
191  inmem.part.c_str(), inmem.project.c_str());
192 
194  fprintf(stderr, "To override, re-run after setting: var(\"flashAcknowledgeMismatch\", 1)\n");
195  return;
196  }
197  }
198  }
199  // user must re-ack for each operation
201 
202  std::vector<epicsUInt8> buf;
203 
204  long pos=0;
205  while(strm.good()) {
206  printf("| %u/%u\n", (unsigned)pos, (unsigned)fsize);
207 
208  buf.resize(mem.blockSize());
209  buf.resize(strm.read((char*)&buf[0], buf.size()).gcount());
210  if(strm.bad())
211  throw std::runtime_error("I/O Error");
212  if(buf.empty())
213  break;
214  pos += buf.size();
215 
216  mem.write(addr, buf, false);
217  addr += buf.size();
218  }
219 
220  printf("\nDone\n");
221 
222  }catch(std::exception& e){
223  printf("Error: %s\n", e.what());
224  }
225 }
226 }
227 
228 extern "C" {
229 void flasherase(const char *name, int addrraw, int countraw)
230 {
231  try {
232  mrf::SPIDevice dev;
233  if(!mrf::SPIDevice::lookupDev(name, &dev)) {
234  printf("No such device");
235  return;
236  }
237  epicsUInt32 addr = addrraw, count = countraw;
238 
239  mrf::CFIFlash mem(dev);
240 
241  mem.erase(addr, count);
242 
243  printf("\nDone\n");
244 
245  }catch(std::exception& e){
246  printf("Error: %s\n", e.what());
247  }
248 }
249 }
250 
251 static const iocshArg flashinfoArg0 = { "device",iocshArgString};
252 static const iocshArg * const flashinfoArgs[1] =
253  {&flashinfoArg0};
254 static const iocshFuncDef flashinfoFuncDef =
255  {"flashinfo",1,flashinfoArgs};
256 
257 static void flashinfoCall(const iocshArgBuf *args)
258 {
259  flashinfo(args[0].sval);
260 }
261 
262 static const iocshArg flashreadArg0 = { "device",iocshArgString};
263 static const iocshArg flashreadArg1 = { "address",iocshArgInt};
264 static const iocshArg flashreadArg2 = { "count",iocshArgInt};
265 static const iocshArg flashreadArg3 = { "file",iocshArgString};
266 static const iocshArg * const flashreadArgs[4] =
267  {&flashreadArg0,&flashreadArg1,&flashreadArg2,&flashreadArg3};
268 static const iocshFuncDef flashreadFuncDef =
269  {"flashread",4,flashreadArgs};
270 
271 static void flashreadCall(const iocshArgBuf *args)
272 {
273  flashread(args[0].sval, args[1].ival, args[2].ival, args[3].sval);
274 }
275 
276 static const iocshArg flashwriteArg0 = { "device",iocshArgString};
277 static const iocshArg flashwriteArg1 = { "address",iocshArgInt};
278 static const iocshArg flashwriteArg2 = { "file",iocshArgString};
279 static const iocshArg * const flashwriteArgs[3] =
280  {&flashwriteArg0,&flashwriteArg1,&flashwriteArg2};
281 static const iocshFuncDef flashwriteFuncDef =
282  {"flashwrite",3,flashwriteArgs};
283 
284 static void flashwriteCall(const iocshArgBuf *args)
285 {
286  flashwrite(args[0].sval, args[1].ival, args[2].sval);
287 }
288 
289 static const iocshArg flasheraseArg0 = { "device",iocshArgString};
290 static const iocshArg flasheraseArg1 = { "address",iocshArgInt};
291 static const iocshArg flasheraseArg2 = { "count",iocshArgInt};
292 static const iocshArg * const flasheraseArgs[3] =
293  {&flasheraseArg0,&flasheraseArg1,&flasheraseArg2};
294 static const iocshFuncDef flasheraseFuncDef =
295  {"flasherase",3,flasheraseArgs};
296 
297 static void flasheraseCall(const iocshArgBuf *args)
298 {
299  flasherase(args[0].sval, args[1].ival, args[2].ival);
300 }
301 
302 static void registrarFlashOps()
303 {
304  iocshRegister(&flashinfoFuncDef, &flashinfoCall);
305  iocshRegister(&flashreadFuncDef, &flashreadCall);
306  iocshRegister(&flashwriteFuncDef, &flashwriteCall);
307  iocshRegister(&flasheraseFuncDef, &flasheraseCall);
308 }
309 extern "C" {
310 epicsExportRegistrar(registrarFlashOps);
312 }
int flashAcknowledgeMismatch
Definition: flashiocsh.cpp:32
epicsUInt32 blockSize()
Definition: flash.h:52
epicsUInt32 pageSize
PAGE PROGRAM (0x02) size in bytes. Always a power of 2.
Definition: flash.h:38
void flashread(const char *name, int addrraw, int countraw, const char *outfile)
Definition: flashiocsh.cpp:90
const char * vendorName
Definition: flash.h:37
void flashinfo(const char *name)
Definition: flashiocsh.cpp:36
Definition: evrdump.c:37
void readID(ID *id)
execute command 0x9f JEDEC-ID read
Definition: flash.cpp:33
std::string date
Definition: flash.h:110
epicsUInt32 capacity
total capacity in bytes
Definition: flash.h:38
Attempt to read out the header of a Xilinx bitstream file.
Definition: flash.h:104
Handling for Common Flash Interfafce compliant chips.
Definition: flash.h:23
epicsUInt32 sectorSize
SECTOR ERASE (0xd8) size in bytes. Always a power of 2.
Definition: flash.h:38
epicsExportAddress(int, flashAcknowledgeMismatch)
epicsExportRegistrar(registrarFlashOps)
std::string part
Definition: flash.h:110
std::vector< epicsUInt8 > SN
Definition: flash.h:42
epicsUInt8 dev_type
Definition: flash.h:33
Definition: devObj.h:97
std::string project
Definition: flash.h:110
epicsUInt8 vendor
Definition: flash.h:33
void flashwrite(const char *name, int addrraw, const char *infile)
Definition: flashiocsh.cpp:145
bool writable()
Definition: flash.h:48
bool read(std::istream &strm)
Definition: flash.cpp:405
void write(epicsUInt32 start, epicsUInt32 count, const epicsUInt8 *out, bool strict=true)
Definition: flash.cpp:157
static bool lookupDev(const std::string &name, SPIDevice *)
Definition: spi.cpp:74
Adapt CFIFlash for use with std::istream.
Definition: flash.h:89
epicsUInt8 dev_id
Definition: flash.h:33
void flasherase(const char *name, int addrraw, int countraw)
Definition: flashiocsh.cpp:229
void erase(epicsUInt32 start, epicsUInt32 count, bool strict=true)
Definition: flash.cpp:274
void read(epicsUInt32 start, epicsUInt32 count, epicsUInt8 *in)
Definition: flash.cpp:124