DUNE-DAQ
DUNE Trigger and Data Acquisition software
Loading...
Searching...
No Matches
WIB_Flash.cpp
Go to the documentation of this file.
1#include "wibmod/WIB1/WIB.hh"
4#include <fstream>
5#include <assert.h>
6#include <algorithm>
7#define FLASH_TIMEOUT 400
8
9#define MIN_LINE_LENGTH 10
10#define MAX_LINE_LENGTH 266
11
12static void ParseIHexLine(std::string line, std::vector <uint8_t> &data, uint32_t &upperAddr){
13 if(line.empty()){
14 BUException::WIB_FLASH_IHEX_ERROR e;
15 e.Append("line is empty");
16 throw e;
17 }else if(line[0] != ':'){
18 BUException::WIB_FLASH_IHEX_ERROR e;
19 e.Append("BAD Line in file - does not start with ':'");
20 throw e;
21 }else{
22 line.erase(0,1);
23 }
24 if(line.size()<MIN_LINE_LENGTH){
25 BUException::WIB_FLASH_IHEX_ERROR e;
26 e.Append("BAD Line in file - incomplete intel hex format\n");
27 throw e;
28 }else if(line.size()>MAX_LINE_LENGTH){
29 BUException::WIB_FLASH_IHEX_ERROR e;
30 e.Append("BAD Line in file - intel hex format not supported, contains too many characters\n");
31 throw e;
32 }else if (line.size()&1){
33 BUException::WIB_FLASH_IHEX_ERROR e;
34 e.Append("BAD Line in file - uneven number of characters\n");
35 throw e;
36 }else {
37 char const *entry = line.c_str();
38 uint32_t line_sum = 0, byte_count = 0, address = 0, record_type = 0;
39
40 uint32_t byte = 0;
41 for(uint32_t iSum = 0; iSum < line.size(); iSum+=2){
42 sscanf(entry+iSum, "%2x", &byte);
43 line_sum += byte;
44 }
45 //the content of the line is cancelled out through addition to its
46 //two's complement which is the checksum if all data is intact
47
48 if(0xFF&line_sum){
49 line_sum = 0xFF & line_sum;
50 BUException::WIB_FLASH_IHEX_ERROR e;
51 e.Append("BAD Line in file - content inconsistent with checksum.\n");
52 throw e;
53 } else{
54 line_sum = 0;
55 }
56
57 sscanf(entry,"%2x %4x %2x ", &byte_count, &address, &record_type);
58 if(4 == record_type){
59 upperAddr = 0;
60 sscanf(entry+8,"%4x", &upperAddr);
61 upperAddr = upperAddr << 16;
62 } else if(0 == record_type){
63 address = upperAddr+address;
64 if(data.size() < (address+byte_count)){
65 data.resize(address+byte_count,0xFF);
66 }
67 for(uint32_t iAddr = 0; iAddr < byte_count; iAddr++){
68 uint32_t tempData = 0;
69 sscanf(entry+(iAddr*2)+8,"%02x",&tempData);
70 data[address+iAddr] = (uint8_t)tempData;
71 }
72
73 }
74 }
75}
76
77 void LoadIHexFile(std::vector <uint8_t>&data, const char* file){
78 std::string line;
79 std::ifstream datafile(file);
80 uint32_t upperAddr = 0;
81 if(datafile.is_open()){
82 while(getline(datafile, line)){
83 ParseIHexLine(line, data, upperAddr);
84 }
85 } else{
86 BUException::WIB_FLASH_IHEX_ERROR e;
87 e.Append("Unable to open file ");
88 e.Append(file);
89 throw e;
90 }
91 }
92
93static std::vector<uint32_t> firmwareFromIntelHexFile(std::string const & iHexFileName){
94 //Ihex parser loads intel hex into a vector of bytes.
95 std::vector<uint8_t> rawData;
96 LoadIHexFile(rawData,iHexFileName.c_str());
97
98 //We now need to convert it to a uint32_t
99 //This has the issue of what to do if we are off by 32bit boundary.
100 //For now we'll just die so we don't have to deal with the issue.
101 //Make sure this is called before we erase the flash :-p
102 if((rawData.size()&0x3) != 0x0){
103 BUException::WIB_FLASH_IHEX_ERROR e;
104 e.Append("Flash data is not a multiple of 32bit words");
105 throw e;
106 }else if(0 == rawData.size()){
107 BUException::WIB_FLASH_IHEX_ERROR e;
108 e.Append("Flash data is empty");
109 throw e;
110 }
111
112 //Create a std::vector<uint32_t> and fill it with rawData;
113 std::vector<uint32_t> ret;
114 for(size_t iRawData = 0; iRawData < rawData.size();iRawData+=4){
115 //Build the 32bit word
116 uint32_t tempData = (rawData[iRawData + 0] << 0 |
117 rawData[iRawData + 1] << 8 |
118 rawData[iRawData + 2] << 16 |
119 rawData[iRawData + 3] << 24 );
120 ret.push_back(tempData);
121 }
122 return ret;
123}
124
125
126void WIB::ReadFlash(std::string const & fileName,uint8_t update_percentage){
127 bool print_updates = false;
128 if(update_percentage < 100){
129 print_updates = true;
130 }
131 size_t update_delta = (update_percentage * float(16*1024*1024/4))/100;
132 size_t next_update = update_delta;
133
134 FILE * outFile = fopen(fileName.c_str(),"w");
135 if(outFile == NULL){
136 BUException::WIB_BAD_ARGS e;
137 e.Append("Failed to create: ");
138 e.Append(fileName);
139 throw e;
140 }
141
142 if(print_updates){
143 fprintf(stderr," Reading flash\n");
144 fprintf(stderr," [");
145 for(size_t i = 0; i < 100.0/update_percentage;i++){
146 fprintf(stderr,"=");
147 }
148 fprintf(stderr,"]\n [");
149 }
150 //program flash in groups of 64 32bit words (256 bytes)
151 uint32_t address = 0;
152
153 uint32_t blockRegMapAddress = GetItem("FLASH.DATA00")->address;
154 size_t blockSize = 64;
155 //set block size
156 WriteWithRetry("FLASH.BYTE_COUNT",255);
157
158 for(size_t iWord = 0; iWord < 16*1024*1024/4;){
160
161 //Set adddress
162 WriteWithRetry("FLASH.ADDRESS",address);
163 //Start read
164 WriteWithRetry("FLASH.RUN_COMMAND",0x5);
165
167
168 //Readout the data
169 for(size_t iWordRead = 0;iWordRead < blockSize;iWordRead++){
170 fprintf(outFile,"0x%06X 0x%08X\n",uint32_t(iWord),ReadWithRetry(blockRegMapAddress+iWordRead));
171 iWord++;
172 }
173
174 // iWord+= blockSize;
175 address+=blockSize*4;
176
177 if(print_updates && (iWord > next_update)){
178 // printf(" % 3f%% done\n",float(iWord)/float(flashData.size()));
179 fprintf(stderr,"=");
180 next_update += update_delta;
181 }
182 }
183 if(print_updates){
184 printf("]\n");
185 printf(" done\n");
186 }
187 fclose(outFile);
188}
189
190void WIB::EraseFlash(bool print_updates){
191 if(print_updates){
192 fprintf(stderr," Erase flash\n");
193 }
194 WriteWithRetry("FLASH.RUN_COMMAND",0x7);
195 size_t iTimeout = FLASH_TIMEOUT;
196 while(ReadWithRetry("FLASH.BUSY") && (iTimeout != 0)){
197 iTimeout--;
198 usleep(100000);
199 }
200 if(iTimeout == 0){
201 BUException::WIB_FLASH_TIMEOUT e;
202 //throw an exception
203 e.Append("Program (erase): FLASH.BUSY");
204 throw e;
205 //throw an exception
206 }
207}
208
209void WIB::ProgramFlash(std::string const & fileName,uint8_t update_percentage){
210 WriteWithRetry("SYSTEM.SLOW_CONTROL_DND",1);
211
212 bool print_updates = false;
213 if(update_percentage < 100){
214 print_updates = true;
215 }
216
217 //Load data and validate
218 if(print_updates){
219 fprintf(stderr," Reading file: %s\n",fileName.c_str());
220 }
221 // std::vector<uint32_t> flashData = firmwareFromDumpFile(fileName);
222 std::vector<uint32_t> flashData = firmwareFromIntelHexFile(fileName);
223
224 //erase flash
225 EraseFlash(print_updates);
226
227 //Load data into flash.
228 WriteFlash(flashData,update_percentage);
229
230
231 //Validate flash
232 CheckFlash(flashData,update_percentage);
233 WriteWithRetry("SYSTEM.SLOW_CONTROL_DND",0);
234}
235
236void WIB::WriteFlash(std::vector<uint32_t> flashData,uint8_t update_percentage){
237 //Setup display if needed
238 bool print_updates = false;
239 if(update_percentage < 100){
240 print_updates = true;
241 }
242 size_t update_delta = (update_percentage * float(flashData.size()))/100;
243 size_t next_update = update_delta;
244 if(print_updates){
245 fprintf(stderr," Programming flash\n");
246 fprintf(stderr," [");
247 for(size_t i = 0; i < 100.0/update_percentage;i++){
248 fprintf(stderr,"=");
249 }
250 fprintf(stderr,"]\n [");
251 }
252
253
254 //program flash in groups of 64 32bit words (256 bytes)
255 uint32_t blockRegMapAddress = GetItem("FLASH.DATA00")->address; //Address of first of 64 32bit words
256 uint32_t flashAddress = 0; //Address in flash that we are writing to.
257
258 for(size_t currentBlockStartIndex = 0; currentBlockStartIndex < flashData.size();){
260
261 //Find size of this block to write (usually just 64 (256bytes)), but the last one might be smaller.
262 size_t blockSize = std::min(size_t(64),flashData.size()-currentBlockStartIndex);
263 //Set adddress
264 WriteWithRetry("FLASH.ADDRESS",flashAddress);
265 //set block size (in bytes and is 1 less than value; 0 means 1 byte, 255 means 256 bytes)
266 WriteWithRetry("FLASH.BYTE_COUNT",(blockSize*sizeof(uint32_t))-1);
267
268 //Write block of data
269 for(size_t iBlockWord = 0; iBlockWord < blockSize;iBlockWord++){
270 //arg1: Address in WIB register map of this 32bit word
271 //arg2: Data for this 32bit word reg map address in data vector
272 WriteWithRetry(blockRegMapAddress + iBlockWord,
273 flashData[currentBlockStartIndex + iBlockWord]);
274 }
275 //Do the block write
276 WriteWithRetry("FLASH.RUN_COMMAND",0x1);
277 currentBlockStartIndex += blockSize;
278 flashAddress += blockSize*sizeof(uint32_t);
279
280 //Update the screen if needed
281 if(print_updates && (currentBlockStartIndex > next_update)){
282 fprintf(stderr,"=");
283 next_update += update_delta;
284 }
285 }
286 //Update the screen if needed
287 if(print_updates){
288 fprintf(stderr,"]\n");
289 fprintf(stderr," done\n");
290 }
291
292}
293
294void WIB::CheckFlash(std::vector<uint32_t> flashData,uint8_t update_percentage){
295 bool print_updates = false;
296 if(update_percentage < 100){
297 print_updates = true;
298 }
299 size_t update_delta = (update_percentage * float(16*1024*1024/4))/100;
300 size_t next_update = update_delta;
301
302 if(print_updates){
303 fprintf(stderr," Checking flash\n");
304 fprintf(stderr," [");
305 for(size_t i = 0; i < 100.0/update_percentage;i++){
306 fprintf(stderr,"=");
307 }
308 fprintf(stderr,"]\n [");
309 }
310 //program flash in groups of 64 32bit words (256 bytes)
311 uint32_t flashAddress = 0;
312 uint32_t blockRegMapAddress = GetItem("FLASH.DATA00")->address;
313
314 for(size_t currentBlockStartIndex = 0; currentBlockStartIndex < 16*1024*1024/4;){
316
317 //Find size of this block to write (usually just 64 (256bytes)), but the last one might be smaller.
318 size_t blockSize = std::min(size_t(64),flashData.size()-currentBlockStartIndex);
319 //Set adddress
320 WriteWithRetry("FLASH.ADDRESS",flashAddress);
321 //set block size (in bytes and is 1 less than value; 0 means 1 byte, 255 means 256 bytes)
322 WriteWithRetry("FLASH.BYTE_COUNT",(blockSize*sizeof(uint32_t))-1);
323 //Start read
324 WriteWithRetry("FLASH.RUN_COMMAND",0x5);
325
327
328 //Check the data.
329 for(size_t iBlockWord = 0;iBlockWord < blockSize;iBlockWord++){
330 //flashData: Address in WIB register map of this 32bit word
331 //ReadWithRetry: Data from the flash for this word
332 uint32_t dataRead;
333 if((dataRead = ReadWithRetry(blockRegMapAddress + iBlockWord)) !=
334 flashData[currentBlockStartIndex + iBlockWord]){
335 BUException::WIB_FLASH_ERROR e;
336 char errorbuffer[] = "Error on index 0xXXXXXXXX: 0xXXXXXXXX != 0xXXXXXXXX";
337 snprintf(errorbuffer,
338 strlen(errorbuffer),
339 "Error on index 0x%08X: 0x%08X != 0x%08X",
340 flashAddress,
341 dataRead,
342 flashData[currentBlockStartIndex + iBlockWord]);
343 e.Append(errorbuffer);
344 throw e;
345 }
346 }
347 currentBlockStartIndex += blockSize;
348 flashAddress += blockSize*sizeof(uint32_t);
349
350 if(print_updates && (currentBlockStartIndex > next_update)){
351 fprintf(stderr,"=");
352 next_update += update_delta;
353 }
354 }
355 if(print_updates){
356 printf("]\n");
357 printf(" Check passed\n");
358 }
359}
360
361
363 size_t iTimeout = FLASH_TIMEOUT;
364 while(ReadWithRetry("FLASH.BUSY") && (iTimeout != 0)){
365 iTimeout--;
366 usleep(10000);
367 }
368 if(iTimeout == 0){
369 BUException::WIB_FLASH_TIMEOUT e;
370 //throw an exception
371 e.Append("Read: FLASH.BUSY");
372 throw e;
373 }
374}
static void ParseIHexLine(std::string line, std::vector< uint8_t > &data, uint32_t &upperAddr)
Definition WIB_Flash.cpp:12
#define FLASH_TIMEOUT
Definition WIB_Flash.cpp:7
#define MIN_LINE_LENGTH
Definition WIB_Flash.cpp:9
void LoadIHexFile(std::vector< uint8_t > &data, const char *file)
Definition WIB_Flash.cpp:77
static std::vector< uint32_t > firmwareFromIntelHexFile(std::string const &iHexFileName)
Definition WIB_Flash.cpp:93
#define MAX_LINE_LENGTH
Definition WIB_Flash.cpp:10
uint16_t address
void WriteWithRetry(uint16_t address, uint32_t value)
Definition WIBBase.cpp:129
uint32_t ReadWithRetry(uint16_t address)
Definition WIBBase.cpp:116
Item const * GetItem(std::string const &)
Definition WIBBase.cpp:103
void EraseFlash(bool print_updates=false)
void WriteFlash(std::vector< uint32_t > data, uint8_t update_percentage=101)
void FlashCheckBusy()
void ReadFlash(std::string const &fileName, uint8_t update_percentage=101)
void ProgramFlash(std::string const &fileName, uint8_t update_percentage=101)
void CheckFlash(std::vector< uint32_t > data, uint8_t update_percentage=101)