DUNE-DAQ
DUNE Trigger and Data Acquisition software
Toggle main menu visibility
Loading...
Searching...
No Matches
dunedaq
sourcecode
wibmod
src
WIB1
WIB_Flash.cpp
Go to the documentation of this file.
1
#include "
wibmod/WIB1/WIB.hh
"
2
#include "
wibmod/WIB1/WIBException.hh
"
3
#include "
wibmod/WIB1/BNL_UDP_Exception.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
12
static
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
93
static
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
126
void
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;){
159
FlashCheckBusy
();
160
161
//Set adddress
162
WriteWithRetry
(
"FLASH.ADDRESS"
,address);
163
//Start read
164
WriteWithRetry
(
"FLASH.RUN_COMMAND"
,0x5);
165
166
FlashCheckBusy
();
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
190
void
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
209
void
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
236
void
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();){
259
FlashCheckBusy
();
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
294
void
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;){
315
FlashCheckBusy
();
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
326
FlashCheckBusy
();
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
362
void
WIB::FlashCheckBusy
(){
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
}
BNL_UDP_Exception.hh
WIBException.hh
WIB.hh
ParseIHexLine
static void ParseIHexLine(std::string line, std::vector< uint8_t > &data, uint32_t &upperAddr)
Definition
WIB_Flash.cpp:12
FLASH_TIMEOUT
#define FLASH_TIMEOUT
Definition
WIB_Flash.cpp:7
MIN_LINE_LENGTH
#define MIN_LINE_LENGTH
Definition
WIB_Flash.cpp:9
LoadIHexFile
void LoadIHexFile(std::vector< uint8_t > &data, const char *file)
Definition
WIB_Flash.cpp:77
firmwareFromIntelHexFile
static std::vector< uint32_t > firmwareFromIntelHexFile(std::string const &iHexFileName)
Definition
WIB_Flash.cpp:93
MAX_LINE_LENGTH
#define MAX_LINE_LENGTH
Definition
WIB_Flash.cpp:10
Item::address
uint16_t address
Definition
AddressTable.hh:18
WIBBase::WriteWithRetry
void WriteWithRetry(uint16_t address, uint32_t value)
Definition
WIBBase.cpp:129
WIBBase::ReadWithRetry
uint32_t ReadWithRetry(uint16_t address)
Definition
WIBBase.cpp:116
WIBBase::GetItem
Item const * GetItem(std::string const &)
Definition
WIBBase.cpp:103
WIB::EraseFlash
void EraseFlash(bool print_updates=false)
Definition
WIB_Flash.cpp:190
WIB::WriteFlash
void WriteFlash(std::vector< uint32_t > data, uint8_t update_percentage=101)
Definition
WIB_Flash.cpp:236
WIB::FlashCheckBusy
void FlashCheckBusy()
Definition
WIB_Flash.cpp:362
WIB::ReadFlash
void ReadFlash(std::string const &fileName, uint8_t update_percentage=101)
Definition
WIB_Flash.cpp:126
WIB::ProgramFlash
void ProgramFlash(std::string const &fileName, uint8_t update_percentage=101)
Definition
WIB_Flash.cpp:209
WIB::CheckFlash
void CheckFlash(std::vector< uint32_t > data, uint8_t update_percentage=101)
Definition
WIB_Flash.cpp:294
Generated on
for DUNE-DAQ by
1.17.0