Skip to content

Commit 1a0ae0a

Browse files
committed
Implemented firmware update via UI
1 parent 6699e18 commit 1a0ae0a

File tree

8 files changed

+246
-15
lines changed

8 files changed

+246
-15
lines changed

qt/cmd.h

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,19 @@
55

66
enum
77
{
8-
CMD_NAND_READ_ID = 0x00,
9-
CMD_NAND_ERASE = 0x01,
10-
CMD_NAND_READ = 0x02,
11-
CMD_NAND_WRITE_S = 0x03,
12-
CMD_NAND_WRITE_D = 0x04,
13-
CMD_NAND_WRITE_E = 0x05,
14-
CMD_NAND_CONF = 0x06,
15-
CMD_NAND_READ_BB = 0x07,
16-
CMD_VERSION_GET = 0x08,
8+
CMD_NAND_READ_ID = 0x00,
9+
CMD_NAND_ERASE = 0x01,
10+
CMD_NAND_READ = 0x02,
11+
CMD_NAND_WRITE_S = 0x03,
12+
CMD_NAND_WRITE_D = 0x04,
13+
CMD_NAND_WRITE_E = 0x05,
14+
CMD_NAND_CONF = 0x06,
15+
CMD_NAND_READ_BB = 0x07,
16+
CMD_VERSION_GET = 0x08,
17+
CMD_ACTIVE_IMAGE_GET = 0x09,
18+
CMD_FW_UPDATE_S = 0x0a,
19+
CMD_FW_UPDATE_D = 0x0b,
20+
CMD_FW_UPDATE_E = 0x0c
1721
};
1822

1923
typedef struct __attribute__((__packed__))

qt/main_window.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent),
8787
SLOT(slotAboutDialog()));
8888
connect(ui->detectPushButton, SIGNAL(clicked()), this,
8989
SLOT(slotDetectChip()));
90+
connect(ui->actionFirmwareUpdate, SIGNAL(triggered()), this,
91+
SLOT(slotFirmwareUpdate()));
9092
}
9193

9294
MainWindow::~MainWindow()
@@ -185,6 +187,7 @@ void MainWindow::setUiStateConnected(bool isConnected)
185187
{
186188
ui->chipSelectComboBox->setEnabled(isConnected);
187189
ui->detectPushButton->setEnabled(isConnected);
190+
ui->actionFirmwareUpdate->setEnabled(isConnected);
188191
if (!isConnected)
189192
ui->chipSelectComboBox->setCurrentIndex(CHIP_INDEX_DEFAULT);
190193
}
@@ -598,3 +601,23 @@ void MainWindow::setProgress(unsigned int progress)
598601
{
599602
statusBar()->showMessage(tr("Progress: %1%").arg(progress));
600603
}
604+
605+
void MainWindow::slotProgFirmwareUpdateCompleted(int status)
606+
{
607+
if (!status)
608+
qInfo() << "Firmware update completed. Please restart device.";
609+
}
610+
611+
void MainWindow::slotFirmwareUpdate()
612+
{
613+
QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"),
614+
".", tr("Binary Files (*.bin)"));
615+
616+
if (fileName.isNull())
617+
return;
618+
619+
qInfo() << "Firmware update ...";
620+
connect(prog, SIGNAL(firmwareUpdateCompleted(int)), this,
621+
SLOT(slotProgFirmwareUpdateCompleted(int)));
622+
prog->firmwareUpdate(fileName);
623+
}

qt/main_window.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ private slots:
5151
void slotProgSelectCompleted(int status);
5252
void slotProgDetectChipConfCompleted(int status);
5353
void slotProgDetectChipReadChipIdCompleted(int status);
54+
void slotProgFirmwareUpdateCompleted(int status);
5455

5556
public slots:
5657
void slotFileOpen();
@@ -66,6 +67,7 @@ public slots:
6667
void slotSettingsProgrammer();
6768
void slotSettingsChipDb();
6869
void slotAboutDialog();
70+
void slotFirmwareUpdate();
6971
};
7072

7173
#endif // MAIN_WINDOW_H

