mirror of
https://github.com/jankae/LibreVNA.git
synced 2026-04-08 16:03:43 +00:00
Bugfixes and improvements for new hardware
This commit is contained in:
parent
7d9d5e27eb
commit
4cbd60e62d
33 changed files with 747 additions and 193 deletions
|
|
@ -12,6 +12,7 @@
|
|||
#include "Flash.hpp"
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "Led.hpp"
|
||||
|
||||
#define LOG_LEVEL LOG_LEVEL_INFO
|
||||
#define LOG_MODULE "App"
|
||||
|
|
@ -66,6 +67,8 @@ void App_Start() {
|
|||
handle = xTaskGetCurrentTaskHandle();
|
||||
usb_init(communication_usb_input);
|
||||
Log_Init();
|
||||
LED::Init();
|
||||
LED::Pulsating();
|
||||
Communication::SetCallback(USBPacketReceived);
|
||||
// Pass on logging output to USB
|
||||
Log_SetRedirect(usb_log);
|
||||
|
|
@ -74,23 +77,34 @@ void App_Start() {
|
|||
#ifdef HAS_FLASH
|
||||
if(!flash.isPresent()) {
|
||||
LOG_CRIT("Failed to detect onboard FLASH");
|
||||
LED::Error(1);
|
||||
}
|
||||
auto fw_info = Firmware::GetFlashContentInfo(&flash);
|
||||
if(fw_info.valid) {
|
||||
if(fw_info.CPU_need_update) {
|
||||
// Function will not return, the device will reboot with the new firmware instead
|
||||
Firmware::PerformUpdate(&flash);
|
||||
// Firmware::PerformUpdate(&flash, fw_info);
|
||||
}
|
||||
if(!FPGA::Configure(&flash, fw_info.FPGA_bitstream_address, fw_info.FPGA_bitstream_size)) {
|
||||
LOG_CRIT("FPGA configuration failed");
|
||||
LED::Error(3);
|
||||
}
|
||||
FPGA::Configure(&flash, fw_info.FPGA_bitstream_address, fw_info.FPGA_bitstream_size);
|
||||
} else {
|
||||
LOG_CRIT("Invalid bitstream/firmware, not configuring FPGA");
|
||||
LED::Error(2);
|
||||
}
|
||||
#else
|
||||
// The FPGA configures itself from the flash, allow time for this
|
||||
vTaskDelay(2000);
|
||||
#endif
|
||||
#if HW_REVISION == 'B'
|
||||
// Enable supply to RF circuit
|
||||
EN_6V_GPIO_Port->BSRR = EN_6V_Pin;
|
||||
#endif
|
||||
|
||||
if (!VNA::Init()) {
|
||||
LOG_CRIT("Initialization failed, unable to start");
|
||||
LED::Error(4);
|
||||
}
|
||||
|
||||
#if HW_REVISION == 'A'
|
||||
|
|
@ -102,6 +116,7 @@ void App_Start() {
|
|||
bool sweepActive = false;
|
||||
Protocol::ReferenceSettings reference;
|
||||
|
||||
LED::Off();
|
||||
while (1) {
|
||||
uint32_t notification;
|
||||
if(xTaskNotifyWait(0x00, UINT32_MAX, ¬ification, 100) == pdPASS) {
|
||||
|
|
@ -190,7 +205,7 @@ void App_Start() {
|
|||
break;
|
||||
#ifdef HAS_FLASH
|
||||
case Protocol::PacketType::ClearFlash:
|
||||
FPGA::AbortSweep();
|
||||
VNA::SetIdle();
|
||||
sweepActive = false;
|
||||
LOG_DEBUG("Erasing FLASH in preparation for firmware update...");
|
||||
if(flash.eraseChip()) {
|
||||
|
|
@ -203,10 +218,15 @@ void App_Start() {
|
|||
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);
|
||||
Communication::SendWithoutPayload(Protocol::PacketType::Ack);
|
||||
if(flash.write(packet.firmware.address, sizeof(packet.firmware.data), packet.firmware.data)) {
|
||||
Communication::SendWithoutPayload(Protocol::PacketType::Ack);
|
||||
} else {
|
||||
LOG_ERR("Failed to write FLASH");
|
||||
Communication::SendWithoutPayload(Protocol::PacketType::Nack);
|
||||
}
|
||||
break;
|
||||
case Protocol::PacketType::PerformFirmwareUpdate: {
|
||||
LOG_INFO("Firmware update process triggered");
|
||||
auto fw_info = Firmware::GetFlashContentInfo(&flash);
|
||||
if(fw_info.valid) {
|
||||
Protocol::PacketInfo p;
|
||||
|
|
@ -214,7 +234,7 @@ void App_Start() {
|
|||
Communication::Send(p);
|
||||
// Some delay to allow communication to finish
|
||||
vTaskDelay(1000);
|
||||
Firmware::PerformUpdate(&flash);
|
||||
Firmware::PerformUpdate(&flash, fw_info);
|
||||
// should never get here
|
||||
Communication::SendWithoutPayload(Protocol::PacketType::Nack);
|
||||
}
|
||||
|
|
@ -230,8 +250,7 @@ void App_Start() {
|
|||
}
|
||||
|
||||
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());
|
||||
LOG_WARN("Timed out waiting for point, last received point was %d (Status 0x%04x)", result.pointNum, FPGA::GetStatus());
|
||||
FPGA::AbortSweep();
|
||||
// restart the current sweep
|
||||
VNA::Init();
|
||||
|
|
|
|||
|
|
@ -14,10 +14,17 @@ static uint16_t ISRMaskReg = 0x0000;
|
|||
|
||||
using namespace FPGAHAL;
|
||||
|
||||
static void SwitchBytes(uint16_t &value) {
|
||||
value = (value & 0xFF00) >> 8 | (value & 0x00FF) << 8;
|
||||
}
|
||||
static void SwitchBytes(int16_t &value) {
|
||||
value = (value & 0xFF00) >> 8 | (value & 0x00FF) << 8;
|
||||
}
|
||||
|
||||
void WriteRegister(FPGA::Reg reg, uint16_t value) {
|
||||
uint16_t cmd[2] = {(uint16_t) (0x8000 | (uint16_t) reg), value};
|
||||
uint8_t cmd[4] = {0x80, (uint8_t) reg, (uint8_t) (value >> 8), (uint8_t) (value & 0xFF)};
|
||||
Low(CS);
|
||||
HAL_SPI_Transmit(&FPGA_SPI, (uint8_t*) cmd, 2, 100);
|
||||
HAL_SPI_Transmit(&FPGA_SPI, (uint8_t*) cmd, 4, 100);
|
||||
High(CS);
|
||||
}
|
||||
|
||||
|
|
@ -34,8 +41,18 @@ bool FPGA::Configure(Flash *f, uint32_t start_address, uint32_t bitstream_size)
|
|||
High(PROGRAM_B);
|
||||
while(!isHigh(INIT_B));
|
||||
|
||||
if(isHigh(DONE)) {
|
||||
LOG_ERR("DONE not asserted, aborting configuration");
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t lastmessage = HAL_GetTick();
|
||||
uint8_t buf[256];
|
||||
while(bitstream_size > 0) {
|
||||
if(HAL_GetTick() - lastmessage > 100) {
|
||||
LOG_DEBUG("Remaining: %lu", bitstream_size);
|
||||
lastmessage = HAL_GetTick();
|
||||
}
|
||||
uint16_t size = sizeof(buf);
|
||||
if(size > bitstream_size) {
|
||||
size = bitstream_size;
|
||||
|
|
@ -73,18 +90,20 @@ bool FPGA::Init(HaltedCallback cb) {
|
|||
Delay::ms(10);
|
||||
|
||||
// Check if FPGA response is as expected
|
||||
uint16_t cmd[2] = {0x4000, 0x0000};
|
||||
uint16_t recv[2];
|
||||
uint8_t cmd[4] = {0x40, 0x00, 0x00, 0x00};
|
||||
uint8_t recv[4];
|
||||
Low(CS);
|
||||
HAL_SPI_TransmitReceive(&FPGA_SPI, (uint8_t*) cmd, (uint8_t*) recv, 2, 100);
|
||||
HAL_SPI_TransmitReceive(&FPGA_SPI, (uint8_t*) cmd, (uint8_t*) recv, 4, 100);
|
||||
High(CS);
|
||||
|
||||
if(recv[1] != 0xF0A5) {
|
||||
LOG_ERR("Initialization failed, got 0x%04x instead of 0xF0A5", recv[1]);
|
||||
uint16_t resp = (uint16_t) recv[2] << 8 | recv[3];
|
||||
uint16_t status = (uint16_t) recv[0] << 8 | recv[1];
|
||||
if(resp != 0xF0A5) {
|
||||
LOG_ERR("Initialization failed, got 0x%04x instead of 0xF0A5", resp);
|
||||
return false;
|
||||
}
|
||||
|
||||
LOG_DEBUG("Initialized, status register: 0x%04x", recv[0]);
|
||||
LOG_DEBUG("Initialized, status register: 0x%04x", status);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -183,8 +202,15 @@ void FPGA::WriteSweepConfig(uint16_t pointnum, bool lowband, uint32_t *SourceReg
|
|||
}
|
||||
send[5] = (Source_M & 0x000F) << 12 | Source_FRAC;
|
||||
send[6] = Source_DIV_A << 13 | Source_VCO << 7 | Source_N;
|
||||
SwitchBytes(send[0]);
|
||||
SwitchBytes(send[1]);
|
||||
SwitchBytes(send[2]);
|
||||
SwitchBytes(send[3]);
|
||||
SwitchBytes(send[4]);
|
||||
SwitchBytes(send[5]);
|
||||
SwitchBytes(send[6]);
|
||||
Low(CS);
|
||||
HAL_SPI_Transmit(&FPGA_SPI, (uint8_t*) send, 7, 100);
|
||||
HAL_SPI_Transmit(&FPGA_SPI, (uint8_t*) send, 14, 100);
|
||||
High(CS);
|
||||
}
|
||||
|
||||
|
|
@ -194,17 +220,18 @@ static inline int64_t sign_extend_64(int64_t x, uint16_t bits) {
|
|||
}
|
||||
|
||||
static FPGA::ReadCallback callback;
|
||||
static uint16_t raw[18];
|
||||
static uint8_t raw[36];
|
||||
static bool halted;
|
||||
|
||||
bool FPGA::InitiateSampleRead(ReadCallback cb) {
|
||||
callback = cb;
|
||||
uint16_t cmd = 0xC000;
|
||||
uint8_t cmd[2] = {0xC0, 0x00};
|
||||
uint16_t status;
|
||||
|
||||
Low(CS);
|
||||
HAL_SPI_TransmitReceive(&FPGA_SPI, (uint8_t*) &cmd, (uint8_t*) &status, 1,
|
||||
100);
|
||||
HAL_SPI_TransmitReceive(&FPGA_SPI, cmd, (uint8_t*) &status, 2, 100);
|
||||
|
||||
SwitchBytes(status);
|
||||
|
||||
if (status & 0x0010) {
|
||||
halted = true;
|
||||
|
|
@ -227,27 +254,28 @@ bool FPGA::InitiateSampleRead(ReadCallback cb) {
|
|||
}
|
||||
|
||||
// Start data read
|
||||
HAL_SPI_Receive_DMA(&FPGA_SPI, (uint8_t*) raw, 18);
|
||||
HAL_SPI_Receive_DMA(&FPGA_SPI, raw, 36);
|
||||
return true;
|
||||
}
|
||||
|
||||
static int64_t assembleSampleResultValue(uint8_t *raw) {
|
||||
return sign_extend_64(
|
||||
(uint16_t) raw[0] << 8 | raw[1] | (uint32_t) raw[2] << 24
|
||||
| (uint32_t) raw[3] << 16 | (uint64_t) raw[4] << 40
|
||||
| (uint64_t) raw[5] << 32, 48);
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi) {
|
||||
FPGA::SamplingResult result;
|
||||
High(CS);
|
||||
// Assemble data from words
|
||||
result.P1I = sign_extend_64(
|
||||
(uint64_t) raw[17] << 32 | (uint32_t) raw[16] << 16 | raw[15], 48);
|
||||
result.P1Q = sign_extend_64(
|
||||
(uint64_t) raw[14] << 32 | (uint32_t) raw[13] << 16 | raw[12], 48);
|
||||
result.P2I = sign_extend_64(
|
||||
(uint64_t) raw[11] << 32 | (uint32_t) raw[10] << 16 | raw[9], 48);
|
||||
result.P2Q = sign_extend_64(
|
||||
(uint64_t) raw[8] << 32 | (uint32_t) raw[7] << 16 | raw[6], 48);
|
||||
result.RefI = sign_extend_64(
|
||||
(uint64_t) raw[5] << 32 | (uint32_t) raw[4] << 16 | raw[3], 48);
|
||||
result.RefQ = sign_extend_64(
|
||||
(uint64_t) raw[2] << 32 | (uint32_t) raw[1] << 16 | raw[0], 48);
|
||||
result.P1I = assembleSampleResultValue(&raw[30]);
|
||||
result.P1Q = assembleSampleResultValue(&raw[24]);
|
||||
result.P2I = assembleSampleResultValue(&raw[18]);
|
||||
result.P2Q = assembleSampleResultValue(&raw[12]);
|
||||
result.RefI = assembleSampleResultValue(&raw[6]);
|
||||
result.RefQ = assembleSampleResultValue(&raw[0]);
|
||||
if (callback) {
|
||||
callback(result);
|
||||
}
|
||||
|
|
@ -293,36 +321,45 @@ void FPGA::SetMode(Mode mode) {
|
|||
}
|
||||
|
||||
uint16_t FPGA::GetStatus() {
|
||||
uint16_t cmd = 0x4000;
|
||||
uint16_t status;
|
||||
uint8_t cmd[2] = {0x40, 0x00};
|
||||
uint8_t status[2];
|
||||
Low(CS);
|
||||
HAL_SPI_TransmitReceive(&FPGA_SPI, (uint8_t*) &cmd, (uint8_t*) &status, 1,
|
||||
HAL_SPI_TransmitReceive(&FPGA_SPI, (uint8_t*) &cmd, (uint8_t*) &status, 2,
|
||||
100);
|
||||
High(CS);
|
||||
return status;
|
||||
return (uint16_t) status[0] << 8 | status[1];
|
||||
}
|
||||
|
||||
FPGA::ADCLimits FPGA::GetADCLimits() {
|
||||
uint16_t cmd = 0xE000;
|
||||
SwitchBytes(cmd);
|
||||
Low(CS);
|
||||
HAL_SPI_Transmit(&FPGA_SPI, (uint8_t*) &cmd, 1, 100);
|
||||
HAL_SPI_Transmit(&FPGA_SPI, (uint8_t*) &cmd, 2, 100);
|
||||
ADCLimits limits;
|
||||
HAL_SPI_Receive(&FPGA_SPI, (uint8_t*) &limits, 6, 100);
|
||||
HAL_SPI_Receive(&FPGA_SPI, (uint8_t*) &limits, 12, 100);
|
||||
High(CS);
|
||||
SwitchBytes(limits.P1max);
|
||||
SwitchBytes(limits.P1min);
|
||||
SwitchBytes(limits.P2max);
|
||||
SwitchBytes(limits.P2min);
|
||||
SwitchBytes(limits.Rmax);
|
||||
SwitchBytes(limits.Rmin);
|
||||
return limits;
|
||||
}
|
||||
|
||||
void FPGA::ResetADCLimits() {
|
||||
uint16_t cmd = 0x6000;
|
||||
SwitchBytes(cmd);
|
||||
Low(CS);
|
||||
HAL_SPI_Transmit(&FPGA_SPI, (uint8_t*) &cmd, 1, 100);
|
||||
HAL_SPI_Transmit(&FPGA_SPI, (uint8_t*) &cmd, 2, 100);
|
||||
High(CS);
|
||||
}
|
||||
|
||||
void FPGA::ResumeHaltedSweep() {
|
||||
uint16_t cmd = 0x2000;
|
||||
SwitchBytes(cmd);
|
||||
Low(CS);
|
||||
HAL_SPI_Transmit(&FPGA_SPI, (uint8_t*) &cmd, 1, 100);
|
||||
HAL_SPI_Transmit(&FPGA_SPI, (uint8_t*) &cmd, 2, 100);
|
||||
High(CS);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,13 @@
|
|||
#include "Flash.hpp"
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include <cstring>
|
||||
|
||||
#define LOG_LEVEL LOG_LEVEL_INFO
|
||||
#define LOG_MODULE "Flash"
|
||||
#include "Log.h"
|
||||
|
||||
bool Flash::isPresent() {
|
||||
CS(false);
|
||||
// read JEDEC ID
|
||||
|
|
@ -24,16 +32,18 @@ void Flash::read(uint32_t address, uint16_t length, void *dest) {
|
|||
bool Flash::write(uint32_t address, uint16_t length, uint8_t *src) {
|
||||
if((address & 0xFF) != 0 || length%256 != 0) {
|
||||
// only writes to complete pages allowed
|
||||
LOG_ERR("Invalid write address/size: %lu/%u", address, length);
|
||||
return false;
|
||||
}
|
||||
address &= 0x00FFFFFF;
|
||||
LOG_DEBUG("Writing %u bytes to address %lu", length, address);
|
||||
while(length > 0) {
|
||||
EnableWrite();
|
||||
CS(false);
|
||||
uint8_t cmd[4] = {
|
||||
0x02,
|
||||
((uint8_t) address >> 16) & 0xFF,
|
||||
((uint8_t) address >> 8) & 0xFF,
|
||||
(uint8_t) (address >> 16) & 0xFF,
|
||||
(uint8_t) (address >> 8) & 0xFF,
|
||||
(uint8_t) (address & 0xFF),
|
||||
};
|
||||
// issue read command
|
||||
|
|
@ -41,9 +51,18 @@ bool Flash::write(uint32_t address, uint16_t length, uint8_t *src) {
|
|||
// write data
|
||||
HAL_SPI_Transmit(spi, src, 256, 1000);
|
||||
CS(true);
|
||||
if(!WaitBusy(5)) {
|
||||
if(!WaitBusy(20)) {
|
||||
LOG_ERR("Write timed out");
|
||||
return false;
|
||||
}
|
||||
// Verify
|
||||
uint8_t buf[256];
|
||||
read(address, 256, buf);
|
||||
if(memcmp(src, buf, 256)) {
|
||||
LOG_ERR("Verification error");
|
||||
return false;
|
||||
}
|
||||
address += 256;
|
||||
length -= 256;
|
||||
src += 256;
|
||||
}
|
||||
|
|
@ -59,6 +78,7 @@ void Flash::EnableWrite() {
|
|||
}
|
||||
|
||||
bool Flash::eraseChip() {
|
||||
LOG_INFO("Erasing...");
|
||||
EnableWrite();
|
||||
CS(false);
|
||||
// enable write latch
|
||||
|
|
@ -73,8 +93,8 @@ void Flash::initiateRead(uint32_t address) {
|
|||
CS(false);
|
||||
uint8_t cmd[4] = {
|
||||
0x03,
|
||||
((uint8_t) address >> 16) & 0xFF,
|
||||
((uint8_t) address >> 8) & 0xFF,
|
||||
(uint8_t) (address >> 16) & 0xFF,
|
||||
(uint8_t) (address >> 8) & 0xFF,
|
||||
(uint8_t) (address & 0xFF),
|
||||
};
|
||||
// issue read command
|
||||
|
|
@ -86,15 +106,17 @@ bool Flash::WaitBusy(uint32_t timeout) {
|
|||
CS(false);
|
||||
uint8_t readStatus1 = 0x05;
|
||||
HAL_SPI_Transmit(spi, &readStatus1, 1, 100);
|
||||
while(HAL_GetTick() - starttime > timeout) {
|
||||
do {
|
||||
vTaskDelay(1);
|
||||
uint8_t status1;
|
||||
HAL_SPI_Receive(spi, &status1, 1, 100);
|
||||
if(!(status1 & 0x01)) {
|
||||
if (!(status1 & 0x01)) {
|
||||
CS(true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} while (HAL_GetTick() - starttime < timeout);
|
||||
// timed out
|
||||
CS(true);
|
||||
LOG_ERR("Timeout occured");
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ extern "C" {
|
|||
|
||||
//#define LOG_BLOCKING
|
||||
|
||||
#define LOG_USART 2
|
||||
#define LOG_USART 3
|
||||
#define LOG_SENDBUF_LENGTH 1024
|
||||
//#define LOG_USE_MUTEX
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
#include <cmath>
|
||||
|
||||
#define LOG_LEVEL LOG_LEVEL_DEBUG
|
||||
#define LOG_LEVEL LOG_LEVEL_INFO
|
||||
#define LOG_MODULE "SI5351"
|
||||
#include "Log.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -296,12 +296,14 @@ void MAX2871::UpdateFrequency() {
|
|||
}
|
||||
|
||||
void MAX2871::Write(uint8_t reg, uint32_t val) {
|
||||
uint16_t data[2];
|
||||
uint8_t data[4];
|
||||
// split value into two 16 bit words
|
||||
data[0] = val >> 16;
|
||||
data[1] = (val & 0xFFF8) | reg;
|
||||
data[0] = (val >> 24) & 0xFF;
|
||||
data[1] = (val >> 16) & 0xFF;
|
||||
data[2] = (val >> 8) & 0xFF;
|
||||
data[3] = (val & 0xF8) | reg;
|
||||
Delay::us(1);
|
||||
HAL_SPI_Transmit(hspi, (uint8_t*) data, 2, 20);
|
||||
HAL_SPI_Transmit(hspi, (uint8_t*) data, 4, 20);
|
||||
LE->BSRR = LEpin;
|
||||
Delay::us(1);
|
||||
LE->BSRR = LEpin << 16;
|
||||
|
|
@ -309,15 +311,16 @@ void MAX2871::Write(uint8_t reg, uint32_t val) {
|
|||
|
||||
// Assumes that the MUX pin is already configured as "Read register 6" and connected to MISO
|
||||
uint32_t MAX2871::Read() {
|
||||
uint16_t transmit[2] = {0x0000, 0x0006};
|
||||
HAL_SPI_Transmit(hspi, (uint8_t*) transmit, 2, 20);
|
||||
uint8_t transmit[4] = {0x00, 0x00, 0x00, 0x06};
|
||||
HAL_SPI_Transmit(hspi, (uint8_t*) transmit, 4, 20);
|
||||
LE->BSRR = LEpin;
|
||||
memset(transmit, 0, sizeof(transmit));
|
||||
uint16_t recv[2];
|
||||
HAL_SPI_TransmitReceive(hspi, (uint8_t*) transmit, (uint8_t*) recv, 2, 20);
|
||||
uint8_t recv[4];
|
||||
HAL_SPI_TransmitReceive(hspi, (uint8_t*) transmit, (uint8_t*) recv, 4, 20);
|
||||
LE->BSRR = LEpin << 16;
|
||||
// assemble readback result
|
||||
uint32_t result = ((uint32_t) recv[0] << 16) | (recv[1] & 0xFFFF);
|
||||
uint32_t result = ((uint32_t) recv[0] << 24) | ((uint32_t) recv[1] << 16
|
||||
) | ((uint32_t) recv[2] << 8) | (recv[3] & 0xFF);
|
||||
result <<= 2;
|
||||
LOG_DEBUG("Readback: 0x%08x", result);
|
||||
return result;
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ Firmware::Info Firmware::GetFlashContentInfo(Flash *f) {
|
|||
}
|
||||
f->read(h.FPGA_start + checked_size, read_size, buf);
|
||||
crc = Protocol::CRC32(crc, buf, read_size);
|
||||
checked_size += read_size;
|
||||
}
|
||||
if (crc != h.crc) {
|
||||
LOG_ERR("CRC mismatch, invalid FPGA bitstream/CPU firmware");
|
||||
|
|
@ -54,12 +55,13 @@ Firmware::Info Firmware::GetFlashContentInfo(Flash *f) {
|
|||
if (h.CPU_size - checked_size < read_size) {
|
||||
read_size = h.CPU_size - checked_size;
|
||||
}
|
||||
f->read(h.FPGA_start + checked_size, read_size, buf);
|
||||
f->read(h.CPU_start + checked_size, read_size, buf);
|
||||
if(memcmp(buf, (void*)(0x8000000+checked_size), read_size)) {
|
||||
LOG_WARN("Difference to CPU firmware in external FLASH detected, update required");
|
||||
ret.CPU_need_update = true;
|
||||
break;
|
||||
}
|
||||
checked_size += read_size;
|
||||
}
|
||||
ret.valid = true;
|
||||
ret.FPGA_bitstream_address = h.FPGA_start;
|
||||
|
|
@ -100,9 +102,12 @@ static void copy_flash(uint32_t size, SPI_TypeDef *spi) {
|
|||
* content into the internal MCU flash */
|
||||
uint32_t written = 0;
|
||||
|
||||
// Enable FIFO notifications for 8 bit
|
||||
SET_BIT(spi->CR2, SPI_RXFIFO_THRESHOLD);
|
||||
|
||||
/* Enable FLASH write */
|
||||
FLASH->CR |= FLASH_CR_PG;
|
||||
uint32_t to = 0x80000000;
|
||||
uint32_t *to = (uint32_t*) 0x8000000;
|
||||
while (written < size) {
|
||||
uint8_t buf[8];
|
||||
// Get 64bit from external flash
|
||||
|
|
@ -110,14 +115,15 @@ static void copy_flash(uint32_t size, SPI_TypeDef *spi) {
|
|||
// wait for SPI ready to transmit dummy data
|
||||
while(!(spi->SR & SPI_FLAG_TXE));
|
||||
// send dummy byte
|
||||
*(__IO uint8_t *)spi->DR = 0x00;
|
||||
*(__IO uint8_t *)&spi->DR = 0x00;
|
||||
// wait for received byte to be ready
|
||||
while(!(spi->SR & SPI_FLAG_RXNE));
|
||||
// get received byte
|
||||
buf[i] = *(__IO uint8_t *)spi->DR;
|
||||
buf[i] = *(__IO uint8_t *)&spi->DR;
|
||||
}
|
||||
// program received data into flash
|
||||
*(__IO uint32_t*) to++ = *(uint32_t*)&buf[0];
|
||||
__ISB();
|
||||
*(__IO uint32_t*) to++ = *(uint32_t*)&buf[4];
|
||||
/* Wait for it to finish */
|
||||
while (FLASH->SR & FLASH_SR_BSY)
|
||||
|
|
@ -152,8 +158,7 @@ static void copy_flash(uint32_t size, SPI_TypeDef *spi) {
|
|||
}
|
||||
}
|
||||
|
||||
void Firmware::PerformUpdate(Flash *f) {
|
||||
auto info = GetFlashContentInfo(f);
|
||||
void Firmware::PerformUpdate(Flash *f, Info info) {
|
||||
if(!info.valid) {
|
||||
LOG_ERR("Invalid firmware data, not performing update");
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ using Info = struct info {
|
|||
};
|
||||
|
||||
Info GetFlashContentInfo(Flash *f);
|
||||
void PerformUpdate(Flash *f);
|
||||
void PerformUpdate(Flash *f, Info info);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
131
Software/VNA_embedded/Application/Led.cpp
Normal file
131
Software/VNA_embedded/Application/Led.cpp
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
#include "Led.hpp"
|
||||
|
||||
#include "stm.hpp"
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
#if HW_REVISION == 'B'
|
||||
|
||||
#define LED_TASK_STACK 128
|
||||
|
||||
extern TIM_HandleTypeDef htim2;
|
||||
|
||||
enum class Mode {
|
||||
Off,
|
||||
On,
|
||||
Blink,
|
||||
Pulsating,
|
||||
Error,
|
||||
};
|
||||
|
||||
static Mode mode;
|
||||
static uint8_t led_statecnt;
|
||||
static int8_t led_ncnt;
|
||||
static xTaskHandle task;
|
||||
static StaticTask_t xTask;
|
||||
static StackType_t xStack[LED_TASK_STACK];
|
||||
static uint8_t err_cnt;
|
||||
|
||||
static void led_set_percentage(uint8_t val) {
|
||||
uint16_t compare = val * val / 100;
|
||||
TIM2->CCR1 = compare;
|
||||
}
|
||||
|
||||
static void led_task(void* unused) {
|
||||
UNUSED(unused);
|
||||
while (1) {
|
||||
if (led_statecnt < 199) {
|
||||
led_statecnt++;
|
||||
} else {
|
||||
led_statecnt = 0;
|
||||
}
|
||||
switch (mode) {
|
||||
case Mode::Off:
|
||||
led_set_percentage(0);
|
||||
vTaskSuspend(NULL);
|
||||
break;
|
||||
case Mode::On:
|
||||
led_set_percentage(100);
|
||||
vTaskSuspend(NULL);
|
||||
break;
|
||||
case Mode::Error:
|
||||
if (led_statecnt == 0) {
|
||||
err_cnt++;
|
||||
if (err_cnt > led_ncnt) {
|
||||
// reached number of blinks + 1
|
||||
err_cnt = 0;
|
||||
}
|
||||
}
|
||||
if (err_cnt >= led_ncnt) {
|
||||
break;
|
||||
}
|
||||
// fall through
|
||||
/* no break */
|
||||
case Mode::Blink:
|
||||
if(led_statecnt < 100) {
|
||||
led_set_percentage(100);
|
||||
} else {
|
||||
led_set_percentage(0);
|
||||
}
|
||||
break;
|
||||
case Mode::Pulsating:
|
||||
if (led_statecnt < 100) {
|
||||
led_set_percentage(led_statecnt);
|
||||
} else {
|
||||
led_set_percentage(200 - led_statecnt);
|
||||
}
|
||||
break;
|
||||
}
|
||||
vTaskDelay(5);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void LED::Init() {
|
||||
#if HW_REVISION == 'B'
|
||||
led_ncnt = 0;
|
||||
mode = Mode::Off;
|
||||
HAL_TIM_Base_Start(&htim2);
|
||||
HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
|
||||
|
||||
task = xTaskCreateStatic(led_task, "LED",
|
||||
LED_TASK_STACK, NULL, 6, xStack, &xTask);
|
||||
vTaskSuspend(task);
|
||||
#endif
|
||||
}
|
||||
|
||||
void LED::Pulsating() {
|
||||
#if HW_REVISION == 'B'
|
||||
if(led_ncnt) {
|
||||
return;
|
||||
}
|
||||
vTaskSuspend(task);
|
||||
mode = Mode::Pulsating;
|
||||
vTaskResume(task);
|
||||
#endif
|
||||
}
|
||||
|
||||
void LED::Off() {
|
||||
#if HW_REVISION == 'B'
|
||||
if(led_ncnt) {
|
||||
return;
|
||||
}
|
||||
vTaskSuspend(task);
|
||||
mode = Mode::Off;
|
||||
vTaskResume(task);
|
||||
#endif
|
||||
}
|
||||
|
||||
void LED::Error(uint8_t code) {
|
||||
#if HW_REVISION == 'B'
|
||||
if(led_ncnt) {
|
||||
return;
|
||||
}
|
||||
vTaskSuspend(task);
|
||||
mode = Mode::Error;
|
||||
led_statecnt = 0;
|
||||
err_cnt = 0;
|
||||
led_ncnt = code;
|
||||
vTaskResume(task);
|
||||
#endif
|
||||
}
|
||||
12
Software/VNA_embedded/Application/Led.hpp
Normal file
12
Software/VNA_embedded/Application/Led.hpp
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace LED {
|
||||
|
||||
void Init();
|
||||
void Pulsating();
|
||||
void Off();
|
||||
void Error(uint8_t code);
|
||||
|
||||
}
|
||||
|
|
@ -568,3 +568,16 @@ bool VNA::ConfigureGenerator(Protocol::GeneratorSettings g) {
|
|||
m.attenuator = attval;
|
||||
return ConfigureManual(m, nullptr);
|
||||
}
|
||||
|
||||
void VNA::SetIdle() {
|
||||
FPGA::AbortSweep();
|
||||
FPGA::SetMode(FPGA::Mode::FPGA);
|
||||
FPGA::Enable(FPGA::Periphery::SourceChip, false);
|
||||
FPGA::Enable(FPGA::Periphery::SourceRF, false);
|
||||
FPGA::Enable(FPGA::Periphery::LO1Chip, false);
|
||||
FPGA::Enable(FPGA::Periphery::LO1RF, false);
|
||||
FPGA::Enable(FPGA::Periphery::Amplifier, false);
|
||||
FPGA::Enable(FPGA::Periphery::Port1Mixer, false);
|
||||
FPGA::Enable(FPGA::Periphery::Port2Mixer, false);
|
||||
FPGA::Enable(FPGA::Periphery::RefMixer, false);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ bool Init();
|
|||
bool ConfigureSweep(Protocol::SweepSettings s, SweepCallback cb);
|
||||
bool ConfigureManual(Protocol::ManualControl m, StatusCallback cb);
|
||||
bool ConfigureGenerator(Protocol::GeneratorSettings g);
|
||||
void SetIdle();
|
||||
|
||||
// Only call the following function when the sweep is inactive
|
||||
bool GetTemps(uint8_t *source, uint8_t *lo);
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@ extern SPI_HandleTypeDef hspi1;
|
|||
namespace VNAHAL {
|
||||
|
||||
static Si5351C Si5351 = Si5351C(&hi2c2, 26000000);
|
||||
static MAX2871 Source = MAX2871(&hspi1, FPGA_CS_GPIO_Port, FPGA_CS_Pin, nullptr, 0, nullptr, 0, nullptr, 0, GPIOB, GPIO_PIN_4);
|
||||
static MAX2871 LO1 = MAX2871(&hspi1, FPGA_CS_GPIO_Port, FPGA_CS_Pin, nullptr, 0, nullptr, 0, nullptr, 0, GPIOB, GPIO_PIN_4);
|
||||
static MAX2871 Source = MAX2871(&hspi1, FPGA_CS_GPIO_Port, FPGA_CS_Pin, nullptr, 0, nullptr, 0, nullptr, 0, GPIOA, GPIO_PIN_6);
|
||||
static MAX2871 LO1 = MAX2871(&hspi1, FPGA_CS_GPIO_Port, FPGA_CS_Pin, nullptr, 0, nullptr, 0, nullptr, 0, GPIOA, GPIO_PIN_6);
|
||||
|
||||
// Mapping of the Si5351 channels to PLLs/Mixers
|
||||
namespace SiChannel {
|
||||
|
|
@ -22,7 +22,7 @@ namespace SiChannel {
|
|||
Port2LO2 = 4,
|
||||
RefLO2 = 1,
|
||||
Port1LO2 = 2,
|
||||
LowbandSource = 1,
|
||||
LowbandSource = 0,
|
||||
ReferenceOut = 6,
|
||||
FPGA = 7,
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue