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