Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ping360 firmware update functionality #1070

Open
wants to merge 28 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
03b52ba
protocoldetector: remove unnecessary include
jaxxzer Dec 19, 2023
9db6728
protocoldetector: quiet debug output by only printing buffer when it …
jaxxzer Dec 19, 2023
e81ba72
protocoldetector: update comment to reflect implementation
jaxxzer Dec 19, 2023
5d1dca3
sensor: ping360: send motor_off command during destruction
jaxxzer Dec 19, 2023
a18793e
flash: make Flasher class valid baud rates available to qml
jaxxzer Dec 19, 2023
9f5a5e4
qml: use Flasher cpp object valid baudrates for selection
jaxxzer Dec 19, 2023
3b42201
qml: FirmwareUpdate: use 115200 instead of 57600 for default flash ba…
jaxxzer Jan 24, 2024
9c1358c
qml: stop protocol detector when displaying manual connection page
jaxxzer Dec 19, 2023
06b4c0f
flash: refactor flasher class in preparation for Ping360 subclass
jaxxzer Dec 19, 2023
e38ed7f
sensor: make sensor _flasher member a pointer to allow dynamic polymo…
jaxxzer Dec 19, 2023
9783391
lib: add libcintelhex dependency for ping360 flashing
jaxxzer Dec 19, 2023
77f6722
flash: add new sources for Ping360 flashing
jaxxzer Dec 19, 2023
ed38e29
cmake: add C language support for libcintelhex dependency
jaxxzer Dec 19, 2023
c71074d
cmake: add libcintelhex to global includes
jaxxzer Dec 19, 2023
da7874c
flash: cmake: add ping360 flash sources to build
jaxxzer Dec 19, 2023
71cfdc4
link: seriallink: add method to get the current baudrate
jaxxzer Jan 31, 2024
071ab0e
sensor: ping360: implement firmware update functionality
jaxxzer Dec 19, 2023
50da735
qml: MainPage: make FirmwareUpdate visible for ping360
jaxxzer Dec 19, 2023
a484e5c
protocoldetector: check for ping360 bootloader during scan
jaxxzer Dec 19, 2023
9469741
sensor: ping360: add check for bootloader
jaxxzer Dec 19, 2023
5511378
qml: Ping360Visualizer: add bootloader notification
jaxxzer Dec 19, 2023
5721dd8
sensor: ping360: send async profile request when settings are valid
jaxxzer Dec 19, 2023
cb1d549
sensor: ping360: allow _profileRequestLogic.type to be updated more t…
jaxxzer Dec 19, 2023
e9ca292
sensor: ping360: add some debug messages about profile timeout
jaxxzer Jan 23, 2024
e858db9
sensor: ping360: remove profile timeout for AUTO_DEVICE_DATA
jaxxzer Jan 23, 2024
912565b
link: seriallink: extend delay for line break auto baudrate procedure
jaxxzer Feb 1, 2024
508b250
sensor: ping360: change default end_angle from 400 to 399
jaxxzer Feb 1, 2024
68fa8b4
sensor: ping360: add num_steps to sensor settings struct
jaxxzer Feb 1, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,6 @@
[submodule "lib/fmt/fmt"]
path = lib/fmt/fmt
url = https://github.com/fmtlib/fmt
[submodule "lib/libcintelhex"]
path = lib/libcintelhex
url = https://github.com/jaxxzer/libcintelhex
5 changes: 3 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.12)
project(ping-viewer LANGUAGES CXX)
project(ping-viewer LANGUAGES CXX C)

set(CMAKE_CXX_STANDARD 17)
set(CXX_STANDARD_REQUIRED ON)
Expand Down Expand Up @@ -50,11 +50,12 @@ message(STATUS "Qt Version: ${Qt5_VERSION}")
# global include directories
include_directories(
lib/fmt/fmt/include/
lib/ping-cpp/ping-cpp/src/message/
lib/libcintelhex/include
lib/maddy/maddy/include/
lib/mavlink/c_library_v2/
lib/mavlink/c_library_v2/minimal
lib/mavlink/c_library_v2/common
lib/ping-cpp/ping-cpp/src/message/
)

