Main thread using FreeRTOS notifications, added missing commands for firmware update
This commit is contained in:
parent
07ba714f1f
commit
8c33ae523a
Binary file not shown.
@ -157,6 +157,30 @@ bool Device::SendFirmwareChunk(Protocol::FirmwarePacket &fw)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Device::SendCommandWithoutPayload(Protocol::PacketType type)
|
||||||
|
{
|
||||||
|
if(m_connected) {
|
||||||
|
unsigned char buffer[32];
|
||||||
|
Protocol::PacketInfo p;
|
||||||
|
p.type = type;
|
||||||
|
unsigned int length = Protocol::EncodePacket(p, buffer, sizeof(buffer));
|
||||||
|
if(!length) {
|
||||||
|
qCritical() << "Failed to encode packet";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
int actual_length;
|
||||||
|
auto ret = libusb_bulk_transfer(m_handle, EP_Data_Out_Addr, buffer, length, &actual_length, 0);
|
||||||
|
if(ret < 0) {
|
||||||
|
qCritical() << "Error sending data: "
|
||||||
|
<< libusb_strerror((libusb_error) ret);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<QString> Device::GetDevices()
|
std::vector<QString> Device::GetDevices()
|
||||||
{
|
{
|
||||||
std::vector<QString> serials;
|
std::vector<QString> serials;
|
||||||
|
@ -48,6 +48,7 @@ public:
|
|||||||
bool Configure(Protocol::SweepSettings settings);
|
bool Configure(Protocol::SweepSettings settings);
|
||||||
bool SetManual(Protocol::ManualControl manual);
|
bool SetManual(Protocol::ManualControl manual);
|
||||||
bool SendFirmwareChunk(Protocol::FirmwarePacket &fw);
|
bool SendFirmwareChunk(Protocol::FirmwarePacket &fw);
|
||||||
|
bool SendCommandWithoutPayload(Protocol::PacketType type);
|
||||||
// Returns serial numbers of all connected devices
|
// Returns serial numbers of all connected devices
|
||||||
static std::vector<QString> GetDevices();
|
static std::vector<QString> GetDevices();
|
||||||
QString serial() const;
|
QString serial() const;
|
||||||
|
@ -62,7 +62,7 @@ void FirmwareUpdateDialog::on_bStart_clicked()
|
|||||||
}
|
}
|
||||||
state = State::ErasingFLASH;
|
state = State::ErasingFLASH;
|
||||||
addStatus("Erasing device memory...");
|
addStatus("Erasing device memory...");
|
||||||
// TODO issue write command
|
dev.SendCommandWithoutPayload(Protocol::PacketType::ClearFlash);
|
||||||
timer.start(10000);
|
timer.start(10000);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,7 +105,7 @@ void FirmwareUpdateDialog::receivedAck()
|
|||||||
// complete file transferred
|
// complete file transferred
|
||||||
addStatus("Triggering device update...");
|
addStatus("Triggering device update...");
|
||||||
state = State::TriggeringUpdate;
|
state = State::TriggeringUpdate;
|
||||||
// TODO trigger update
|
dev.SendCommandWithoutPayload(Protocol::PacketType::PerformFirmwareUpdate);
|
||||||
timer.start(5000);
|
timer.start(5000);
|
||||||
}
|
}
|
||||||
sendNextFirmwareChunk();
|
sendNextFirmwareChunk();
|
||||||
@ -113,7 +113,7 @@ void FirmwareUpdateDialog::receivedAck()
|
|||||||
break;
|
break;
|
||||||
case State::TriggeringUpdate:
|
case State::TriggeringUpdate:
|
||||||
addStatus("Rebooting device...");
|
addStatus("Rebooting device...");
|
||||||
// TODO listen for detected device
|
// TODO delete current device and listen for reconnect
|
||||||
state = State::Idle;
|
state = State::Idle;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -124,4 +124,5 @@ void FirmwareUpdateDialog::sendNextFirmwareChunk()
|
|||||||
Protocol::FirmwarePacket fw;
|
Protocol::FirmwarePacket fw;
|
||||||
fw.address = transferredBytes;
|
fw.address = transferredBytes;
|
||||||
file->read((char*) &fw.data, Protocol::FirmwareChunkSize);
|
file->read((char*) &fw.data, Protocol::FirmwareChunkSize);
|
||||||
|
dev.SendFirmwareChunk(fw);
|
||||||
}
|
}
|
||||||
|
@ -11,21 +11,22 @@
|
|||||||
#include "USB/usb.h"
|
#include "USB/usb.h"
|
||||||
#include "Flash.hpp"
|
#include "Flash.hpp"
|
||||||
#include "Firmware.hpp"
|
#include "Firmware.hpp"
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
#include "task.h"
|
||||||
|
|
||||||
#define LOG_LEVEL LOG_LEVEL_INFO
|
#define LOG_LEVEL LOG_LEVEL_INFO
|
||||||
#define LOG_MODULE "App"
|
#define LOG_MODULE "App"
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
|
|
||||||
static volatile bool newResult;
|
|
||||||
static Protocol::Datapoint result;
|
static Protocol::Datapoint result;
|
||||||
static volatile bool newSettings = false;
|
|
||||||
static Protocol::SweepSettings settings;
|
static Protocol::SweepSettings settings;
|
||||||
|
|
||||||
static volatile bool newStatus = false;
|
|
||||||
static FPGA::SamplingResult statusResult;
|
static FPGA::SamplingResult statusResult;
|
||||||
static volatile bool newManual = false;
|
|
||||||
static Protocol::ManualControl manual;
|
static Protocol::ManualControl manual;
|
||||||
|
|
||||||
|
static Protocol::PacketInfo packet;
|
||||||
|
static TaskHandle_t handle;
|
||||||
|
|
||||||
// TODO set proper values
|
// TODO set proper values
|
||||||
#define HW_REVISION 'A'
|
#define HW_REVISION 'A'
|
||||||
#define FW_MAJOR 0
|
#define FW_MAJOR 0
|
||||||
@ -34,18 +35,34 @@ static Protocol::ManualControl manual;
|
|||||||
extern SPI_HandleTypeDef hspi1;
|
extern SPI_HandleTypeDef hspi1;
|
||||||
static Flash flash = Flash(&hspi1, FLASH_CS_GPIO_Port, FLASH_CS_Pin);
|
static Flash flash = Flash(&hspi1, FLASH_CS_GPIO_Port, FLASH_CS_Pin);
|
||||||
|
|
||||||
void VNACallback(Protocol::Datapoint res) {
|
#define FLAG_USB_PACKET 0x01
|
||||||
|
#define FLAG_DATAPOINT 0x02
|
||||||
|
#define FLAG_STATUSRESULT 0x04
|
||||||
|
|
||||||
|
static void VNACallback(Protocol::Datapoint res) {
|
||||||
result = res;
|
result = res;
|
||||||
newResult = true;
|
BaseType_t woken = false;
|
||||||
|
xTaskNotifyFromISR(handle, FLAG_DATAPOINT, eSetBits, &woken);
|
||||||
|
portYIELD_FROM_ISR(woken);
|
||||||
}
|
}
|
||||||
void VNAStatusCallback(FPGA::SamplingResult res) {
|
static void VNAStatusCallback(FPGA::SamplingResult res) {
|
||||||
statusResult = res;
|
statusResult = res;
|
||||||
newStatus = true;
|
BaseType_t woken = false;
|
||||||
|
xTaskNotifyFromISR(handle, FLAG_STATUSRESULT, eSetBits, &woken);
|
||||||
|
portYIELD_FROM_ISR(woken);
|
||||||
|
}
|
||||||
|
static void USBPacketReceived(Protocol::PacketInfo p) {
|
||||||
|
packet = p;
|
||||||
|
BaseType_t woken = false;
|
||||||
|
xTaskNotifyFromISR(handle, FLAG_USB_PACKET, eSetBits, &woken);
|
||||||
|
portYIELD_FROM_ISR(woken);
|
||||||
}
|
}
|
||||||
|
|
||||||
void App_Start() {
|
void App_Start() {
|
||||||
|
handle = xTaskGetCurrentTaskHandle();
|
||||||
usb_init(communication_usb_input);
|
usb_init(communication_usb_input);
|
||||||
Log_Init();
|
Log_Init();
|
||||||
|
Communication::SetCallback(USBPacketReceived);
|
||||||
// Pass on logging output to USB
|
// Pass on logging output to USB
|
||||||
Log_SetRedirect(usb_log);
|
Log_SetRedirect(usb_log);
|
||||||
LOG_INFO("Start");
|
LOG_INFO("Start");
|
||||||
@ -66,19 +83,19 @@ void App_Start() {
|
|||||||
if (!VNA::Init()) {
|
if (!VNA::Init()) {
|
||||||
LOG_CRIT("Initialization failed, unable to start");
|
LOG_CRIT("Initialization failed, unable to start");
|
||||||
}
|
}
|
||||||
// Allow USB enumeration
|
|
||||||
// USB_EN_GPIO_Port->BSRR = USB_EN_Pin;
|
|
||||||
|
|
||||||
uint32_t lastNewPoint = HAL_GetTick();
|
uint32_t lastNewPoint = HAL_GetTick();
|
||||||
bool sweepActive = false;
|
bool sweepActive = false;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
if (newResult) {
|
uint32_t notification;
|
||||||
|
if(xTaskNotifyWait(0x00, UINT32_MAX, ¬ification, 100) == pdPASS) {
|
||||||
|
// something happened
|
||||||
|
if(notification & FLAG_DATAPOINT) {
|
||||||
Protocol::PacketInfo packet;
|
Protocol::PacketInfo packet;
|
||||||
packet.type = Protocol::PacketType::Datapoint;
|
packet.type = Protocol::PacketType::Datapoint;
|
||||||
packet.datapoint = result;
|
packet.datapoint = result;
|
||||||
Communication::Send(packet);
|
Communication::Send(packet);
|
||||||
newResult = false;
|
|
||||||
lastNewPoint = HAL_GetTick();
|
lastNewPoint = HAL_GetTick();
|
||||||
if(result.pointNum == settings.points - 1) {
|
if(result.pointNum == settings.points - 1) {
|
||||||
// end of sweep
|
// end of sweep
|
||||||
@ -119,29 +136,7 @@ void App_Start() {
|
|||||||
FPGA::StartSweep();
|
FPGA::StartSweep();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (newSettings) {
|
if(notification & FLAG_STATUSRESULT) {
|
||||||
LOG_INFO("New settings received");
|
|
||||||
newSettings = false;
|
|
||||||
VNA::ConfigureSweep(settings, VNACallback);
|
|
||||||
sweepActive = true;
|
|
||||||
lastNewPoint = HAL_GetTick();
|
|
||||||
}
|
|
||||||
if(sweepActive && HAL_GetTick() - lastNewPoint > 1000) {
|
|
||||||
LOG_WARN("Timed out waiting for point, last received point was %d", result.pointNum);
|
|
||||||
LOG_WARN("FPGA status: 0x%04x", FPGA::GetStatus());
|
|
||||||
// restart the current sweep
|
|
||||||
VNA::ConfigureSweep(settings, VNACallback);
|
|
||||||
sweepActive = true;
|
|
||||||
lastNewPoint = HAL_GetTick();
|
|
||||||
}
|
|
||||||
if (newManual) {
|
|
||||||
LOG_INFO("New manual control");
|
|
||||||
sweepActive = false;
|
|
||||||
newManual = false;
|
|
||||||
VNA::ConfigureManual(manual, VNAStatusCallback);
|
|
||||||
}
|
|
||||||
if (newStatus) {
|
|
||||||
newStatus = false;
|
|
||||||
Protocol::PacketInfo p;
|
Protocol::PacketInfo p;
|
||||||
p.type = Protocol::PacketType::Status;
|
p.type = Protocol::PacketType::Status;
|
||||||
memset(&p.status, 0, sizeof(p.status));
|
memset(&p.status, 0, sizeof(p.status));
|
||||||
@ -171,15 +166,67 @@ void App_Start() {
|
|||||||
// Trigger next status update
|
// Trigger next status update
|
||||||
FPGA::StartSweep();
|
FPGA::StartSweep();
|
||||||
}
|
}
|
||||||
|
if(notification & FLAG_USB_PACKET) {
|
||||||
|
switch(packet.type) {
|
||||||
|
case Protocol::PacketType::SweepSettings:
|
||||||
|
LOG_INFO("New settings received");
|
||||||
|
settings = packet.settings;
|
||||||
|
VNA::ConfigureSweep(settings, VNACallback);
|
||||||
|
sweepActive = true;
|
||||||
|
lastNewPoint = HAL_GetTick();
|
||||||
|
break;
|
||||||
|
case Protocol::PacketType::ManualControl:
|
||||||
|
sweepActive = false;
|
||||||
|
manual = packet.manual;
|
||||||
|
VNA::ConfigureManual(manual, VNAStatusCallback);
|
||||||
|
break;
|
||||||
|
case Protocol::PacketType::ClearFlash:
|
||||||
|
FPGA::AbortSweep();
|
||||||
|
sweepActive = false;
|
||||||
|
LOG_DEBUG("Erasing FLASH in preparation for firmware update...");
|
||||||
|
if(flash.eraseChip()) {
|
||||||
|
LOG_DEBUG("...FLASH erased")
|
||||||
|
Protocol::PacketInfo p;
|
||||||
|
p.type = Protocol::PacketType::Ack;
|
||||||
|
Communication::Send(p);
|
||||||
|
} else {
|
||||||
|
LOG_ERR("Failed to erase FLASH");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Protocol::PacketType::FirmwarePacket:
|
||||||
|
LOG_INFO("Writing firmware packet at address %u", packet.firmware.address);
|
||||||
|
flash.write(packet.firmware.address, sizeof(packet.firmware.data), packet.firmware.data);
|
||||||
|
Protocol::PacketInfo p;
|
||||||
|
p.type = Protocol::PacketType::Ack;
|
||||||
|
Communication::Send(p);
|
||||||
|
break;
|
||||||
|
case Protocol::PacketType::PerformFirmwareUpdate: {
|
||||||
|
auto fw_info = Firmware::GetFlashContentInfo(&flash);
|
||||||
|
if(fw_info.valid) {
|
||||||
|
Protocol::PacketInfo p;
|
||||||
|
p.type = Protocol::PacketType::Ack;
|
||||||
|
Communication::Send(p);
|
||||||
|
// Some delay to allow communication to finish
|
||||||
|
vTaskDelay(1000);
|
||||||
|
Firmware::PerformUpdate(&flash);
|
||||||
|
// will never get here
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// ignore all other packets
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void App::NewSettings(Protocol::SweepSettings s) {
|
if(sweepActive && HAL_GetTick() - lastNewPoint > 1000) {
|
||||||
settings = s;
|
LOG_WARN("Timed out waiting for point, last received point was %d", result.pointNum);
|
||||||
newSettings = true;
|
LOG_WARN("FPGA status: 0x%04x", FPGA::GetStatus());
|
||||||
|
// restart the current sweep
|
||||||
|
VNA::ConfigureSweep(settings, VNACallback);
|
||||||
|
sweepActive = true;
|
||||||
|
lastNewPoint = HAL_GetTick();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void App::SetManual(Protocol::ManualControl m) {
|
|
||||||
manual = m;
|
|
||||||
newManual = true;
|
|
||||||
}
|
}
|
||||||
|
@ -3,13 +3,6 @@
|
|||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
#include "Protocol.hpp"
|
#include "Protocol.hpp"
|
||||||
|
|
||||||
namespace App {
|
|
||||||
|
|
||||||
void NewSettings(Protocol::SweepSettings s);
|
|
||||||
void SetManual(Protocol::ManualControl m);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -9,10 +9,12 @@ static uint8_t inputBuffer[1024];
|
|||||||
uint16_t inputCnt = 0;
|
uint16_t inputCnt = 0;
|
||||||
static uint8_t outputBuffer[1024];
|
static uint8_t outputBuffer[1024];
|
||||||
|
|
||||||
//#include "usbd_def.h"
|
static Communication::Callback callback = nullptr;
|
||||||
//#include "usbd_cdc_if.h"
|
|
||||||
|
void Communication::SetCallback(Callback cb) {
|
||||||
|
callback = cb;
|
||||||
|
}
|
||||||
|
|
||||||
//extern USBD_HandleTypeDef hUsbDeviceFS;
|
|
||||||
|
|
||||||
void Communication::Input(const uint8_t *buf, uint16_t len) {
|
void Communication::Input(const uint8_t *buf, uint16_t len) {
|
||||||
if (inputCnt + len < sizeof(inputBuffer)) {
|
if (inputCnt + len < sizeof(inputBuffer)) {
|
||||||
@ -33,13 +35,10 @@ void Communication::Input(const uint8_t *buf, uint16_t len) {
|
|||||||
memmove(inputBuffer, &inputBuffer[handled_len], remaining);
|
memmove(inputBuffer, &inputBuffer[handled_len], remaining);
|
||||||
inputCnt = remaining;
|
inputCnt = remaining;
|
||||||
}
|
}
|
||||||
switch(packet.type) {
|
if(packet.type != Protocol::PacketType::None) {
|
||||||
case Protocol::PacketType::SweepSettings:
|
if(callback) {
|
||||||
App::NewSettings(packet.settings);
|
callback(packet);
|
||||||
break;
|
}
|
||||||
case Protocol::PacketType::ManualControl:
|
|
||||||
App::SetManual(packet.manual);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
} while (handled_len > 0);
|
} while (handled_len > 0);
|
||||||
}
|
}
|
||||||
@ -63,3 +62,4 @@ bool Communication::Send(Protocol::PacketInfo packet) {
|
|||||||
void communication_usb_input(const uint8_t *buf, uint16_t len) {
|
void communication_usb_input(const uint8_t *buf, uint16_t len) {
|
||||||
Communication::Input(buf, len);
|
Communication::Input(buf, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,6 +8,9 @@
|
|||||||
|
|
||||||
namespace Communication {
|
namespace Communication {
|
||||||
|
|
||||||
|
using Callback = void(*)(Protocol::PacketInfo);
|
||||||
|
|
||||||
|
void SetCallback(Callback cb);
|
||||||
void Input(const uint8_t *buf, uint16_t len);
|
void Input(const uint8_t *buf, uint16_t len);
|
||||||
bool Send(Protocol::PacketInfo packet);
|
bool Send(Protocol::PacketInfo packet);
|
||||||
|
|
||||||
|
@ -401,6 +401,8 @@ uint16_t Protocol::DecodeBuffer(uint8_t *buf, uint16_t len, PacketInfo *info) {
|
|||||||
info->firmware = DecodeFirmwarePacket(&data[4]);
|
info->firmware = DecodeFirmwarePacket(&data[4]);
|
||||||
break;
|
break;
|
||||||
case PacketType::Ack:
|
case PacketType::Ack:
|
||||||
|
case PacketType::PerformFirmwareUpdate:
|
||||||
|
case PacketType::ClearFlash:
|
||||||
// no payload, nothing to do
|
// no payload, nothing to do
|
||||||
break;
|
break;
|
||||||
case PacketType::None:
|
case PacketType::None:
|
||||||
@ -432,6 +434,8 @@ uint16_t Protocol::EncodePacket(PacketInfo packet, uint8_t *dest, uint16_t dests
|
|||||||
payload_size = EncodeFirmwarePacket(packet.firmware, &dest[4], destsize - 8);
|
payload_size = EncodeFirmwarePacket(packet.firmware, &dest[4], destsize - 8);
|
||||||
break;
|
break;
|
||||||
case PacketType::Ack:
|
case PacketType::Ack:
|
||||||
|
case PacketType::PerformFirmwareUpdate:
|
||||||
|
case PacketType::ClearFlash:
|
||||||
// no payload, nothing to do
|
// no payload, nothing to do
|
||||||
break;
|
break;
|
||||||
case PacketType::None:
|
case PacketType::None:
|
||||||
|
@ -91,14 +91,16 @@ using FirmwarePacket = struct _firmwarePacket {
|
|||||||
};
|
};
|
||||||
|
|
||||||
enum class PacketType : uint8_t {
|
enum class PacketType : uint8_t {
|
||||||
None,
|
None = 0,
|
||||||
Datapoint,
|
Datapoint = 1,
|
||||||
SweepSettings,
|
SweepSettings = 2,
|
||||||
Status,
|
Status = 3,
|
||||||
ManualControl,
|
ManualControl = 4,
|
||||||
DeviceInfo,
|
DeviceInfo = 5,
|
||||||
FirmwarePacket,
|
FirmwarePacket = 6,
|
||||||
Ack,
|
Ack = 7,
|
||||||
|
ClearFlash = 8,
|
||||||
|
PerformFirmwareUpdate = 9,
|
||||||
};
|
};
|
||||||
|
|
||||||
using PacketInfo = struct _packetinfo {
|
using PacketInfo = struct _packetinfo {
|
||||||
|
@ -21,7 +21,7 @@ public:
|
|||||||
bool eraseChip();
|
bool eraseChip();
|
||||||
// Starts the reading process without actually reading any bytes
|
// Starts the reading process without actually reading any bytes
|
||||||
void initiateRead(uint32_t address);
|
void initiateRead(uint32_t address);
|
||||||
const SPI_HandleTypeDef* const& getSpi() const {
|
const SPI_HandleTypeDef* const getSpi() const {
|
||||||
return spi;
|
return spi;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user