pull/166/merge
PhysicistJohn 7 days ago committed by GitHub
commit afb163caa2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

4
.gitmodules vendored

@ -1,4 +1,4 @@
[submodule "ChibiOS"]
path = ChibiOS
url = https://github.com/edy555/ChibiOS.git
branch = I2SFULLDUPLEX
url = https://github.com/PhysicistJohn/chibios.git
branch = codex/integration-tinysa-21.11.5

@ -1 +1 @@
Subproject commit ade76dea89cd093650552328e881252a06486094
Subproject commit db35f6df137058c612dc13e4488ac923219d881a

@ -13,7 +13,9 @@ endif
# Compiler options here.
ifeq ($(USE_OPT),)
ifeq ($(TARGET),F303)
USE_OPT = -Og -fno-inline-small-functions -ggdb -fomit-frame-pointer -falign-functions=16 --specs=nano.specs -fstack-usage -std=c11
USE_OPT = -Og -fno-inline-small-functions -ggdb -fomit-frame-pointer -falign-functions=16 --specs=nano.specs -fstack-usage -fsingle-precision-constant -std=c11
# The legacy ChibiOS rules appended -fsingle-precision-constant for hard-FPU
# builds. Keep that numeric behavior explicit when using the 21.11.x rules.
#USE_OPT+=-fstack-protector-strong
else
USE_OPT = -Og -fno-inline-small-functions -ggdb -fomit-frame-pointer -falign-functions=16 --specs=nano.specs -fstack-usage -fsingle-precision-constant
@ -93,7 +95,9 @@ endif
ifeq ($(TARGET),F303)
USE_FPU = hard
USE_PROCESS_STACKSIZE = 0x480
USE_EXCEPTIONS_STACKSIZE = 0x200
# The fault reporter renders through the LCD/printf stack. Reserve room for
# its assembly veneer, an extended exception frame, and a nested ISR frame.
USE_EXCEPTIONS_STACKSIZE = 0x400
endif
#
@ -115,6 +119,8 @@ endif
#CHIBIOS = ../ChibiOS-RT
CHIBIOS = ChibiOS
PROJ = .
# ChibiOS 21.11.x keeps its license policy header in a dedicated include.
include $(CHIBIOS)/os/license/license.mk
# Startup files.
ifeq ($(TARGET),F303)
@ -130,13 +136,13 @@ include $(CHIBIOS)/os/hal/ports/STM32/STM32F0xx/platform.mk
include NANOVNA_STM32_F072/board.mk
endif
include $(CHIBIOS)/os/hal/osal/rt/osal.mk
include $(CHIBIOS)/os/hal/osal/rt-nil/osal.mk
# RTOS files (optional).
include $(CHIBIOS)/os/rt/rt.mk
ifeq ($(TARGET),F303)
include $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/mk/port_v7m.mk
include $(CHIBIOS)/os/common/ports/ARMv7-M/compilers/GCC/mk/port.mk
else
include $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/mk/port_v6m.mk
include $(CHIBIOS)/os/common/ports/ARMv6-M/compilers/GCC/mk/port.mk
endif
# Other files (optional).
#include $(CHIBIOS)/test/rt/test.mk
@ -156,6 +162,7 @@ endif
ifeq ($(TARGET),F303)
CSRC = $(STARTUPSRC) \
$(KERNSRC) \
$(OSLIBSRC) \
$(PORTSRC) \
$(OSALSRC) \
$(HALSRC) \
@ -170,6 +177,7 @@ CSRC = $(STARTUPSRC) \
else
CSRC = $(STARTUPSRC) \
$(KERNSRC) \
$(OSLIBSRC) \
$(PORTSRC) \
$(OSALSRC) \
$(HALSRC) \
@ -205,10 +213,11 @@ TCSRC =
# option that results in lower performance and larger code size.
TCPPSRC =
# List ASM source files here
ASMSRC = $(STARTUPASM) $(PORTASM) $(OSALASM)
# ChibiOS startup and port assembly is preprocessed (.S), not plain assembly.
ASMSRC =
ASMXSRC = $(STARTUPASM) $(PORTASM) $(OSALASM)
INCDIR = $(STARTUPINC) $(KERNINC) $(PORTINC) $(OSALINC) \
INCDIR = $(LICINC) $(STARTUPINC) $(KERNINC) $(OSLIBINC) $(PORTINC) $(OSALINC) \
$(HALINC) $(PLATFORMINC) $(BOARDINC) \
$(STREAMSINC)
@ -266,7 +275,7 @@ CPPWARN = -Wall -Wextra -Wundef
# List all user C define here, like -D_DEBUG=1
ifeq ($(TARGET),F303)
UDEFS = -DARM_MATH_CM4 -DVERSION=\"$(VERSION)\" -DTINYSA_F303 -D__FPU_USED -DST7796S -DTINYSA4
UDEFS = -DARM_MATH_CM4 -DVERSION=\"$(VERSION)\" -DTINYSA_F303 -DST7796S -DTINYSA4
#Enable if install external 32.768kHz clock quartz on PC14 and PC15 pins on STM32 CPU
UDEFS+= -DVNA_USE_LSE
# Use R as usb pullup
@ -292,19 +301,12 @@ ULIBS = -lm
# End of user defines
##############################################################################
RULESPATH = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC
RULESPATH = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/mk
include $(RULESPATH)/arm-none-eabi.mk
include $(RULESPATH)/rules.mk
#include $(CHIBIOS)/memory.mk
ifeq ($(TARGET),F303)
clean:
rm -f -rf build/tinySA4.* build/lst/*.* build/obj/*.*
else
clean:
rm -f -rf build/$(PROJECT).* build/lst/*.* build/obj/*.*
endif
flash: build/$(PROJECT).bin
-@printf "reset dfu\r" >/dev/cu.usbmodem401 # mac
-@printf "reset dfu\r" >/dev/ttyACM0 # linux
@ -323,4 +325,3 @@ else
@etags *.[ch] NANOVNA_STM32_F072/*.[ch] $(shell find ChibiOS/os/hal/ports/STM32/STM32F0xx ChibiOS/os -name \*.\[ch\] -print)
endif
@ls -l TAGS

@ -80,7 +80,7 @@ int16_t adc_vbat_read(void)
// Vbat measure averange count = 2^VBAT_AVERAGE
#define VBAT_AVERAGE 4
// Measure vbat every 5 second
#define VBAT_MEASURE_INTERVAL S2ST(5)
#define VBAT_MEASURE_INTERVAL TIME_S2I(5)
static int16_t vbat_raw = 0;
static systime_t vbat_time = -VBAT_MEASURE_INTERVAL-1;

@ -14,15 +14,41 @@
limitations under the License.
*/
#include "hal.h"
#if HAL_USE_PAL || defined(__DOXYGEN__)
/**
* @brief PAL setup.
* @details Digital I/O ports static configuration as defined in @p board.h.
* This variable is used by the HAL when initializing the PAL driver.
*/
const PALConfig pal_default_config = {
#include "hal.h"
#include "stm32_gpio.h"
typedef struct {
uint32_t moder;
uint32_t otyper;
uint32_t ospeedr;
uint32_t pupdr;
uint32_t odr;
uint32_t afrl;
uint32_t afrh;
} gpio_setup_t;
typedef struct {
#if STM32_HAS_GPIOA
gpio_setup_t PAData;
#endif
#if STM32_HAS_GPIOB
gpio_setup_t PBData;
#endif
#if STM32_HAS_GPIOC
gpio_setup_t PCData;
#endif
#if STM32_HAS_GPIOD
gpio_setup_t PDData;
#endif
#if STM32_HAS_GPIOE
gpio_setup_t PEData;
#endif
#if STM32_HAS_GPIOF
gpio_setup_t PFData;
#endif
} gpio_config_t;
static const gpio_config_t gpio_default_config = {
#if STM32_HAS_GPIOA
{VAL_GPIOA_MODER, VAL_GPIOA_OTYPER, VAL_GPIOA_OSPEEDR, VAL_GPIOA_PUPDR,
VAL_GPIOA_ODR, VAL_GPIOA_AFRL, VAL_GPIOA_AFRH},
@ -59,8 +85,40 @@ const PALConfig pal_default_config = {
{VAL_GPIOI_MODER, VAL_GPIOI_OTYPER, VAL_GPIOI_OSPEEDR, VAL_GPIOI_PUPDR,
VAL_GPIOI_ODR, VAL_GPIOI_AFRL, VAL_GPIOI_AFRH}
#endif
};
#endif
};
static void gpio_init(stm32_gpio_t *gpiop, const gpio_setup_t *config) {
gpiop->OTYPER = config->otyper;
gpiop->OSPEEDR = config->ospeedr;
gpiop->PUPDR = config->pupdr;
gpiop->ODR = config->odr;
gpiop->AFRL = config->afrl;
gpiop->AFRH = config->afrh;
gpiop->MODER = config->moder;
}
static void stm32_gpio_init(void) {
rccResetAHB(STM32_GPIO_EN_MASK);
rccEnableAHB(STM32_GPIO_EN_MASK, true);
#if STM32_HAS_GPIOA
gpio_init(GPIOA, &gpio_default_config.PAData);
#endif
#if STM32_HAS_GPIOB
gpio_init(GPIOB, &gpio_default_config.PBData);
#endif
#if STM32_HAS_GPIOC
gpio_init(GPIOC, &gpio_default_config.PCData);
#endif
#if STM32_HAS_GPIOD
gpio_init(GPIOD, &gpio_default_config.PDData);
#endif
#if STM32_HAS_GPIOE
gpio_init(GPIOE, &gpio_default_config.PEData);
#endif
#if STM32_HAS_GPIOF
gpio_init(GPIOF, &gpio_default_config.PFData);
#endif
}
static bool needDFU(void) {
// Magick data in memory before reset
@ -105,7 +163,8 @@ void __early_init(void) {
}
//si5351_setup();
stm32_clock_init();
stm32_gpio_init();
stm32_clock_init();
}
/*

@ -36,54 +36,67 @@ static adcsample_t samplesVBAT[ADC_GRP_NUM_CHANNELS_VBAT];
static adcsample_t samples[1];
static const ADCConversionGroup adcgrpcfgVBAT = {
FALSE,
ADC_GRP_NUM_CHANNELS_VBAT,
NULL,
NULL,
ADC_CFGR_CONT | ADC_CFGR1_RES_12BIT, // CFGR1
ADC_TR(0, 0), // ADC watchdog threshold TR1
{0, ADC_SMPR2_SMP_AN16(ADC_VBAT_SMP_TIME) | ADC_SMPR2_SMP_AN17(ADC_VBAT_SMP_TIME)/*| ADC_SMPR2_SMP_AN18(ADC_VBAT_SMP_TIME)*/}, // SMPR
{ADC_SQR1_SQ1_N(ADC_CHANNEL_IN17) | ADC_SQR1_SQ2_N(ADC_CHANNEL_IN18)/*| ADC_SQR1_SQ3_N(ADC_CHANNEL_IN16)*/, 0, 0, 0} // CHSELR
.circular = false,
.num_channels = ADC_GRP_NUM_CHANNELS_VBAT,
.end_cb = NULL,
.error_cb = NULL,
.cfgr = ADC_CFGR_CONT | ADC_CFGR_RES_12BITS,
.tr1 = ADC_TR(0, 0),
.tr2 = ADC_TR_DISABLED,
.tr3 = ADC_TR_DISABLED,
.awd2cr = 0U,
.awd3cr = 0U,
.smpr = {0, ADC_SMPR2_SMP_AN16(ADC_VBAT_SMP_TIME) |
ADC_SMPR2_SMP_AN17(ADC_VBAT_SMP_TIME)},
.sqr = {ADC_SQR1_SQ1_N(ADC_CHANNEL_IN17) |
ADC_SQR1_SQ2_N(ADC_CHANNEL_IN18), 0, 0, 0}
};
static const ADCConversionGroup adcgrpcfgVersion = {
FALSE,
1,
NULL,
NULL,
ADC_CFGR1_RES_12BIT, // CFGR1
ADC_TR(0, 0), // ADC watchdog threshold TR1
{ADC_SMPR1_SMP_AN1(ADC_TOUCH_XY_SMP_TIME), 0}, /* SMPR[2] */
{ADC_SQR1_SQ1_N(ADC_CHANNEL_IN1), 0, 0, 0} /* SQR[4] */
.circular = false,
.num_channels = 1,
.end_cb = NULL,
.error_cb = NULL,
.cfgr = ADC_CFGR_RES_12BITS,
.tr1 = ADC_TR(0, 0),
.tr2 = ADC_TR_DISABLED,
.tr3 = ADC_TR_DISABLED,
.awd2cr = 0U,
.awd3cr = 0U,
.smpr = {ADC_SMPR1_SMP_AN1(ADC_TOUCH_XY_SMP_TIME), 0},
.sqr = {ADC_SQR1_SQ1_N(ADC_CHANNEL_IN1), 0, 0, 0}
};
static const ADCConversionGroup adcgrpcfgTouch = {
TRUE, // Enables the circular buffer mode for the group.
1, // Number of the analog channels belonging to the conversion group.
NULL, // adccallback_touch
NULL, // adcerrorcallback_touch
// CFGR
ADC_CFGR_EXTEN_0 // rising edge of external trigger
| ADC_CFGR_EXTSEL_3 | ADC_CFGR_EXTSEL_0 // EXT4 0x1001 event (TIM1_TRGO)
// | ADC_CFGR_EXTSEL_2 // EXT4 0x100 event (TIM3_TRGO)
| ADC_CFGR_AWD1EN, // Enable Analog watchdog check interrupt
ADC_TR(0, TOUCH_THRESHOLD), // Analog watchdog threshold TR1, interrupt on touch press
{ADC_SMPR1_SMP_AN4(ADC_TOUCH_SMP_TIME), 0}, // SMPR[2]
{ADC_SQR1_SQ1_N(ADC_CHANNEL_IN4), 0, 0, 0} // SQR[4]
.circular = true,
.num_channels = 1,
.end_cb = NULL,
.error_cb = NULL,
.cfgr = ADC_CFGR_EXTEN_0 | ADC_CFGR_EXTSEL_3 | ADC_CFGR_EXTSEL_0 |
ADC_CFGR_AWD1EN,
.tr1 = ADC_TR(0, TOUCH_THRESHOLD),
.tr2 = ADC_TR_DISABLED,
.tr3 = ADC_TR_DISABLED,
.awd2cr = 0U,
.awd3cr = 0U,
.smpr = {ADC_SMPR1_SMP_AN4(ADC_TOUCH_SMP_TIME), 0},
.sqr = {ADC_SQR1_SQ1_N(ADC_CHANNEL_IN4), 0, 0, 0}
};
static ADCConversionGroup adcgrpcfgXY = {
FALSE,
1,
NULL, /* adccallback_touch */
NULL, /* adcerrorcallback_touch */
ADC_CFGR1_RES_12BIT, /* CFGR */
ADC_TR(0, 0), /* TR1 */
{ADC_SMPR1_SMP_AN3(ADC_TOUCH_XY_SMP_TIME) | ADC_SMPR1_SMP_AN4(ADC_TOUCH_XY_SMP_TIME), 0}, /* SMPR[2] */
{ADC_SQR1_SQ1_N(ADC_CHANNEL_IN3), 0, 0, 0} /* SQR[4] */
.circular = false,
.num_channels = 1,
.end_cb = NULL,
.error_cb = NULL,
.cfgr = ADC_CFGR_RES_12BITS,
.tr1 = ADC_TR(0, 0),
.tr2 = ADC_TR_DISABLED,
.tr3 = ADC_TR_DISABLED,
.awd2cr = 0U,
.awd3cr = 0U,
.smpr = {ADC_SMPR1_SMP_AN3(ADC_TOUCH_XY_SMP_TIME) |
ADC_SMPR1_SMP_AN4(ADC_TOUCH_XY_SMP_TIME), 0},
.sqr = {ADC_SQR1_SQ1_N(ADC_CHANNEL_IN3), 0, 0, 0}
};
void adc_init(void)
@ -120,7 +133,7 @@ int16_t adc_vbat_read(void)
// Vbat measure averange count = 2^VBAT_AVERAGE
#define VBAT_AVERAGE 4
// Measure vbat every 5 second
#define VBAT_MEASURE_INTERVAL S2ST(5)
#define VBAT_MEASURE_INTERVAL TIME_S2I(5)
static int16_t vbat_raw = 0;
static systime_t vbat_time = -VBAT_MEASURE_INTERVAL-1;
@ -219,7 +232,7 @@ uint16_t adc_multi_read(uint32_t chsel, uint16_t *result, uint32_t count)
VNA_ADC->IER = 0;
VNA_ADC->TR = ADC_TR(0, 0);
VNA_ADC->SMPR = ADC_SMPR_SMP_1P5;
VNA_ADC->CFGR1 = ADC_CFGR1_RES_12BIT;
VNA_ADC->CFGR = ADC_CFGR_RES_12BITS;
VNA_ADC->CHSELR = chsel;

@ -15,14 +15,40 @@
*/
#include "hal.h"
#include "stm32_gpio.h"
#if HAL_USE_PAL || defined(__DOXYGEN__)
/**
* @brief PAL setup.
* @details Digital I/O ports static configuration as defined in @p board.h.
* This variable is used by the HAL when initializing the PAL driver.
*/
const PALConfig pal_default_config = {
typedef struct {
uint32_t moder;
uint32_t otyper;
uint32_t ospeedr;
uint32_t pupdr;
uint32_t odr;
uint32_t afrl;
uint32_t afrh;
} gpio_setup_t;
typedef struct {
#if STM32_HAS_GPIOA
gpio_setup_t PAData;
#endif
#if STM32_HAS_GPIOB
gpio_setup_t PBData;
#endif
#if STM32_HAS_GPIOC
gpio_setup_t PCData;
#endif
#if STM32_HAS_GPIOD
gpio_setup_t PDData;
#endif
#if STM32_HAS_GPIOE
gpio_setup_t PEData;
#endif
#if STM32_HAS_GPIOF
gpio_setup_t PFData;
#endif
} gpio_config_t;
static const gpio_config_t gpio_default_config = {
#if STM32_HAS_GPIOA
{VAL_GPIOA_MODER, VAL_GPIOA_OTYPER, VAL_GPIOA_OSPEEDR, VAL_GPIOA_PUPDR,
VAL_GPIOA_ODR, VAL_GPIOA_AFRL, VAL_GPIOA_AFRH},
@ -60,7 +86,39 @@ const PALConfig pal_default_config = {
VAL_GPIOI_ODR, VAL_GPIOI_AFRL, VAL_GPIOI_AFRH}
#endif
};
static void gpio_init(stm32_gpio_t *gpiop, const gpio_setup_t *config) {
gpiop->OTYPER = config->otyper;
gpiop->OSPEEDR = config->ospeedr;
gpiop->PUPDR = config->pupdr;
gpiop->ODR = config->odr;
gpiop->AFRL = config->afrl;
gpiop->AFRH = config->afrh;
gpiop->MODER = config->moder;
}
static void stm32_gpio_init(void) {
rccResetAHB(STM32_GPIO_EN_MASK);
rccEnableAHB(STM32_GPIO_EN_MASK, true);
#if STM32_HAS_GPIOA
gpio_init(GPIOA, &gpio_default_config.PAData);
#endif
#if STM32_HAS_GPIOB
gpio_init(GPIOB, &gpio_default_config.PBData);
#endif
#if STM32_HAS_GPIOC
gpio_init(GPIOC, &gpio_default_config.PCData);
#endif
#if STM32_HAS_GPIOD
gpio_init(GPIOD, &gpio_default_config.PDData);
#endif
#if STM32_HAS_GPIOE
gpio_init(GPIOE, &gpio_default_config.PEData);
#endif
#if STM32_HAS_GPIOF
gpio_init(GPIOF, &gpio_default_config.PFData);
#endif
}
// extern void si5351_setup(void);
@ -129,6 +187,7 @@ void __early_init(void) {
#endif
}
// si5351_setup();
stm32_gpio_init();
stm32_clock_init();
}

@ -27,8 +27,6 @@
#define BOARD_NANOVNA_STM32_F303
#define BOARD_NAME "tinySA ULTRA"
#include <stm32f303xc.h>
//#include "..\nanovna.h"
/*
* Board frequencies.
*/

@ -32,6 +32,7 @@
*/
#define STM32F3xx_MCUCONF
#define STM32F303_MCUCONF
/*
* HAL driver system settings.
@ -111,9 +112,9 @@
//#define STM32_ADC_ADC4_DMA_STREAM STM32_DMA_STREAM_ID(2, 2)
#define STM32_ADC_ADC12_DMA_PRIORITY 2
//#define STM32_ADC_ADC34_DMA_PRIORITY 2
#define STM32_ADC_ADC12_IRQ_PRIORITY 2
#define STM32_ADC_ADC12_IRQ_PRIORITY 3
//#define STM32_ADC_ADC34_IRQ_PRIORITY 5
#define STM32_ADC_ADC12_DMA_IRQ_PRIORITY 2
#define STM32_ADC_ADC12_DMA_IRQ_PRIORITY 3
//#define STM32_ADC_ADC34_DMA_IRQ_PRIORITY 5
//#define STM32_ADC_ADC12_CLOCK_MODE ADC_CCR_CKMODE_ADCCK
//#define STM32_ADC_ADC12_CLOCK_MODE ADC_CCR_CKMODE_AHB_DIV2
@ -157,10 +158,10 @@
#define STM32_GPT_USE_TIM2 FALSE
#define STM32_GPT_USE_TIM3 FALSE
#define STM32_GPT_USE_TIM4 TRUE
#define STM32_GPT_TIM1_IRQ_PRIORITY 2
#define STM32_GPT_TIM2_IRQ_PRIORITY 2
#define STM32_GPT_TIM3_IRQ_PRIORITY 2
#define STM32_GPT_TIM4_IRQ_PRIORITY 2
#define STM32_GPT_TIM1_IRQ_PRIORITY 3
#define STM32_GPT_TIM2_IRQ_PRIORITY 3
#define STM32_GPT_TIM3_IRQ_PRIORITY 3
#define STM32_GPT_TIM4_IRQ_PRIORITY 3
/*
* I2C driver system settings.
@ -184,8 +185,8 @@
STM32_I2S_MODE_RX)
#define STM32_I2S_SPI2_MODE (STM32_I2S_MODE_SLAVE | \
STM32_I2S_MODE_RX )
#define STM32_I2S_SPI1_IRQ_PRIORITY 2
#define STM32_I2S_SPI2_IRQ_PRIORITY 2
#define STM32_I2S_SPI1_IRQ_PRIORITY 3
#define STM32_I2S_SPI2_IRQ_PRIORITY 3
#define STM32_I2S_SPI1_DMA_PRIORITY 1
#define STM32_I2S_SPI2_DMA_PRIORITY 1
#define STM32_I2S_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2)
@ -233,14 +234,14 @@
#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3)
#define STM32_SPI_SPI1_DMA_PRIORITY 1
#define STM32_SPI_SPI2_DMA_PRIORITY 1
#define STM32_SPI_SPI1_IRQ_PRIORITY 2
#define STM32_SPI_SPI2_IRQ_PRIORITY 2
#define STM32_SPI_SPI1_IRQ_PRIORITY 3
#define STM32_SPI_SPI2_IRQ_PRIORITY 3
#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure")
/*
* ST driver system settings.
*/
#define STM32_ST_IRQ_PRIORITY 2
#define STM32_ST_IRQ_PRIORITY 3
#define STM32_ST_USE_TIMER 2
/*

@ -29,6 +29,9 @@
#define _CHCONF_H_
#define _CHIBIOS_RT_CONF_
#define _CHIBIOS_RT_CONF_VER_7_0_
#define CH_CFG_SMP_MODE FALSE
/*===========================================================================*/
/**
@ -49,6 +52,8 @@
* setting also defines the system tick time unit.
*/
#define CH_CFG_ST_FREQUENCY 10000
#define CH_CFG_INTERVALS_SIZE 32
#define CH_CFG_TIME_TYPES_SIZE 32
/**
* @brief Time delta constant for the tick-less mode.
@ -140,6 +145,7 @@
* @note The default is @p TRUE.
*/
#define CH_CFG_USE_TM FALSE
#define CH_CFG_USE_TIMESTAMP FALSE
/**
* @brief Threads registry APIs.
@ -305,6 +311,20 @@
*/
#define CH_CFG_USE_MEMPOOLS FALSE
#define CH_CFG_USE_OBJ_FIFOS FALSE
#define CH_CFG_USE_PIPES FALSE
#define CH_CFG_USE_OBJ_CACHES FALSE
#define CH_CFG_USE_DELEGATES FALSE
#define CH_CFG_USE_JOBS FALSE
#define CH_CFG_USE_FACTORY FALSE
#define CH_CFG_FACTORY_MAX_NAMES_LENGTH 8
#define CH_CFG_FACTORY_OBJECTS_REGISTRY FALSE
#define CH_CFG_FACTORY_GENERIC_BUFFERS FALSE
#define CH_CFG_FACTORY_SEMAPHORES FALSE
#define CH_CFG_FACTORY_MAILBOXES FALSE
#define CH_CFG_FACTORY_OBJ_FIFOS FALSE
#define CH_CFG_FACTORY_PIPES FALSE
/**
* @brief Dynamic Threads APIs.
* @details If enabled then the dynamic threads creation APIs are included
@ -417,6 +437,18 @@
*/
/*===========================================================================*/
#define CH_CFG_SYSTEM_EXTRA_FIELDS \
/* No custom system fields.*/
#define CH_CFG_SYSTEM_INIT_HOOK() { \
}
#define CH_CFG_OS_INSTANCE_EXTRA_FIELDS \
/* No custom instance fields.*/
#define CH_CFG_OS_INSTANCE_INIT_HOOK(oip) { \
}
/**
* @brief Threads descriptor structure extension.
* @details User fields added to the end of the @p thread_t structure.
@ -522,6 +554,9 @@
/* Trace code here.*/ \
}
#define CH_CFG_RUNTIME_FAULTS_HOOK(mask) { \
}
/** @} */
/*===========================================================================*/

@ -630,7 +630,13 @@ static msg_t put(void *ip, uint8_t b) {
return MSG_OK;
}
static const struct printStreamVMT vmt = {NULL, NULL, put, NULL};
static const struct printStreamVMT vmt = {
.instance_offset = 0U,
.write = NULL,
.read = NULL,
.put = put,
.get = NULL
};
void printObjectInit(printStream *ps, int size, uint8_t *buffer){
ps->vmt = &vmt;
ps->buffer = buffer;

@ -0,0 +1,63 @@
# ChibiOS 21.11.5 port
This branch ports both firmware targets from the historical tinySA ChibiOS
fork to the official ChibiOS `ver21.11.5` release.
The draft currently pins the public integration commit
`db35f6df137058c612dc13e4488ac923219d881a` from
`PhysicistJohn/chibios`. It contains two focused commits on top of the release
tag:
1. restore the standalone STM32F0 TIM14 GPT interrupt service;
2. preserve active USBv1 endpoint-zero PMA buffers when configuration
endpoints are rebuilt.
Those fixes are also proposed independently to current ChibiOS in PRs #84 and
#85 and to `stable-21.11.x` in draft PRs #86 and #87. The temporary fork URL
will be replaced with the canonical ChibiOS URL and merged stable commit before
this port is marked ready.
## Port changes
- Adopt the RT7/HAL9 configuration markers, OS library settings, build rules,
Cortex-M port paths, and license include required by ChibiOS 21.11.5.
- Raise kernel-aware F303 interrupt priorities to respect the RT7
fast-interrupt reservation.
- Migrate board GPIO initialization, DMA allocation, ADC group definitions,
PAL line events, USB serial hooks, endpoint configuration, PWM configuration,
queue reset calls, time conversions, and thread diagnostics.
- Update the project-local F303 ADC LLD while retaining its tinySA-specific
behavior.
- Convert custom `BaseSequentialStream` VMTs to the current layout, including
the required `instance_offset` field.
- Preserve the legacy hard-FPU build's `-fsingle-precision-constant` behavior
explicitly. ChibiOS 21.11.x no longer adds it automatically; omitting it
promotes unsuffixed sweep constants to software double precision and causes
a measurable self-test sweep regression.
- Split the F303 HardFault entry into an assembly-only MSP/PSP veneer and an
ordinary non-returning C reporter, while reserving a 1 KiB exception stack.
## Build
With an Arm GNU toolchain on `PATH`:
```sh
git submodule update --init --recursive
make TARGET=F303 -j8
make clean
make TARGET=F072 -j8
```
## Qualification boundary
The predecessor RC5 image using the same application port and equivalent
ChibiOS fixes was exercised on a tinySA Ultra+ ZS407. Its exact DFU write and
readback, USB runtime, warm reset retention, cold boot, and all fourteen
built-in self-tests passed. A fresh official-versus-candidate comparison had
one first-cold measured-level threshold failure in case 2; three repeats,
including a second cold run, passed. Physical forced-fault injection was not
performed.
The clean public branch has different commit identity and embedded version, so
it is a new binary. It must be rebuilt and receive a final physical smoke and
self-test run before this draft is promoted to ready.

@ -444,7 +444,7 @@ void adc_lld_init(void) {
#if STM32_ADC_DUAL_MODE
ADCD1.adcs = ADC2;
#endif
ADCD1.dmastp = STM32_DMA_STREAM(STM32_ADC_ADC1_DMA_STREAM);
ADCD1.dmastp = NULL;
ADCD1.dmamode = ADC_DMA_SIZE |
STM32_DMA_CR_PL(STM32_ADC_ADC1_DMA_PRIORITY) |
STM32_DMA_CR_DIR_P2M |
@ -461,7 +461,7 @@ void adc_lld_init(void) {
ADCD2.adcc = ADC123_COMMON;
#endif
ADCD2.adcm = ADC2;
ADCD2.dmastp = STM32_DMA_STREAM(STM32_ADC_ADC2_DMA_STREAM);
ADCD2.dmastp = NULL;
ADCD2.dmamode = ADC_DMA_SIZE |
STM32_DMA_CR_PL(STM32_ADC_ADC2_DMA_PRIORITY) |
STM32_DMA_CR_DIR_P2M |
@ -483,7 +483,7 @@ void adc_lld_init(void) {
#if STM32_ADC_DUAL_MODE
ADCD3.adcs = ADC4;
#endif
ADCD3.dmastp = STM32_DMA_STREAM(STM32_ADC_ADC3_DMA_STREAM);
ADCD3.dmastp = NULL;
ADCD3.dmamode = ADC_DMA_SIZE |
STM32_DMA_CR_PL(STM32_ADC_ADC3_DMA_PRIORITY) |
STM32_DMA_CR_DIR_P2M |
@ -496,7 +496,7 @@ void adc_lld_init(void) {
adcObjectInit(&ADCD4);
ADCD4.adcc = ADC3_4_COMMON;
ADCD4.adcm = ADC4;
ADCD4.dmastp = STM32_DMA_STREAM(STM32_ADC_ADC4_DMA_STREAM);
ADCD4.dmastp = NULL;
ADCD4.dmamode = ADC_DMA_SIZE |
STM32_DMA_CR_PL(STM32_ADC_ADC4_DMA_PRIORITY) |
STM32_DMA_CR_DIR_P2M |
@ -524,13 +524,13 @@ void adc_lld_init(void) {
rccEnableADC12(FALSE);
rccResetADC12();
ADC1_2_COMMON->CCR = STM32_ADC_ADC12_CLOCK_MODE | ADC_DMA_MDMA;
rccDisableADC12(FALSE);
rccDisableADC12();
#endif
#if STM32_ADC_USE_ADC3 || STM32_ADC_USE_ADC4
rccEnableADC34(FALSE);
rccResetADC34();
ADC3_4_COMMON->CCR = STM32_ADC_ADC34_CLOCK_MODE | ADC_DMA_MDMA;
rccDisableADC34(FALSE);
rccDisableADC34();
#endif
#endif
@ -538,7 +538,7 @@ void adc_lld_init(void) {
rccEnableADC123(FALSE);
rccResetADC123();
ADC123_COMMON->CCR = STM32_ADC_ADC123_CLOCK_MODE | ADC_DMA_MDMA;
rccDisableADC123(FALSE);
rccDisableADC123();
#endif
}
@ -560,12 +560,11 @@ void adc_lld_start(ADCDriver *adcp) {
if (adcp->state == ADC_STOP) {
#if STM32_ADC_USE_ADC1
if (&ADCD1 == adcp) {
bool b;
b = dmaStreamAllocate(adcp->dmastp,
STM32_ADC_ADC1_DMA_IRQ_PRIORITY,
(stm32_dmaisr_t)adc_lld_serve_dma_interrupt,
(void *)adcp);
osalDbgAssert(!b, "stream already allocated");
adcp->dmastp = dmaStreamAllocI(STM32_ADC_ADC1_DMA_STREAM,
STM32_ADC_ADC1_DMA_IRQ_PRIORITY,
(stm32_dmaisr_t)adc_lld_serve_dma_interrupt,
(void *)adcp);
osalDbgAssert(adcp->dmastp != NULL, "unable to allocate stream");
clkmask |= (1 << 0);
#if defined(STM32F3XX)
@ -579,12 +578,11 @@ void adc_lld_start(ADCDriver *adcp) {
#if STM32_ADC_USE_ADC2
if (&ADCD2 == adcp) {
bool b;
b = dmaStreamAllocate(adcp->dmastp,
STM32_ADC_ADC2_DMA_IRQ_PRIORITY,
(stm32_dmaisr_t)adc_lld_serve_dma_interrupt,
(void *)adcp);
osalDbgAssert(!b, "stream already allocated");
adcp->dmastp = dmaStreamAllocI(STM32_ADC_ADC2_DMA_STREAM,
STM32_ADC_ADC2_DMA_IRQ_PRIORITY,
(stm32_dmaisr_t)adc_lld_serve_dma_interrupt,
(void *)adcp);
osalDbgAssert(adcp->dmastp != NULL, "unable to allocate stream");
clkmask |= (1 << 1);
#if defined(STM32F3XX)
@ -598,12 +596,11 @@ void adc_lld_start(ADCDriver *adcp) {
#if STM32_ADC_USE_ADC3
if (&ADCD3 == adcp) {
bool b;
b = dmaStreamAllocate(adcp->dmastp,
STM32_ADC_ADC3_DMA_IRQ_PRIORITY,
(stm32_dmaisr_t)adc_lld_serve_dma_interrupt,
(void *)adcp);
osalDbgAssert(!b, "stream already allocated");
adcp->dmastp = dmaStreamAllocI(STM32_ADC_ADC3_DMA_STREAM,
STM32_ADC_ADC3_DMA_IRQ_PRIORITY,
(stm32_dmaisr_t)adc_lld_serve_dma_interrupt,
(void *)adcp);
osalDbgAssert(adcp->dmastp != NULL, "unable to allocate stream");
clkmask |= (1 << 2);
#if defined(STM32F3XX)
@ -617,12 +614,11 @@ void adc_lld_start(ADCDriver *adcp) {
#if STM32_ADC_USE_ADC4
if (&ADCD4 == adcp) {
bool b;
b = dmaStreamAllocate(adcp->dmastp,
STM32_ADC_ADC4_DMA_IRQ_PRIORITY,
(stm32_dmaisr_t)adc_lld_serve_dma_interrupt,
(void *)adcp);
osalDbgAssert(!b, "stream already allocated");
adcp->dmastp = dmaStreamAllocI(STM32_ADC_ADC4_DMA_STREAM,
STM32_ADC_ADC4_DMA_IRQ_PRIORITY,
(stm32_dmaisr_t)adc_lld_serve_dma_interrupt,
(void *)adcp);
osalDbgAssert(adcp->dmastp != NULL, "unable to allocate stream");
clkmask |= (1 << 3);
#if defined(STM32F3XX)
@ -671,7 +667,8 @@ void adc_lld_stop(ADCDriver *adcp) {
if (adcp->state == ADC_READY) {
/* Releasing the associated DMA channel.*/
dmaStreamRelease(adcp->dmastp);
dmaStreamFreeI(adcp->dmastp);
adcp->dmastp = NULL;
/* Stopping the ongoing conversion, if any.*/
adc_lld_stop_adc(adcp);
@ -727,16 +724,16 @@ void adc_lld_stop(ADCDriver *adcp) {
#if defined(STM32F3XX)
if ((clkmask & 0x3) == 0) {
rccDisableADC12(FALSE);
rccDisableADC12();
}
if ((clkmask & 0xC) == 0) {
rccDisableADC34(FALSE);
rccDisableADC34();
}
#endif
#if defined(STM32L4XX)
if ((clkmask & 0x7) == 0) {
rccDisableADC123(FALSE);
rccDisableADC123();
}
#endif
}

@ -28,6 +28,9 @@
#ifndef _HALCONF_H_
#define _HALCONF_H_
#define _CHIBIOS_HAL_CONF_
#define _CHIBIOS_HAL_CONF_VER_9_1_
#include "mcuconf.h"
/**

@ -526,7 +526,10 @@ void ili9341_init(void)
LCD_CS_HIGH;
}
static void ili9341_setWindow(uint8_t cmd, uint16_t x, uint16_t y, uint16_t w, uint16_t h){
// Every DMA region starts here; keep command setup inlined on the rendering
// path without enabling strict aliasing for the legacy display code.
static void __attribute__((optimize("O3,no-strict-aliasing")))
ili9341_setWindow(uint8_t cmd, uint16_t x, uint16_t y, uint16_t w, uint16_t h){
// Any LCD exchange start from this
#ifdef __USE_DISPLAY_DMA__
dmaChannelWaitCompletionRxTx();
@ -663,8 +666,11 @@ void ili9341_bulk_finish(void){
}
#endif
// Copy part of spi_buffer to region, no wait completion after if buffer count !=1
#ifndef ili9341_bulk_continue
void ili9341_bulk_continue(int x, int y, int w, int h)
#ifndef ili9341_bulk_continue
// This runs once per dirty plot cell. Keep the DMA handoff inlined so a held
// self-test screen is not slower than the historical display pipeline.
void __attribute__((optimize("O3,no-strict-aliasing")))
ili9341_bulk_continue(int x, int y, int w, int h)
{
ili9341_bulk_finish(); // Wait DMA
ili9341_DMA_bulk(x, y, w, h, ili9341_get_cell_buffer()); // Send new cell data
@ -783,7 +789,10 @@ void ili9341_set_rotation(uint8_t r)
send_command(ILI9341_MEMORY_ACCESS_CONTROL, 1, &r);
}
void ili9341_blitBitmap(int x, int y, int width, int height, const uint8_t *b)
// Text drawing calls this once per glyph. Inline the DMA setup on this hot
// path while retaining the aliasing rules used by the rest of the release.
void __attribute__((optimize("O3,no-strict-aliasing")))
ili9341_blitBitmap(int x, int y, int width, int height, const uint8_t *b)
{
pixel_t *buf = spi_buffer;
uint8_t bits = 0;
@ -881,7 +890,13 @@ int lcd_printf(int16_t x, int16_t y, const char *fmt, ...) {
// Init small lcd print stream
struct lcd_printStreamVMT {
_base_sequential_stream_methods
} lcd_vmt = {NULL, NULL, put_char, NULL};
} lcd_vmt = {
.instance_offset = 0U,
.write = NULL,
.read = NULL,
.put = put_char,
.get = NULL
};
lcdPrintStream ps = {&lcd_vmt, x, y, x, y};
// Performing the print operation using the common code.
va_list ap;
@ -1357,7 +1372,7 @@ static uint8_t SD_WaitNotBusy(uint32_t wait_time) {
// Receive data block from SD
static bool SD_RxDataBlock(uint8_t *buff, uint16_t len, uint8_t token) {
// loop until receive read response token or timeout ~50ms
if (!SD_WaitDataToken(token, MS2ST(50))) {
if (!SD_WaitDataToken(token, TIME_MS2I(50))) {
DEBUG_PRINT(" rx SD_WaitDataToken err\r\n");
return FALSE;
}
@ -1408,7 +1423,7 @@ static bool SD_TxDataBlock(const uint8_t *buff, uint16_t len, uint8_t token) {
}
#if 1
// Wait busy (recommended timeout is 250ms (500ms for SDXC) set 250ms
resp = SD_WaitNotBusy(MS2ST(250));
resp = SD_WaitNotBusy(TIME_MS2I(250));
if (resp == 0xFF)
return TRUE;
#else
@ -1427,7 +1442,7 @@ static uint8_t SD_SendCmd(uint8_t cmd, uint32_t arg) {
uint8_t buf[6];
volatile uint8_t r1;
// wait SD ready after last Tx (recommended timeout is 250ms (500ms for SDXC) set 250ms
if ((r1 = SD_WaitNotBusy(MS2ST(500))) != 0xFF) {
if ((r1 = SD_WaitNotBusy(TIME_MS2I(500))) != 0xFF) {
DEBUG_PRINT(" SD_WaitNotBusy CMD%d err, %02x\r\n", cmd-0x40, (uint32_t)r1);
return 0xFF;
}
@ -1707,7 +1722,7 @@ DRESULT disk_ioctl(BYTE pdrv, BYTE cmd, void* buff) {
// Nothing to do for this command if each write operation to the media is completed
// within the disk_write function.
case CTRL_SYNC:
if (SD_WaitNotBusy(MS2ST(200)) == 0xFF) res = RES_OK;
if (SD_WaitNotBusy(TIME_MS2I(200)) == 0xFF) res = RES_OK;
break;
#if FF_USE_TRIM == 1
// Informs the device the data on the block of sectors is no longer needed and it can be erased.

@ -161,7 +161,8 @@ static THD_FUNCTION(Thread1, arg)
while (1) {
// START_PROFILE
if (sweep_mode&(SWEEP_ENABLE|SWEEP_ONCE)) {
backup_t b;
/* Initialize the reserved byte covered by the checksum too. */
backup_t b = {0};
b.data.frequency0 = setting.frequency0;
b.data.frequency1 = setting.frequency1;
if (setting.auto_attenuation)
@ -209,7 +210,7 @@ static THD_FUNCTION(Thread1, arg)
{
completed = sweep(true);
#ifdef __USE_SD_CARD__
if (setting.trigger_auto_save && (last_auto_save == 0 || chVTGetSystemTimeX() - last_auto_save > S2ST(30)) ) { // once every 30 seconds max
if (setting.trigger_auto_save && (last_auto_save == 0 || chVTGetSystemTimeX() - last_auto_save > TIME_S2I(30)) ) { // once every 30 seconds max
uint16_t old_mode = config._mode;
config._mode |= _MODE_AUTO_FILENAME;
save_csv(1+(2<<0)); // frequencies + trace 1
@ -455,7 +456,7 @@ VNA_SHELL_FUNCTION(cmd_restart)
(void)argc;
(void)argv;
if (argc == 1) {
restart_interval = S2ST(my_atoi(argv[0]));
restart_interval = TIME_S2I(my_atoi(argv[0]));
if (restart_interval) {
restart_set_time = chVTGetSystemTimeX();
if (restart_set_time == 0)
@ -2418,7 +2419,7 @@ VNA_SHELL_FUNCTION(cmd_threads)
#endif
shell_printf("%08x|%08x|%08x|%08x|%4u|%4u|%9s|%12s"VNA_SHELL_NEWLINE_STR,
stklimit, (uint32_t)tp->ctx.sp, max_stack_use, (uint32_t)tp,
(uint32_t)tp->refs - 1, (uint32_t)tp->prio, states[tp->state],
(uint32_t)tp->refs - 1, (uint32_t)tp->hdr.pqueue.prio, states[tp->state],
tp->name == NULL ? "" : tp->name);
tp = chRegNextThread(tp);
} while (tp != NULL);
@ -2697,18 +2698,21 @@ void shell_update_speed(void){
}
void shell_reset_console(void){
osalSysLock();
// Reset I/O queue over USB (for USB need also connect/disconnect)
if (usb_IsActive()){
if (config._mode & _MODE_SERIAL)
sduDisconnectI(&SDU1);
sduSuspendHookI(&SDU1);
else
sduConfigureHookI(&SDU1);
}
// Reset I/O queue over Serial
// oqResetI(&SD1.oqueue);
// iqResetI(&SD1.iqueue);
qResetI(&SD1.oqueue);
qResetI(&SD1.iqueue);
oqResetI(&SD1.oqueue);
iqResetI(&SD1.iqueue);
osalOsRescheduleS();
osalSysUnlock();
}
@ -2886,7 +2890,7 @@ static void VNAShell_executeLine(char *line)
int timeout_count = 0;
msg_t result;
do {
result = osalThreadEnqueueTimeoutS(&shell_thread, MS2ST(5000)); // 5 second timeout
result = osalThreadEnqueueTimeoutS(&shell_thread, TIME_MS2I(5000)); // 5 second timeout
if (result == MSG_TIMEOUT) {
timeout_count++;
if (timeout_count > 3) {
@ -3004,6 +3008,7 @@ static PWMConfig pwmcfg = {
{PWM_OUTPUT_DISABLED, NULL}
},
0,
0,
0
};
@ -3446,8 +3451,35 @@ int main(void)
}
}
/* The prototype shows it is a naked function - in effect this is just an
assembly function. */
#ifdef TINYSA4
void hard_fault_handler_c(uint32_t *sp, const uint32_t *callee)
__attribute__((noreturn, noinline));
void HardFault_Handler(void) __attribute__((naked));
void HardFault_Handler(void)
{
__asm volatile(
"tst lr, #4\n"
"ite eq\n"
"mrseq r0, msp\n"
"mrsne r0, psp\n"
"sub sp, sp, #32\n"
"str r4, [sp, #0]\n"
"str r5, [sp, #4]\n"
"str r6, [sp, #8]\n"
"str r7, [sp, #12]\n"
"mov r2, r8\n"
"str r2, [sp, #16]\n"
"mov r2, r9\n"
"str r2, [sp, #20]\n"
"mov r2, r10\n"
"str r2, [sp, #24]\n"
"mov r2, r11\n"
"str r2, [sp, #28]\n"
"mov r1, sp\n"
"b hard_fault_handler_c\n");
}
#else
void HardFault_Handler(void);
void hard_fault_handler_c(uint32_t *sp) __attribute__((naked));
@ -3460,22 +3492,27 @@ void HardFault_Handler(void)
__asm volatile("mrs %0, psp \n\t" : "=r"(sp));
hard_fault_handler_c(sp);
}
#endif
#ifdef TINYSA4
void hard_fault_handler_c(uint32_t *sp, const uint32_t *callee)
#else
void hard_fault_handler_c(uint32_t *sp)
#endif
{
#ifdef TINYSA4
uint32_t r0 = sp[0];
uint32_t r1 = sp[1];
uint32_t r2 = sp[2];
uint32_t r3 = sp[3];
register uint32_t r4 __asm("r4");
register uint32_t r5 __asm("r5");
register uint32_t r6 __asm("r6");
register uint32_t r7 __asm("r7");
register uint32_t r8 __asm("r8");
register uint32_t r9 __asm("r9");
register uint32_t r10 __asm("r10");
register uint32_t r11 __asm("r11");
uint32_t r4 = callee[0];
uint32_t r5 = callee[1];
uint32_t r6 = callee[2];
uint32_t r7 = callee[3];
uint32_t r8 = callee[4];
uint32_t r9 = callee[5];
uint32_t r10 = callee[6];
uint32_t r11 = callee[7];
uint32_t r12 = sp[4];
uint32_t lr = sp[5];
uint32_t pc = sp[6];
@ -3516,7 +3553,7 @@ void hard_fault_handler_c(uint32_t *sp)
#endif
lcd_printf(x, y+=FONT_STR_HEIGHT, "%08x|%08x|%08x|%08x|%4u|%4u|%9s|%12s",
stklimit, (uint32_t)tp->ctx.sp, max_stack_use, (uint32_t)tp,
(uint32_t)tp->refs - 1, (uint32_t)tp->prio, states[tp->state],
(uint32_t)tp->refs - 1, (uint32_t)tp->hdr.pqueue.prio, states[tp->state],
tp->name == NULL ? "" : tp->name);
tp = chRegNextThread(tp);
} while (tp != NULL);
@ -3533,4 +3570,3 @@ void hard_fault_handler_c(uint32_t *sp)
}

@ -984,6 +984,7 @@ extern int8_t marker_tracking;
void plot_init(void);
void update_grid(void);
void update_grid_if_changed(void);
void request_to_redraw_grid(void);
void redraw_frame(void);
//void redraw_all(void);

@ -110,19 +110,24 @@ float2int(float v)
}
#endif
void update_grid(void)
static void calculate_grid(int16_t *offset, int16_t *width, freq_t *span)
{
freq_t gdigit = 1000000000;
freq_t fstart = get_sweep_frequency(ST_START) + (setting.frequency_offset - FREQUENCY_SHIFT);
freq_t fspan = get_sweep_frequency(ST_SPAN);
freq_t grid;
bool time_domain = fspan == 0;
if (fspan == 0) {
if (time_domain) {
fspan = setting.actual_sweep_time_us; // Time in uS
fstart = 0;
}
if (fspan == 0)
fspan = 1;
if (config.gridlines == 0) {
grid = fspan/10;
if (grid == 0)
grid = 1;
} else {
if (config.gridlines < 3)
config.gridlines = 6;
@ -139,21 +144,54 @@ void update_grid(void)
gdigit /= 10;
}
}
grid_span = grid;
if (grid > 1000) {
grid_offset = (WIDTH) * ((fstart % grid) / 100) / (fspan / 100);
grid_width = (WIDTH) * (grid / 100) / (fspan / 1000);
*span = grid;
if (time_domain) {
// The zero-span x axis is measured in microseconds. Keep the full ratio
// until the final division so 5-20 ms sweeps do not shift by whole pixels.
*offset = (int16_t)((uint64_t)WIDTH * (fstart % grid) / fspan);
*width = (int16_t)((uint64_t)WIDTH * 10U * grid / fspan);
} else if (grid > 1000) {
*offset = (WIDTH) * ((fstart % grid) / 100) / (fspan / 100);
*width = (WIDTH) * (grid / 100) / (fspan / 1000);
} else {
grid_offset = (WIDTH) * ((fstart % grid)) / (fspan);
grid_width = (WIDTH) * (grid) / (fspan/10);
*offset = (WIDTH) * ((fstart % grid)) / (fspan);
*width = (WIDTH) * (grid) / (fspan/10);
}
if (*width < 1)
*width = 1;
if (config.gridlines == 0)
grid_offset = 0;
*offset = 0;
}
static void apply_grid(int16_t offset, int16_t width, freq_t span)
{
grid_offset = offset;
grid_width = width;
grid_span = span;
// if (setting.waterfall)
set_level_meter_or_waterfall();
redraw_request |= REDRAW_FREQUENCY | REDRAW_AREA;
}
void update_grid(void)
{
int16_t offset;
int16_t width;
freq_t span;
calculate_grid(&offset, &width, &span);
apply_grid(offset, width, span);
}
void update_grid_if_changed(void)
{
int16_t offset;
int16_t width;
freq_t span;
calculate_grid(&offset, &width, &span);
if (offset != grid_offset || width != grid_width || span != grid_span)
apply_grid(offset, width, span);
}
#if 0
static int
rectangular_grid(int x, int y)
@ -1509,7 +1547,13 @@ int cell_printf(int16_t x, int16_t y, const char *fmt, ...) {
// Init small cell print stream
struct cellprintStreamVMT {
_base_sequential_stream_methods
} cell_vmt = {NULL, NULL, NULL, NULL};
} cell_vmt = {
.instance_offset = 0U,
.write = NULL,
.read = NULL,
.put = NULL,
.get = NULL
};
screenPrintStream ps = {&cell_vmt, x, y};
// Select font and skip print if not on cell (at top/bottom)
switch (*fmt++){

@ -499,6 +499,9 @@ const freq_t fh_high[] = { 480000000, 960000000, 1920000000, 2880000000, 3840000
uint8_t in_selftest = false;
uint8_t ignore_stored = false;
#ifdef TINYSA4
static uint8_t factory_selftest_direct_scratch = false;
#endif
uint8_t in_step_test = false;
uint8_t in_calibration = false;
uint8_t calibration_stage;
@ -3555,6 +3558,20 @@ deviceRSSI_t age[POINTS_COUNT]; // Array used for 1: calculating the age of
static pureRSSI_t correct_RSSI;
static pureRSSI_t correct_RSSI_freq;
systime_t start_of_sweep_timestamp;
#ifdef TINYSA4
#if OSAL_ST_MODE != OSAL_ST_MODE_FREERUNNING
#error "The optimized sweep clock requires the ChibiOS free-running system timer"
#endif
#if CH_CFG_ST_TIMEDELTA == 0
#error "The optimized sweep clock requires the port-backed ChibiOS system timer"
#endif
// Keep the timed sweep hot path on the current free-running timer backend.
// Re-audit this equivalence whenever the ChibiOS system-timer backend changes.
#define SWEEP_CLOCK_NOW() st_lld_get_counter()
#else
#define SWEEP_CLOCK_NOW() chVTGetSystemTimeX()
#endif
static systime_t sweep_elapsed = 0; // Time since first start of sweeping, used only for auto attenuate
uint8_t signal_is_AM = false;
static uint8_t check_for_AM = false;
@ -3637,6 +3654,9 @@ bool depth_error = false;
#endif
#ifdef TINYSA4
__attribute__((optimize("O2,no-strict-aliasing")))
#endif
pureRSSI_t perform(bool break_on_operation, int i, freq_t f, int tracking) // Measure the RSSI for one frequency, used from sweep and other measurement routines. Must do all HW setup
{
int modulation_delay = 0;
@ -4761,7 +4781,7 @@ again: // Spur redu
skip_LO_setting:
if (i == 0 && t == 0) // if first point in scan (here is get 1 point data)
start_of_sweep_timestamp = chVTGetSystemTimeX(); // initialize start sweep time
start_of_sweep_timestamp = SWEEP_CLOCK_NOW(); // initialize start sweep time
if (MODE_OUTPUT(setting.mode)) { // No substepping and no RSSI in output mode
if (break_on_operation && operation_requested) // break subscanning if requested
@ -4893,7 +4913,7 @@ again: // Spur redu
if (setting.trigger == T_SINGLE) {
set_trigger(T_DONE);
}
start_of_sweep_timestamp = chVTGetSystemTimeX();
start_of_sweep_timestamp = SWEEP_CLOCK_NOW();
}
TRACE(5);
#ifdef TINYSA4
@ -5067,6 +5087,9 @@ void reset_band(void) {
#endif
// main loop for measurement
#ifdef TINYSA4
__attribute__((optimize("O2,no-strict-aliasing")))
#endif
static bool sweep(bool break_on_operation)
{
float RSSI;
@ -5187,6 +5210,7 @@ static bool sweep(bool break_on_operation)
#endif
setting.measure_sweep_time_us = 0; // start measure sweep time
// start_of_sweep_timestamp = chVTGetSystemTimeX(); // Will be set in perform
uint8_t progress_mask = 0x3f;
sweep_again: // stay in sweep loop when output mode and modulation on.
@ -5301,33 +5325,41 @@ static bool sweep(bool break_on_operation)
}
}
}
systime_t local_sweep_time = sa_ST2US(chVTGetSystemTimeX() - start_of_sweep_timestamp);
if (setting.actual_sweep_time_us > ONE_SECOND_TIME)
local_sweep_time = setting.actual_sweep_time_us;
if (
#ifdef TINYSA4
progress_bar &&
#endif
show_bar && (( local_sweep_time > ONE_SECOND_TIME && (i & 0x07) == 0) /* || ( local_sweep_time > ONE_SECOND_TIME*10)*/ ) )
show_bar && (i & progress_mask) == 0)
{
int pos = i * (WIDTH+1) / sweep_points;
ili9341_set_background(LCD_SWEEP_LINE_COLOR);
ili9341_fill(OFFSETX, CHART_BOTTOM+1, pos, 1); // update sweep progress bar
ili9341_set_background(LCD_BG_COLOR);
ili9341_fill(OFFSETX+pos, CHART_BOTTOM+1, WIDTH-pos, 1);
if (local_sweep_time > 10 * ONE_SECOND_TIME) {
plot_into_index(measured);
redraw_request |= REDRAW_CELLS | REDRAW_BATTERY | REDRAW_INBETWEEN;
// plot trace and other indications as raster
draw_all(true); // flush markmap only if scan completed to prevent
}
// Expected long sweeps can use their known duration directly. For an
// expected fast sweep, sample every 64th point until an unexpected
// one-second overrun is observed, then resume the normal 8-point rate.
// This retains overrun progress while avoiding timer traffic in the
// common sub-second path.
systime_t local_sweep_time = setting.actual_sweep_time_us;
if (local_sweep_time <= ONE_SECOND_TIME)
local_sweep_time = sa_ST2US(SWEEP_CLOCK_NOW() - start_of_sweep_timestamp);
if (local_sweep_time > ONE_SECOND_TIME) {
progress_mask = 0x07;
int pos = i * (WIDTH+1) / sweep_points;
ili9341_set_background(LCD_SWEEP_LINE_COLOR);
ili9341_fill(OFFSETX, CHART_BOTTOM+1, pos, 1); // update sweep progress bar
ili9341_set_background(LCD_BG_COLOR);
ili9341_fill(OFFSETX+pos, CHART_BOTTOM+1, WIDTH-pos, 1);
if (local_sweep_time > 10 * ONE_SECOND_TIME) {
plot_into_index(measured);
redraw_request |= REDRAW_CELLS | REDRAW_BATTERY | REDRAW_INBETWEEN;
// plot trace and other indications as raster
draw_all(true); // flush markmap only if scan completed to prevent
}
#ifdef __SWEEP_RESTART__
if (MODE_OUTPUT(setting.mode) && (setting.level_sweep != 0 || get_sweep_frequency(ST_SPAN) != 0))
refresh_sweep_menu(i);
if (MODE_OUTPUT(setting.mode) && (setting.level_sweep != 0 || get_sweep_frequency(ST_SPAN) != 0))
refresh_sweep_menu(i);
#endif
}
}
// ----------------------- debug avoid --------------------------------
if (debug_avoid) {
@ -5651,6 +5683,14 @@ static volatile int dummy;
// add_to_peak_finding(actual_t, i);
}
#if TRACES_MAX == 4
// The factory test freezes two default scratch passes below. Preserve
// their exact AV_OFF result once, after ACTUAL processing is complete.
if (factory_selftest_direct_scratch) {
temp_t[i] = RSSI;
stored2_t[i] = RSSI;
}
#endif
}
}
@ -5688,14 +5728,20 @@ static volatile int dummy;
// ---------------------- process measured actual sweep time -----------------
// For CW mode value calculated in SI4432_Fill
if (setting.measure_sweep_time_us == 0)
setting.measure_sweep_time_us = sa_ST2US(chVTGetSystemTimeX() - start_of_sweep_timestamp);
setting.measure_sweep_time_us = sa_ST2US(SWEEP_CLOCK_NOW() - start_of_sweep_timestamp);
// Update actual time on change on status panel
uint32_t delta = abs((int)(setting.actual_sweep_time_us - setting.measure_sweep_time_us));
if ((delta<<3) > setting.actual_sweep_time_us){ // update if delta > 1/8
bool sweep_time_changed = (delta<<3) > setting.actual_sweep_time_us;
if (sweep_time_changed){ // update if delta > 1/8
redraw_request|=REDRAW_CAL_STATUS | REDRAW_FREQUENCY;
}
setting.actual_sweep_time_us = setting.measure_sweep_time_us;
// The zero-span x axis represents the sweep that just completed. Recompute
// its tuple every time; update_grid_if_changed() suppresses redraws while
// the exact grid geometry remains unchanged.
if (FREQ_IS_CW())
update_grid_if_changed();
// Not possible reduce sweep time, it minimum!
if (setting.sweep_time_us < setting.actual_sweep_time_us && setting.additional_step_delay_us == 0){
// Warning!! not correct set sweep time here, you get error!!
@ -5849,7 +5895,7 @@ static volatile int dummy;
} else if (actual_max_level > target_level && setting.attenuate_x2 < 60) {
delta = actual_max_level - target_level;
}
if (chVTGetSystemTimeX() - sweep_elapsed > MS2ST(1000)){
if (chVTGetSystemTimeX() - sweep_elapsed > TIME_MS2I(1000)){
if (( delta < -5 || delta > +5) || delta > 10 ) {
setting.attenuate_x2 += delta + delta;
if (setting.attenuate_x2 < 0)
@ -7117,6 +7163,7 @@ void selftest(int test)
{
bool no_wait = false;
#ifdef TINYSA4
factory_selftest_direct_scratch = false;
bool old_ultra = config.ultra;
config.ultra = true;
// if (adc_vbat_read() < 3800) {
@ -7158,7 +7205,33 @@ void selftest(int test)
}
do {
test_prepare(test_step);
#if TRACES_MAX == 4
// Preserve any pre-existing frozen traces. For the normal factory setup,
// freeze both AV_OFF scratch passes and write their raw samples directly.
// Zero-span timing still measures this faster path, and its grid is
// refreshed from that completed measurement below.
bool old_temp_stored = setting.stored[TRACE_TEMP];
bool old_stored2_stored = setting.stored[TRACE_STORED2];
factory_selftest_direct_scratch =
!debug_spur && !debug_avoid &&
!old_temp_stored && !old_stored2_stored &&
setting.average[TRACE_TEMP] == AV_OFF &&
setting.subtract[TRACE_TEMP] == 0 &&
!setting.normalized[TRACE_TEMP] &&
setting.average[TRACE_STORED2] == AV_OFF &&
setting.subtract[TRACE_STORED2] == 0 &&
!setting.normalized[TRACE_STORED2];
if (factory_selftest_direct_scratch) {
setting.stored[TRACE_TEMP] = true;
setting.stored[TRACE_STORED2] = true;
}
#endif
test_acquire(test_step); // Acquire test
#if TRACES_MAX == 4
factory_selftest_direct_scratch = false;
setting.stored[TRACE_TEMP] = old_temp_stored;
setting.stored[TRACE_STORED2] = old_stored2_stored;
#endif
test_status[test_step] = test_validate(test_step); // Validate test
if (test_step == 2) {

@ -210,7 +210,7 @@ static bool si5351_wait_ready(void)
{
uint8_t status = 0xff;
systime_t start = chVTGetSystemTime();
systime_t end = start + MS2ST(1000); // 1000 ms timeout
systime_t end = start + TIME_MS2I(1000); // 1000 ms timeout
while (chVTIsSystemTimeWithin(start, end))
{
if(!si5351_read(0, &status))
@ -230,7 +230,7 @@ static void si5351_wait_pll_lock(void)
status = 0xff; // comm timeout
if ((status & 0x60) == 0)
return;
systime_t end = start + MS2ST(100); // 100 ms timeout
systime_t end = start + TIME_MS2I(100); // 100 ms timeout
while (chVTIsSystemTimeWithin(start, end))
{
if(!si5351_read(0, &status))

75
ui.c

@ -48,10 +48,10 @@ uistat_t uistat = {
#define EVT_DOWN 0x20
#define EVT_REPEAT 0x40
#define BUTTON_DOWN_LONG_TICKS MS2ST(500) // 500ms
#define BUTTON_DOUBLE_TICKS MS2ST(250) // 250ms
#define BUTTON_REPEAT_TICKS MS2ST( 40) // 40ms
#define BUTTON_DEBOUNCE_TICKS MS2ST( 2) // 2ms
#define BUTTON_DOWN_LONG_TICKS TIME_MS2I(500) // 500ms
#define BUTTON_DOUBLE_TICKS TIME_MS2I(250) // 250ms
#define BUTTON_REPEAT_TICKS TIME_MS2I(40) // 40ms
#define BUTTON_DEBOUNCE_TICKS TIME_MS2I(2) // 2ms
/* lever switch assignment */
#define BIT_UP1 3
@ -684,7 +684,7 @@ extern const char *states[];
#endif
lcd_printf(x, y+=bFONT_STR_HEIGHT, "%08x|%08x|%08x|%08x|%4u|%4u|%9s|%12s",
stklimit, (uint32_t)tp->ctx.sp, max_stack_use, (uint32_t)tp,
(uint32_t)tp->refs - 1, (uint32_t)tp->prio, states[tp->state],
(uint32_t)tp->refs - 1, (uint32_t)tp->hdr.pqueue.prio, states[tp->state],
tp->name == NULL ? "" : tp->name);
tp = chRegNextThread(tp);
} while (tp != NULL);
@ -1599,10 +1599,12 @@ static const menuitem_t menu_calibrate_normal[];
#endif
static const menuitem_t menu_calibrate[];
static const menuitem_t menu_sweep[];
#ifdef TINYSA4
static const menuitem_t menu_settings[];
static const menuitem_t menu_settings2[];
static const menuitem_t menu_lowoutput_settings[];
static const menuitem_t menu_lowoutput_settings_max[];
#endif
static const menuitem_t menu_settings2[];
extern bool dirty;
char range_text[20];
#ifdef TINYSA4
@ -8382,10 +8384,9 @@ ui_process(void)
}
/* Triggered when the button is pressed or released. The LED4 is set to ON.*/
static void extcb1(EXTDriver *extp, expchannel_t channel)
static void extcb1(void *arg)
{
(void)extp;
(void)channel;
uint32_t channel = (uint32_t)(uintptr_t)arg;
#ifdef __USE_SD_CARD__
if (channel == 12)
SD_PowerOff();
@ -8397,42 +8398,6 @@ static void extcb1(EXTDriver *extp, expchannel_t channel)
// cur_button = READ_PORT() & BUTTON_MASK;
}
static const EXTConfig extcfg = {
{
{EXT_CH_MODE_DISABLED, NULL},
{EXT_CH_MODE_RISING_EDGE | EXT_CH_MODE_AUTOSTART | EXT_MODE_GPIOA, extcb1},
{EXT_CH_MODE_RISING_EDGE | EXT_CH_MODE_AUTOSTART | EXT_MODE_GPIOA, extcb1},
{EXT_CH_MODE_RISING_EDGE | EXT_CH_MODE_AUTOSTART | EXT_MODE_GPIOA, extcb1},
{EXT_CH_MODE_DISABLED, NULL},
{EXT_CH_MODE_DISABLED, NULL},
{EXT_CH_MODE_DISABLED, NULL},
{EXT_CH_MODE_DISABLED, NULL},
{EXT_CH_MODE_DISABLED, NULL},
#ifdef __WAIT_CTS_WHILE_SLEEPING__
{EXT_CH_MODE_RISING_EDGE | EXT_CH_MODE_AUTOSTART | EXT_MODE_GPIOB, extcb1},
#else
{EXT_CH_MODE_DISABLED, NULL},
#endif
{EXT_CH_MODE_DISABLED, NULL},
{EXT_CH_MODE_DISABLED, NULL},
#ifdef __USE_SD_CARD__
{EXT_CH_MODE_RISING_EDGE | EXT_CH_MODE_AUTOSTART | EXT_MODE_GPIOB, extcb1},
#else
{EXT_CH_MODE_DISABLED, NULL},
#endif
{EXT_CH_MODE_DISABLED, NULL},
{EXT_CH_MODE_DISABLED, NULL},
{EXT_CH_MODE_DISABLED, NULL},
{EXT_CH_MODE_DISABLED, NULL},
{EXT_CH_MODE_DISABLED, NULL},
{EXT_CH_MODE_DISABLED, NULL},
{EXT_CH_MODE_DISABLED, NULL},
{EXT_CH_MODE_DISABLED, NULL},
{EXT_CH_MODE_DISABLED, NULL},
{EXT_CH_MODE_DISABLED, NULL}
}
};
void
handle_touch_interrupt(void)
{
@ -8442,8 +8407,24 @@ handle_touch_interrupt(void)
void
ui_init()
{
// Activates the EXT driver 1.
extStart(&EXTD1, &extcfg);
/* HAL 9.1 routes STM32 EXTI through PAL line events. */
palSetLineCallback(PAL_LINE(GPIOA, GPIOA_LEVER1), extcb1,
(void *)(uintptr_t)GPIOA_LEVER1);
palEnableLineEvent(PAL_LINE(GPIOA, GPIOA_LEVER1), PAL_EVENT_MODE_RISING_EDGE);
palSetLineCallback(PAL_LINE(GPIOA, GPIOA_PUSH), extcb1,
(void *)(uintptr_t)GPIOA_PUSH);
palEnableLineEvent(PAL_LINE(GPIOA, GPIOA_PUSH), PAL_EVENT_MODE_RISING_EDGE);
palSetLineCallback(PAL_LINE(GPIOA, GPIOA_LEVER2), extcb1,
(void *)(uintptr_t)GPIOA_LEVER2);
palEnableLineEvent(PAL_LINE(GPIOA, GPIOA_LEVER2), PAL_EVENT_MODE_RISING_EDGE);
#ifdef __WAIT_CTS_WHILE_SLEEPING__
palSetLineCallback(LINE_RX_CTS, extcb1, (void *)(uintptr_t)9U);
palEnableLineEvent(LINE_RX_CTS, PAL_EVENT_MODE_RISING_EDGE);
#endif
#ifdef __USE_SD_CARD__
palSetLineCallback(LINE_SD_CD, extcb1, (void *)(uintptr_t)12U);
palEnableLineEvent(LINE_SD_CD, PAL_EVENT_MODE_RISING_EDGE);
#endif
// Init touch subsystem
touch_init();
}

@ -297,8 +297,10 @@ static const USBEndpointConfig ep1config = {
sduDataReceived,
0x0040,
0x0040,
&ep1instate,
&ep1outstate,
&ep1instate,
&ep1outstate,
1,
NULL
};
/**
@ -316,8 +318,10 @@ static const USBEndpointConfig ep2config = {
NULL,
0x0010,
0x0000,
&ep2instate,
NULL,
&ep2instate,
NULL,
1,
NULL
};
/*
@ -327,10 +331,8 @@ static void usb_event(USBDriver *usbp, usbevent_t event) {
extern SerialUSBDriver SDU1;
switch (event) {
case USB_EVENT_RESET:
return;
case USB_EVENT_ADDRESS:
return;
case USB_EVENT_ADDRESS:
return;
case USB_EVENT_CONFIGURED:
chSysLockFromISR();
@ -345,16 +347,21 @@ static void usb_event(USBDriver *usbp, usbevent_t event) {
chSysUnlockFromISR();
return;
case USB_EVENT_SUSPEND:
case USB_EVENT_RESET:
case USB_EVENT_UNCONFIGURED:
case USB_EVENT_SUSPEND:
chSysLockFromISR();
/* Disconnection event on suspend.*/
sduDisconnectI(&SDU1);
sduSuspendHookI(&SDU1);
chSysUnlockFromISR();
return;
case USB_EVENT_WAKEUP:
return;
case USB_EVENT_WAKEUP:
chSysLockFromISR();
sduWakeupHookI(&SDU1);
chSysUnlockFromISR();
return;
case USB_EVENT_STALLED:
return;
}

Loading…
Cancel
Save

Powered by TurnKey Linux.