add_subdirectory(lib/fmt/fmt)
Expand Down
1 change: 1 addition & 0 deletions lib/libcintelhex
Submodule libcintelhex added at 2db480
16 changes: 13 additions & 3 deletions qml/DeviceManagerViewer.qml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,14 @@ PingPopup {

closePolicy: Popup.NoAutoClose
onVisibleChanged: {
visible ? DeviceManager.startDetecting() : DeviceManager.stopDetecting();
print(stack.depth);
if (visible) {
if (stack.depth == 1)
DeviceManager.startDetecting();

} else {
DeviceManager.stopDetecting();
}
}
Component.onCompleted: {
if (!DeviceManager.primarySensor)
Expand Down Expand Up @@ -57,10 +64,13 @@ PingPopup {
Layout.fillWidth: true
onClicked: {
print(stack.depth);
if (stack.depth == 1)
if (stack.depth == 1) {
DeviceManager.stopDetecting();
stack.push(connectionMenu);
else
} else {
DeviceManager.startDetecting();
stack.pop();
}
}
}

Expand Down
5 changes: 2 additions & 3 deletions qml/FirmwareUpdate.qml
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,7 @@ RowLayout {
PingComboBox {
id: baudComboBox

// This should use the same values in Flasher::_validBaudRates
model: [57600, 115200, 230400]
model: ping.flasher.validBaudRates
Layout.fillWidth: true
visible: SettingsManager.debugMode
}
Expand Down Expand Up @@ -159,7 +158,7 @@ RowLayout {
Layout.fillWidth: true
enabled: !running && ((fwCombo.currentText != "" && !browseBt.visible) || (fileDialog.fileName != "" && browseBt.visible))
onClicked: {
var baud = SettingsManager.debugMode ? baudComboBox.model[baudComboBox.currentIndex] : 57600;
var baud = SettingsManager.debugMode ? baudComboBox.model[baudComboBox.currentIndex] : 115200;
var verify = SettingsManager.debugMode ? verifyCB.checked : true;
var path = automaticUpdateCB.currentIndex ? fileDialog.fileUrl : ping.firmwaresAvailable[fwCombo.currentText];
running = true;
Expand Down
1 change: 0 additions & 1 deletion qml/MainPage.qml
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,6 @@ Item {
PingItem {
id: firmwareUpdateItem

visible: ping ? ping.link.configuration.deviceType() == PingEnumNamespace.PingDeviceType.PING1D : false
isSubItem: true
icon: StyleManager.firmwareUpdateIcon()
onHideItemChanged: {
Expand Down
16 changes: 16 additions & 0 deletions qml/Ping360Visualizer.qml
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,22 @@ Item {
visible: false
}

Text {
id: bootloaderWarning

visible: ping.isBootloader
anchors.fill: waterfall
anchors.margins: 5
font.bold: true
font.family: "Arial"
font.pointSize: 15
text: "Ping360 is in Bootloader Mode. Please flash firmware."
color: "red"
z: 100
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}

Text {
id: mouseReadout

Expand Down
10 changes: 10 additions & 0 deletions src/flash/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
file(GLOB LIBCINTELHEXFILES
${PROJECT_SOURCE_DIR}/lib/libcintelhex/src/ihex_parse.c
${PROJECT_SOURCE_DIR}/lib/libcintelhex/src/ihex_record.c
)

add_library(
flash
STATIC
flasher.cpp
pic-hex.cpp
ping360bootloaderpacket.cpp
ping360flasher.cpp
ping360flashworker.cpp
${LIBCINTELHEXFILES}
)

target_link_libraries(
Expand Down
3 changes: 2 additions & 1 deletion src/flash/flasher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@

PING_LOGGING_CATEGORY(FLASH, "ping.flash")

Flasher::Flasher(QObject* parent)
Flasher::Flasher(QObject* parent, const QList<QVariant> validBaudRates)
: QObject(parent)
, _validBaudRates(validBaudRates)
{
_binRelativePath =
#ifdef Q_OS_OSX
Expand Down
25 changes: 18 additions & 7 deletions src/flash/flasher.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ class Flasher : public QObject {
* @brief Construct a new Flasher object
*
* @param parent
* @param validBaudRates
*/
Flasher(QObject* parent = nullptr);
Flasher(QObject* parent = nullptr, const QList<QVariant> validBaudRates = {57600, 115200, 230400});

/**
* @brief Destroy the Flasher object
Expand Down Expand Up @@ -72,11 +73,17 @@ class Flasher : public QObject {
Flasher::States state() const { return _state; };
Q_PROPERTY(Flasher::States state READ state NOTIFY stateChanged)

/**
* @brief Return the valid baud rates for device communication
*/
const QVariantList& validBaudRates() const { return _validBaudRates; };
Q_PROPERTY(QVariant validBaudRates READ validBaudRates CONSTANT);

/**
* @brief Start the flash procedure
*
*/
void flash();
virtual void flash();

/**
* @brief Set the flash baud rate
Expand Down Expand Up @@ -111,17 +118,21 @@ class Flasher : public QObject {
void flashProgress(float progress);
void stateChanged(Flasher::States state);

protected:
int _baudRate = 57600;
QString _firmwareFilePath;
LinkConfiguration _link;
const QList<QVariant> _validBaudRates;
bool _verify = true;

private:
void firmwareUpdatePercentage(const QString& output);
static QString stm32flashPath();

int _baudRate = 57600;
QString _binRelativePath;
QString _firmwareFilePath;
QSharedPointer<QProcess> _firmwareProcess;
LinkConfiguration _link;
QString _message;
States _state = Idle;
const QList<int> _validBaudRates = {57600, 115200, 230400};
bool _verify = true;
};

Q_DECLARE_METATYPE(Flasher::States);
138 changes: 138 additions & 0 deletions src/flash/pic-hex.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
#include "pic-hex.h"

#include <stdio.h>
#include <string.h>

bool PicHex::pic_hex_read_file(const char* filename)
{
printf("extracting pic hex application data\n");
if (!pic_hex_extract_application(filename)) {
return false;
}
printf("extracting pic hex configuration data\n");
if (!pic_hex_extract_configuration(filename)) {
return false;
}
return true;
}

bool PicHex::pic_hex_extract_application(const char* filename)
{
ihex_recordset_t* record_set = ihex_rs_from_file(filename);

if (record_set == 0) {
printf("failed to read recordset from file %s\n", filename);
return false;
}

bool ret = pic_hex_mem_cpy(
record_set, pic_hex_application_data, sizeof(pic_hex_application_data), PROGRAM_MEMORY_OFFSET);
ihex_rs_free(record_set);
return ret;
}

bool PicHex::pic_hex_extract_configuration(const char* filename)
{
ihex_recordset_t* record_set = ihex_rs_from_file(filename);

if (record_set == 0) {
printf("failed to read recordset from file %s\n", filename);
return false;
}

bool ret = pic_hex_mem_cpy(
record_set, pic_hex_configuration_data, sizeof(pic_hex_configuration_data), CONFIGURATION_MEMORY_OFFSET);
ihex_rs_free(record_set);
return ret;
}

/*
* Address equations for your convenience:
*
* | ihex | pic | data |
* | 0x000000 | 0x000000 | 0x000000 |
* | 0x000800 | 0x000400 | 0x000600 |
* | 0x001000 | 0x000800 | 0x000c00 |
* | 0x001800 | 0x000c00 | 0x001200 |
* | 0x002000 | 0x001000 | 0x001800 |
*/
bool PicHex::pic_hex_mem_cpy(ihex_recordset_t* record_set, uint8_t* destination, uint32_t length, uint32_t offset)
{
uint_t i = 0; // current record #
uint32_t record_offset, record_address = 0x00;

// record iterator
ihex_record_t* record;

// zero-initialize destination data
memset(destination, 0, length);

do {
int r = ihex_rs_iterate_data(record_set, &i, &record, &record_offset);

// check error code
if (r) {
return false;
// check record is valid
} else if (record == 0) {
// we reached the end of the list
break;
}

////////////////////////////
// hex contains 16 bit words, addressed to 16 bit memory
////////////////////////////

// get the record address
record_address = (record_offset + record->ihr_address);

///////////////////////////////////////////
// memory contains 24 bit words, addressed to 32 bit memory (address/2)
///////////////////////////////////////////

record_address = record_address / 2;

// record out of range low
if (record_address < offset) {
// printf("warn, record %d address %08x below offset %08x\r\n", i, record_address, offset);
continue;
}

// record out of range high
if (record_address >= offset + length) {
// printf("warn, record %d address %08x beyond range %08x + %08x\r\n", i, record_address, offset, length);
continue;
}

//////////////////////////////////////////////////
// transmit data array contains 24 bit words *(3/2)
//////////////////////////////////////////////////

uint32_t destination_address = (3 * (record_address - offset)) / 2;

// record out of range high
if (destination_address >= length) {
// printf("warn, destination address %08x beyond range %08x + %08x\r\n", destination_address, offset,
// length);
continue;
}

for (int j = 0; j < record->ihr_length; j += 4) {
uint32_t destination_offset = destination_address + j - (j / 4);
if (destination_offset > length) {
// printf("warn, destination offset %08x beyond destination length %d", destination_offset, length);
continue;
}
// pointer to destination byte
uint8_t* target = (uint8_t*)(destination + destination_offset);

// copy a 24 bit word
for (int l = 0; (l < 3); l++) {

*(target++) = record->ihr_data[j + l];
}
}
} while (i > 0);

return true;
}
43 changes: 43 additions & 0 deletions src/flash/pic-hex.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#pragma once

#include <cintelhex.h>

/**
* @brief facilities to convert an intel hex to PIC microcontroller memory space
*/
class PicHex {
public:
// 86 pages * 512 words * 3 bytes
static const uint32_t PROGRAM_MEMORY_SIZE = 0x20400;
static const uint32_t PROGRAM_MEMORY_OFFSET = 0x0;

// 24 bytes configuration in separate memory region
static const uint32_t CONFIGURATION_MEMORY_SIZE = 24;
static const uint32_t CONFIGURATION_MEMORY_OFFSET = 0x00F80000;

/**
* @brief read a hex file and extract the firmware application and configuration data
* @param filename
* @return true if application and configuration data were successfully extracted
*/
bool pic_hex_read_file(const char* filename);

/**
* @brief The hex file data for the application memory region
* this data is valid if pic_hex_read_file returns true
*/
uint8_t pic_hex_application_data[PROGRAM_MEMORY_SIZE];

/**
* @brief The hex file data for the configuration memory region
* The configuration memory region is located at CONFIGURATION_MEMORY_OFFSET
* and is CONFIGURATION_MEMORY_SIZE bytes wide
* this data is valid if pic_hex_read_file returns true
*/
uint8_t pic_hex_configuration_data[CONFIGURATION_MEMORY_SIZE];

private:
bool pic_hex_mem_cpy(ihex_recordset_t* record_set, uint8_t* destination, uint32_t length, uint32_t offset);
bool pic_hex_extract_application(const char* filename);
bool pic_hex_extract_configuration(const char* filename);
};