qt/main_window.ui

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,8 @@
280280
</property>
281281
<addaction name="actionProgrammer"/>
282282
<addaction name="actionChipDb"/>
283+
<addaction name="separator"/>
284+
<addaction name="actionFirmwareUpdate"/>
283285
</widget>
284286
<widget class="QMenu" name="menuHelp">
285287
<property name="title">
@@ -383,6 +385,14 @@
383385
<string>About NANDO</string>
384386
</property>
385387
</action>
388+
<action name="actionFirmwareUpdate">
389+
<property name="enabled">
390+
<bool>false</bool>
391+
</property>
392+
<property name="text">
393+
<string>Firmware update</string>
394+
</property>
395+
</action>
386396
</widget>
387397
<layoutdefault spacing="6" margin="11"/>
388398
<resources/>

qt/programmer.cpp

Lines changed: 151 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ Programmer::Programmer(QObject *parent) : QObject(parent)
2525
skipBB = true;
2626
incSpare = false;
2727
isConn = false;
28+
firmwareBuffer = nullptr;
2829
QObject::connect(&reader, SIGNAL(log(QtMsgType, QString)), this,
2930
SLOT(logCb(QtMsgType, QString)));
3031
QObject::connect(&writer, SIGNAL(log(QtMsgType, QString)), this,
@@ -260,7 +261,7 @@ void Programmer::writeChip(uint8_t *buf, uint32_t addr, uint32_t len,
260261
SLOT(writeProgressCb(unsigned int)));
261262

262263
writer.init(usbDevName, SERIAL_PORT_SPEED, buf, addr, len, pageSize,
263-
skipBB, incSpare);
264+
skipBB, incSpare, CMD_NAND_WRITE_S, CMD_NAND_WRITE_D, CMD_NAND_WRITE_E);
264265
writer.start();
265266
}
266267

@@ -378,4 +379,153 @@ QString Programmer::fwVersionToString(FwVersion fwVersion)
378379
arg(fwVersion.minor).arg(fwVersion.build);
379380
}
380381

382+
int Programmer::firmwareImageRead()
383+
{
384+
qint64 ret, fileSize;
385+
uint32_t updateImageSize, updateImageOffset;
386+
387+
QFile file(firmwareFileName);
388+
if (!file.open(QIODevice::ReadOnly))
389+
{
390+
qCritical() << "Failed to open file:" << firmwareFileName <<
391+
", error:" << file.errorString();
392+
goto Error;
393+
}
394+
395+
fileSize = file.size();
396+
if (fileSize != (firmwareImage[FIRMWARE_IMAGE_LAST - 1].offset +
397+
firmwareImage[FIRMWARE_IMAGE_LAST - 1].size))
398+
{
399+
qCritical() << "Firmware image " << firmwareFileName <<
400+
" size " << fileSize << "is invalid, expected " << 256 * 1024;
401+
goto Error;
402+
}
403+
404+
updateImage = activeImage == FIRMWARE_IMAGE_1 ? FIRMWARE_IMAGE_2 :
405+
FIRMWARE_IMAGE_1;
406+
updateImageSize = firmwareImage[updateImage].size;
407+
updateImageOffset = firmwareImage[updateImage].offset;
408+
if (!(firmwareBuffer = new (std::nothrow) char[updateImageSize]))
409+
{
410+
qCritical() << "Failed to allocate memory for firmware image " <<
411+
firmwareFileName;
412+
goto Error;
413+
}
414+
415+
if (!file.seek(updateImageOffset))
416+
{
417+
qCritical() << "Failed to seek firmware image " << firmwareFileName;
418+
goto Error;
419+
}
420+
421+
if ((ret = file.read(firmwareBuffer, updateImageSize)) < 0)
422+
{
423+
qCritical() << "Failed to read firmware image " << firmwareFileName <<
424+
", error:" << file.errorString();
425+
goto Error;
426+
}
427+
428+
if (ret != updateImageSize)
429+
{
430+
qCritical() << "Firmware image " << firmwareFileName <<
431+
" was partially read, length" << ret;
432+
goto Error;
433+
}
434+
435+
return 0;
436+
437+
Error:
438+
if (firmwareBuffer)
439+
{
440+
delete [] firmwareBuffer;
441+
firmwareBuffer = nullptr;
442+
}
443+
emit firmwareUpdateCompleted(-1);
444+
return -1;
445+
}
446+
447+
void Programmer::firmwareUpdateProgressCb(unsigned int progress)
448+
{
449+
emit firmwareUpdateProgress(progress);
450+
}
451+
452+
void Programmer::firmwareUpdateCb(int ret)
453+
{
454+
QObject::disconnect(&writer, SIGNAL(progress(unsigned int)), this,
455+
SLOT(firmwareUpdateProgressCb(unsigned int)));
456+
QObject::disconnect(&writer, SIGNAL(result(int)), this,
457+
SLOT(firmwareUpdateCb(int)));
458+
459+
delete [] firmwareBuffer;
460+
firmwareBuffer = nullptr;
461+
462+
emit firmwareUpdateCompleted(ret);
463+
}
464+
465+
void Programmer::firmwareUpdateStart()
466+
{
467+
if (firmwareImageRead())
468+
{
469+
emit firmwareUpdateCompleted(-1);
470+
return;
471+
}
472+
473+
QObject::connect(&writer, SIGNAL(result(int)), this,
474+
SLOT(firmwareUpdateCb(int)));
475+
QObject::connect(&writer, SIGNAL(progress(unsigned int)), this,
476+
SLOT(firmwareUpdateProgressCb(unsigned int)));
477+
478+
writer.init(usbDevName, SERIAL_PORT_SPEED,
479+
reinterpret_cast<uint8_t *>(firmwareBuffer),
480+
firmwareImage[updateImage].address, firmwareImage[updateImage].size,
481+
flashPageSize, 0, 0, CMD_FW_UPDATE_S, CMD_FW_UPDATE_D, CMD_FW_UPDATE_E);
482+
writer.start();
483+
}
484+
485+
void Programmer::getActiveImageCb(int ret)
486+
{
487+
QObject::disconnect(&reader, SIGNAL(result(int)), this,
488+
SLOT(getActiveImageCb(int)));
489+
490+
if (ret < 0)
491+
{
492+
qCritical() << "Failed to get active firmware image";
493+
goto Error;
494+
}
495+
496+
if (activeImage >= FIRMWARE_IMAGE_LAST)
497+
{
498+
qCritical() << "Wrong active firmware image: " << activeImage;
499+
goto Error;
500+
}
501+
502+
qInfo() << "Active firmware image: " << activeImage;
503+
504+
firmwareUpdateStart();
505+
return;
506+
507+
Error:
508+
emit firmwareUpdateCompleted(-1);
509+
}
510+
511+
void Programmer::firmwareUpdate(const QString &fileName)
512+
{
513+
Cmd cmd;
514+
515+
firmwareFileName = fileName;
516+
517+
QObject::connect(&reader, SIGNAL(result(int)), this,
518+
SLOT(getActiveImageCb(int)));
519+
520+
cmd.code = CMD_ACTIVE_IMAGE_GET;
521+
522+
writeData.clear();
523+
writeData.append(reinterpret_cast<const char *>(&cmd), sizeof(cmd));
524+
reader.init(usbDevName, SERIAL_PORT_SPEED, &activeImage,
525+
sizeof(activeImage),
526+
reinterpret_cast<const uint8_t *>(writeData.constData()),
527+
static_cast<uint32_t>(writeData.size()), false, false);
528+
reader.start();
529+
}
530+
381531

qt/programmer.h

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,28 @@ class Programmer : public QObject
2121
{
2222
Q_OBJECT
2323

24+
typedef enum
25+
{
26+
FIRMWARE_IMAGE_1 = 0,
27+
FIRMWARE_IMAGE_2 = 1,
28+
FIRMWARE_IMAGE_LAST = 2,
29+
} FirmwareImageNum;
30+
31+
typedef struct
32+
{
33+
FirmwareImageNum num;
34+
uint32_t address;
35+
uint32_t offset;
36+
uint32_t size;
37+
} FirmwareImage;
38+
39+
const FirmwareImage firmwareImage[FIRMWARE_IMAGE_LAST] =
40+
{
41+
{ FIRMWARE_IMAGE_1, 0x08004000, 0x00004000, 0x1e000 },
42+
{ FIRMWARE_IMAGE_2, 0x08022000, 0x00022000, 0x1e000 },
43+
};
44+
const uint32_t flashPageSize = 0x800;
45+
2446
QSerialPort serialPort;
2547
QString usbDevName;
2648
Writer writer;
@@ -29,9 +51,15 @@ class Programmer : public QObject
2951
bool skipBB;
3052
bool incSpare;
3153
FwVersion fwVersion;
54+
uint8_t activeImage;
55+
uint8_t updateImage;
56+
QString firmwareFileName;
57+
char *firmwareBuffer;
3258

3359
int serialPortConnect();
3460
void serialPortDisconnect();
61+
int firmwareImageRead();
62+
void firmwareUpdateStart();
3563

3664
public:
3765
QByteArray writeData;
@@ -56,6 +84,7 @@ class Programmer : public QObject
5684
void confChip(ChipInfo *chipInfo);
5785
void detectChip();
5886
QString fwVersionToString(FwVersion fwVersion);
87+
void firmwareUpdate(const QString &fileName);
5988

6089
signals:
6190
void connectCompleted(int ret);
@@ -68,6 +97,8 @@ class Programmer : public QObject
6897
void eraseChipProgress(unsigned int progress);
6998
void readChipBadBlocksCompleted(int ret);
7099
void confChipCompleted(int ret);
100+
void firmwareUpdateCompleted(int ret);
101+
void firmwareUpdateProgress(unsigned int progress);
71102

72103
private slots:
73104
void readChipIdCb(int ret);
@@ -81,6 +112,9 @@ private slots:
81112
void confChipCb(int ret);
82113
void logCb(QtMsgType msgType, QString msg);
83114
void connectCb(int ret);
115+
void getActiveImageCb(int ret);
116+
void firmwareUpdateCb(int ret);
117+
void firmwareUpdateProgressCb(unsigned int progress);
84118
};
85119

86120
#endif // PROGRAMMER_H

qt/writer.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@
1515
Q_DECLARE_METATYPE(QtMsgType)
1616

1717
void Writer::init(const QString &portName, qint32 baudRate, uint8_t *buf,
18-
uint32_t addr, uint32_t len, uint32_t pageSize, bool skipBB, bool incSpare)
18+
uint32_t addr, uint32_t len, uint32_t pageSize, bool skipBB, bool incSpare,
19+
uint8_t startCmd, uint8_t dataCmd, uint8_t endCmd)
1920
{
2021
this->portName = portName;
2122
this->baudRate = baudRate;
@@ -25,6 +26,9 @@ void Writer::init(const QString &portName, qint32 baudRate, uint8_t *buf,
2526
this->pageSize = pageSize;
2627
this->skipBB = skipBB;
2728
this->incSpare = incSpare;
29+
this->startCmd = startCmd;
30+
this->dataCmd = dataCmd;
31+
this->endCmd = endCmd;
2832
bytesWritten = 0;
2933
bytesAcked = 0;
3034
}
@@ -212,7 +216,7 @@ int Writer::writeStart()
212216
{
213217
WriteStartCmd writeStartCmd;
214218

215-
writeStartCmd.cmd.code = CMD_NAND_WRITE_S;
219+
writeStartCmd.cmd.code = startCmd;
216220
writeStartCmd.addr = addr;
217221
writeStartCmd.len = len;
218222
writeStartCmd.flags.skipBB = skipBB;
@@ -236,7 +240,7 @@ int Writer::writeData()
236240
WriteDataCmd *writeDataCmd = reinterpret_cast<WriteDataCmd *>(pbuf);
237241
uint32_t dataLen, dataLenMax, headerLen, pageLim;
238242

239-
writeDataCmd->cmd.code = CMD_NAND_WRITE_D;
243+
writeDataCmd->cmd.code = dataCmd;
240244
headerLen = sizeof(WriteDataCmd);
241245
dataLenMax = BUF_SIZE - headerLen;
242246

@@ -270,7 +274,7 @@ int Writer::writeEnd()
270274
{
271275
WriteEndCmd writeEndCmd;
272276

273-
writeEndCmd.cmd.code = CMD_NAND_WRITE_E;
277+
writeEndCmd.cmd.code = endCmd;
274278

275279
if (write(reinterpret_cast<uint8_t *>(&writeEndCmd), sizeof(WriteEndCmd)))
276280
return -1;

0 commit comments

Comments
 (0)