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"] [submodule "ChibiOS"]
path = ChibiOS path = ChibiOS
url = https://github.com/edy555/ChibiOS.git url = https://github.com/PhysicistJohn/chibios.git
branch = I2SFULLDUPLEX branch = codex/integration-tinysa-21.11.5

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

@ -13,7 +13,9 @@ endif
# Compiler options here. # Compiler options here.
ifeq ($(USE_OPT),) ifeq ($(USE_OPT),)
ifeq ($(TARGET),F303) 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 #USE_OPT+=-fstack-protector-strong
else else
USE_OPT = -Og -fno-inline-small-functions -ggdb -fomit-frame-pointer -falign-functions=16 --specs=nano.specs -fstack-usage -fsingle-precision-constant 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) ifeq ($(TARGET),F303)
USE_FPU = hard USE_FPU = hard
USE_PROCESS_STACKSIZE = 0x480 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 endif
# #
@ -115,6 +119,8 @@ endif
#CHIBIOS = ../ChibiOS-RT #CHIBIOS = ../ChibiOS-RT
CHIBIOS = ChibiOS CHIBIOS = ChibiOS
PROJ = . PROJ = .
# ChibiOS 21.11.x keeps its license policy header in a dedicated include.
include $(CHIBIOS)/os/license/license.mk
# Startup files. # Startup files.
ifeq ($(TARGET),F303) ifeq ($(TARGET),F303)
@ -130,13 +136,13 @@ include $(CHIBIOS)/os/hal/ports/STM32/STM32F0xx/platform.mk
include NANOVNA_STM32_F072/board.mk include NANOVNA_STM32_F072/board.mk
endif endif
include $(CHIBIOS)/os/hal/osal/rt/osal.mk include $(CHIBIOS)/os/hal/osal/rt-nil/osal.mk
# RTOS files (optional). # RTOS files (optional).
include $(CHIBIOS)/os/rt/rt.mk include $(CHIBIOS)/os/rt/rt.mk
ifeq ($(TARGET),F303) 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 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 endif
# Other files (optional). # Other files (optional).
#include $(CHIBIOS)/test/rt/test.mk #include $(CHIBIOS)/test/rt/test.mk
@ -156,6 +162,7 @@ endif
ifeq ($(TARGET),F303) ifeq ($(TARGET),F303)
CSRC = $(STARTUPSRC) \ CSRC = $(STARTUPSRC) \
$(KERNSRC) \ $(KERNSRC) \
$(OSLIBSRC) \
$(PORTSRC) \ $(PORTSRC) \
$(OSALSRC) \ $(OSALSRC) \
$(HALSRC) \ $(HALSRC) \
@ -170,6 +177,7 @@ CSRC = $(STARTUPSRC) \
else else
CSRC = $(STARTUPSRC) \ CSRC = $(STARTUPSRC) \
$(KERNSRC) \ $(KERNSRC) \
$(OSLIBSRC) \
$(PORTSRC) \ $(PORTSRC) \
$(OSALSRC) \ $(OSALSRC) \
$(HALSRC) \ $(HALSRC) \
@ -205,10 +213,11 @@ TCSRC =
# option that results in lower performance and larger code size. # option that results in lower performance and larger code size.
TCPPSRC = TCPPSRC =
# List ASM source files here # ChibiOS startup and port assembly is preprocessed (.S), not plain assembly.
ASMSRC = $(STARTUPASM) $(PORTASM) $(OSALASM) ASMSRC =
ASMXSRC = $(STARTUPASM) $(PORTASM) $(OSALASM)
INCDIR = $(STARTUPINC) $(KERNINC) $(PORTINC) $(OSALINC) \ INCDIR = $(LICINC) $(STARTUPINC) $(KERNINC) $(OSLIBINC) $(PORTINC) $(OSALINC) \
$(HALINC) $(PLATFORMINC) $(BOARDINC) \ $(HALINC) $(PLATFORMINC) $(BOARDINC) \
$(STREAMSINC) $(STREAMSINC)
@ -266,7 +275,7 @@ CPPWARN = -Wall -Wextra -Wundef
# List all user C define here, like -D_DEBUG=1 # List all user C define here, like -D_DEBUG=1
ifeq ($(TARGET),F303) 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 #Enable if install external 32.768kHz clock quartz on PC14 and PC15 pins on STM32 CPU
UDEFS+= -DVNA_USE_LSE UDEFS+= -DVNA_USE_LSE
# Use R as usb pullup # Use R as usb pullup
@ -292,19 +301,12 @@ ULIBS = -lm
# End of user defines # 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 $(RULESPATH)/rules.mk
#include $(CHIBIOS)/memory.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 flash: build/$(PROJECT).bin
-@printf "reset dfu\r" >/dev/cu.usbmodem401 # mac -@printf "reset dfu\r" >/dev/cu.usbmodem401 # mac
-@printf "reset dfu\r" >/dev/ttyACM0 # linux -@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) @etags *.[ch] NANOVNA_STM32_F072/*.[ch] $(shell find ChibiOS/os/hal/ports/STM32/STM32F0xx ChibiOS/os -name \*.\[ch\] -print)
endif endif
@ls -l TAGS @ls -l TAGS

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

@ -14,15 +14,41 @@
limitations under the License. limitations under the License.
*/ */
#include "hal.h" #include "hal.h"
#include "stm32_gpio.h"
#if HAL_USE_PAL || defined(__DOXYGEN__)
/** typedef struct {
* @brief PAL setup. uint32_t moder;
* @details Digital I/O ports static configuration as defined in @p board.h. uint32_t otyper;
* This variable is used by the HAL when initializing the PAL driver. uint32_t ospeedr;
*/ uint32_t pupdr;
const PALConfig pal_default_config = { 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 #if STM32_HAS_GPIOA
{VAL_GPIOA_MODER, VAL_GPIOA_OTYPER, VAL_GPIOA_OSPEEDR, VAL_GPIOA_PUPDR, {VAL_GPIOA_MODER, VAL_GPIOA_OTYPER, VAL_GPIOA_OSPEEDR, VAL_GPIOA_PUPDR,
VAL_GPIOA_ODR, VAL_GPIOA_AFRL, VAL_GPIOA_AFRH}, 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_MODER, VAL_GPIOI_OTYPER, VAL_GPIOI_OSPEEDR, VAL_GPIOI_PUPDR,
VAL_GPIOI_ODR, VAL_GPIOI_AFRL, VAL_GPIOI_AFRH} VAL_GPIOI_ODR, VAL_GPIOI_AFRL, VAL_GPIOI_AFRH}
#endif #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) { static bool needDFU(void) {
// Magick data in memory before reset // Magick data in memory before reset
@ -105,7 +163,8 @@ void __early_init(void) {
} }
//si5351_setup(); //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 adcsample_t samples[1];
static const ADCConversionGroup adcgrpcfgVBAT = { static const ADCConversionGroup adcgrpcfgVBAT = {
FALSE, .circular = false,
ADC_GRP_NUM_CHANNELS_VBAT, .num_channels = ADC_GRP_NUM_CHANNELS_VBAT,
NULL, .end_cb = NULL,
NULL, .error_cb = NULL,
ADC_CFGR_CONT | ADC_CFGR1_RES_12BIT, // CFGR1 .cfgr = ADC_CFGR_CONT | ADC_CFGR_RES_12BITS,
ADC_TR(0, 0), // ADC watchdog threshold TR1 .tr1 = ADC_TR(0, 0),
{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 .tr2 = ADC_TR_DISABLED,
{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 .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 = { static const ADCConversionGroup adcgrpcfgVersion = {
FALSE, .circular = false,
1, .num_channels = 1,
NULL, .end_cb = NULL,
NULL, .error_cb = NULL,
ADC_CFGR1_RES_12BIT, // CFGR1 .cfgr = ADC_CFGR_RES_12BITS,
ADC_TR(0, 0), // ADC watchdog threshold TR1 .tr1 = ADC_TR(0, 0),
{ADC_SMPR1_SMP_AN1(ADC_TOUCH_XY_SMP_TIME), 0}, /* SMPR[2] */ .tr2 = ADC_TR_DISABLED,
{ADC_SQR1_SQ1_N(ADC_CHANNEL_IN1), 0, 0, 0} /* SQR[4] */ .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 = { static const ADCConversionGroup adcgrpcfgTouch = {
TRUE, // Enables the circular buffer mode for the group. .circular = true,
1, // Number of the analog channels belonging to the conversion group. .num_channels = 1,
NULL, // adccallback_touch .end_cb = NULL,
NULL, // adcerrorcallback_touch .error_cb = NULL,
// CFGR .cfgr = ADC_CFGR_EXTEN_0 | ADC_CFGR_EXTSEL_3 | ADC_CFGR_EXTSEL_0 |
ADC_CFGR_EXTEN_0 // rising edge of external trigger ADC_CFGR_AWD1EN,
.tr1 = ADC_TR(0, TOUCH_THRESHOLD),
| ADC_CFGR_EXTSEL_3 | ADC_CFGR_EXTSEL_0 // EXT4 0x1001 event (TIM1_TRGO) .tr2 = ADC_TR_DISABLED,
// | ADC_CFGR_EXTSEL_2 // EXT4 0x100 event (TIM3_TRGO) .tr3 = ADC_TR_DISABLED,
.awd2cr = 0U,
.awd3cr = 0U,
| ADC_CFGR_AWD1EN, // Enable Analog watchdog check interrupt .smpr = {ADC_SMPR1_SMP_AN4(ADC_TOUCH_SMP_TIME), 0},
ADC_TR(0, TOUCH_THRESHOLD), // Analog watchdog threshold TR1, interrupt on touch press .sqr = {ADC_SQR1_SQ1_N(ADC_CHANNEL_IN4), 0, 0, 0}
{ADC_SMPR1_SMP_AN4(ADC_TOUCH_SMP_TIME), 0}, // SMPR[2]
{ADC_SQR1_SQ1_N(ADC_CHANNEL_IN4), 0, 0, 0} // SQR[4]
}; };
static ADCConversionGroup adcgrpcfgXY = { static ADCConversionGroup adcgrpcfgXY = {
FALSE, .circular = false,
1, .num_channels = 1,
NULL, /* adccallback_touch */ .end_cb = NULL,
NULL, /* adcerrorcallback_touch */ .error_cb = NULL,
ADC_CFGR1_RES_12BIT, /* CFGR */ .cfgr = ADC_CFGR_RES_12BITS,
ADC_TR(0, 0), /* TR1 */ .tr1 = ADC_TR(0, 0),
{ADC_SMPR1_SMP_AN3(ADC_TOUCH_XY_SMP_TIME) | ADC_SMPR1_SMP_AN4(ADC_TOUCH_XY_SMP_TIME), 0}, /* SMPR[2] */ .tr2 = ADC_TR_DISABLED,
{ADC_SQR1_SQ1_N(ADC_CHANNEL_IN3), 0, 0, 0} /* SQR[4] */ .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) void adc_init(void)
@ -120,7 +133,7 @@ int16_t adc_vbat_read(void)
// Vbat measure averange count = 2^VBAT_AVERAGE // Vbat measure averange count = 2^VBAT_AVERAGE
#define VBAT_AVERAGE 4 #define VBAT_AVERAGE 4
// Measure vbat every 5 second // 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 int16_t vbat_raw = 0;
static systime_t vbat_time = -VBAT_MEASURE_INTERVAL-1; 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->IER = 0;
VNA_ADC->TR = ADC_TR(0, 0); VNA_ADC->TR = ADC_TR(0, 0);
VNA_ADC->SMPR = ADC_SMPR_SMP_1P5; 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; VNA_ADC->CHSELR = chsel;

@ -15,14 +15,40 @@
*/ */
#include "hal.h" #include "hal.h"
#include "stm32_gpio.h"
#if HAL_USE_PAL || defined(__DOXYGEN__) typedef struct {
/** uint32_t moder;
* @brief PAL setup. uint32_t otyper;
* @details Digital I/O ports static configuration as defined in @p board.h. uint32_t ospeedr;
* This variable is used by the HAL when initializing the PAL driver. uint32_t pupdr;
*/ uint32_t odr;
const PALConfig pal_default_config = { 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 #if STM32_HAS_GPIOA
{VAL_GPIOA_MODER, VAL_GPIOA_OTYPER, VAL_GPIOA_OSPEEDR, VAL_GPIOA_PUPDR, {VAL_GPIOA_MODER, VAL_GPIOA_OTYPER, VAL_GPIOA_OSPEEDR, VAL_GPIOA_PUPDR,
VAL_GPIOA_ODR, VAL_GPIOA_AFRL, VAL_GPIOA_AFRH}, 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} 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 #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); // extern void si5351_setup(void);
@ -129,6 +187,7 @@ void __early_init(void) {
#endif #endif
} }
// si5351_setup(); // si5351_setup();
stm32_gpio_init();
stm32_clock_init(); stm32_clock_init();
} }

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

@ -32,6 +32,7 @@
*/ */
#define STM32F3xx_MCUCONF #define STM32F3xx_MCUCONF
#define STM32F303_MCUCONF
/* /*
* HAL driver system settings. * HAL driver system settings.
@ -111,9 +112,9 @@
//#define STM32_ADC_ADC4_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) //#define STM32_ADC_ADC4_DMA_STREAM STM32_DMA_STREAM_ID(2, 2)
#define STM32_ADC_ADC12_DMA_PRIORITY 2 #define STM32_ADC_ADC12_DMA_PRIORITY 2
//#define STM32_ADC_ADC34_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_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_ADC34_DMA_IRQ_PRIORITY 5
//#define STM32_ADC_ADC12_CLOCK_MODE ADC_CCR_CKMODE_ADCCK //#define STM32_ADC_ADC12_CLOCK_MODE ADC_CCR_CKMODE_ADCCK
//#define STM32_ADC_ADC12_CLOCK_MODE ADC_CCR_CKMODE_AHB_DIV2 //#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_TIM2 FALSE
#define STM32_GPT_USE_TIM3 FALSE #define STM32_GPT_USE_TIM3 FALSE
#define STM32_GPT_USE_TIM4 TRUE #define STM32_GPT_USE_TIM4 TRUE
#define STM32_GPT_TIM1_IRQ_PRIORITY 2 #define STM32_GPT_TIM1_IRQ_PRIORITY 3
#define STM32_GPT_TIM2_IRQ_PRIORITY 2 #define STM32_GPT_TIM2_IRQ_PRIORITY 3
#define STM32_GPT_TIM3_IRQ_PRIORITY 2 #define STM32_GPT_TIM3_IRQ_PRIORITY 3
#define STM32_GPT_TIM4_IRQ_PRIORITY 2 #define STM32_GPT_TIM4_IRQ_PRIORITY 3
/* /*
* I2C driver system settings. * I2C driver system settings.
@ -184,8 +185,8 @@
STM32_I2S_MODE_RX) STM32_I2S_MODE_RX)
#define STM32_I2S_SPI2_MODE (STM32_I2S_MODE_SLAVE | \ #define STM32_I2S_SPI2_MODE (STM32_I2S_MODE_SLAVE | \
STM32_I2S_MODE_RX ) STM32_I2S_MODE_RX )
#define STM32_I2S_SPI1_IRQ_PRIORITY 2 #define STM32_I2S_SPI1_IRQ_PRIORITY 3
#define STM32_I2S_SPI2_IRQ_PRIORITY 2 #define STM32_I2S_SPI2_IRQ_PRIORITY 3
#define STM32_I2S_SPI1_DMA_PRIORITY 1 #define STM32_I2S_SPI1_DMA_PRIORITY 1
#define STM32_I2S_SPI2_DMA_PRIORITY 1 #define STM32_I2S_SPI2_DMA_PRIORITY 1
#define STM32_I2S_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) #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_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3)
#define STM32_SPI_SPI1_DMA_PRIORITY 1 #define STM32_SPI_SPI1_DMA_PRIORITY 1
#define STM32_SPI_SPI2_DMA_PRIORITY 1 #define STM32_SPI_SPI2_DMA_PRIORITY 1
#define STM32_SPI_SPI1_IRQ_PRIORITY 2 #define STM32_SPI_SPI1_IRQ_PRIORITY 3
#define STM32_SPI_SPI2_IRQ_PRIORITY 2 #define STM32_SPI_SPI2_IRQ_PRIORITY 3
#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") #define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure")
/* /*
* ST driver system settings. * ST driver system settings.
*/ */
#define STM32_ST_IRQ_PRIORITY 2 #define STM32_ST_IRQ_PRIORITY 3
#define STM32_ST_USE_TIMER 2 #define STM32_ST_USE_TIMER 2
/* /*

@ -29,6 +29,9 @@
#define _CHCONF_H_ #define _CHCONF_H_
#define _CHIBIOS_RT_CONF_ #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. * setting also defines the system tick time unit.
*/ */
#define CH_CFG_ST_FREQUENCY 10000 #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. * @brief Time delta constant for the tick-less mode.
@ -140,6 +145,7 @@
* @note The default is @p TRUE. * @note The default is @p TRUE.
*/ */
#define CH_CFG_USE_TM FALSE #define CH_CFG_USE_TM FALSE
#define CH_CFG_USE_TIMESTAMP FALSE
/** /**
* @brief Threads registry APIs. * @brief Threads registry APIs.
@ -305,6 +311,20 @@
*/ */
#define CH_CFG_USE_MEMPOOLS FALSE #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. * @brief Dynamic Threads APIs.
* @details If enabled then the dynamic threads creation APIs are included * @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. * @brief Threads descriptor structure extension.
* @details User fields added to the end of the @p thread_t structure. * @details User fields added to the end of the @p thread_t structure.
@ -522,6 +554,9 @@
/* Trace code here.*/ \ /* 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; 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){ void printObjectInit(printStream *ps, int size, uint8_t *buffer){
ps->vmt = &vmt; ps->vmt = &vmt;
ps->buffer = buffer; 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 #if STM32_ADC_DUAL_MODE
ADCD1.adcs = ADC2; ADCD1.adcs = ADC2;
#endif #endif
ADCD1.dmastp = STM32_DMA_STREAM(STM32_ADC_ADC1_DMA_STREAM); ADCD1.dmastp = NULL;
ADCD1.dmamode = ADC_DMA_SIZE | ADCD1.dmamode = ADC_DMA_SIZE |
STM32_DMA_CR_PL(STM32_ADC_ADC1_DMA_PRIORITY) | STM32_DMA_CR_PL(STM32_ADC_ADC1_DMA_PRIORITY) |
STM32_DMA_CR_DIR_P2M | STM32_DMA_CR_DIR_P2M |
@ -461,7 +461,7 @@ void adc_lld_init(void) {
ADCD2.adcc = ADC123_COMMON; ADCD2.adcc = ADC123_COMMON;
#endif #endif
ADCD2.adcm = ADC2; ADCD2.adcm = ADC2;
ADCD2.dmastp = STM32_DMA_STREAM(STM32_ADC_ADC2_DMA_STREAM); ADCD2.dmastp = NULL;
ADCD2.dmamode = ADC_DMA_SIZE | ADCD2.dmamode = ADC_DMA_SIZE |
STM32_DMA_CR_PL(STM32_ADC_ADC2_DMA_PRIORITY) | STM32_DMA_CR_PL(STM32_ADC_ADC2_DMA_PRIORITY) |
STM32_DMA_CR_DIR_P2M | STM32_DMA_CR_DIR_P2M |
@ -483,7 +483,7 @@ void adc_lld_init(void) {
#if STM32_ADC_DUAL_MODE #if STM32_ADC_DUAL_MODE
ADCD3.adcs = ADC4; ADCD3.adcs = ADC4;
#endif #endif
ADCD3.dmastp = STM32_DMA_STREAM(STM32_ADC_ADC3_DMA_STREAM); ADCD3.dmastp = NULL;
ADCD3.dmamode = ADC_DMA_SIZE | ADCD3.dmamode = ADC_DMA_SIZE |
STM32_DMA_CR_PL(STM32_ADC_ADC3_DMA_PRIORITY) | STM32_DMA_CR_PL(STM32_ADC_ADC3_DMA_PRIORITY) |
STM32_DMA_CR_DIR_P2M | STM32_DMA_CR_DIR_P2M |
@ -496,7 +496,7 @@ void adc_lld_init(void) {
adcObjectInit(&ADCD4); adcObjectInit(&ADCD4);
ADCD4.adcc = ADC3_4_COMMON; ADCD4.adcc = ADC3_4_COMMON;
ADCD4.adcm = ADC4; ADCD4.adcm = ADC4;
ADCD4.dmastp = STM32_DMA_STREAM(STM32_ADC_ADC4_DMA_STREAM); ADCD4.dmastp = NULL;
ADCD4.dmamode = ADC_DMA_SIZE | ADCD4.dmamode = ADC_DMA_SIZE |
STM32_DMA_CR_PL(STM32_ADC_ADC4_DMA_PRIORITY) | STM32_DMA_CR_PL(STM32_ADC_ADC4_DMA_PRIORITY) |
STM32_DMA_CR_DIR_P2M | STM32_DMA_CR_DIR_P2M |
@ -524,13 +524,13 @@ void adc_lld_init(void) {
rccEnableADC12(FALSE); rccEnableADC12(FALSE);
rccResetADC12(); rccResetADC12();
ADC1_2_COMMON->CCR = STM32_ADC_ADC12_CLOCK_MODE | ADC_DMA_MDMA; ADC1_2_COMMON->CCR = STM32_ADC_ADC12_CLOCK_MODE | ADC_DMA_MDMA;
rccDisableADC12(FALSE); rccDisableADC12();
#endif #endif
#if STM32_ADC_USE_ADC3 || STM32_ADC_USE_ADC4 #if STM32_ADC_USE_ADC3 || STM32_ADC_USE_ADC4
rccEnableADC34(FALSE); rccEnableADC34(FALSE);
rccResetADC34(); rccResetADC34();
ADC3_4_COMMON->CCR = STM32_ADC_ADC34_CLOCK_MODE | ADC_DMA_MDMA; ADC3_4_COMMON->CCR = STM32_ADC_ADC34_CLOCK_MODE | ADC_DMA_MDMA;
rccDisableADC34(FALSE); rccDisableADC34();
#endif #endif
#endif #endif
@ -538,7 +538,7 @@ void adc_lld_init(void) {
rccEnableADC123(FALSE); rccEnableADC123(FALSE);
rccResetADC123(); rccResetADC123();
ADC123_COMMON->CCR = STM32_ADC_ADC123_CLOCK_MODE | ADC_DMA_MDMA; ADC123_COMMON->CCR = STM32_ADC_ADC123_CLOCK_MODE | ADC_DMA_MDMA;
rccDisableADC123(FALSE); rccDisableADC123();
#endif #endif
} }
@ -560,12 +560,11 @@ void adc_lld_start(ADCDriver *adcp) {
if (adcp->state == ADC_STOP) { if (adcp->state == ADC_STOP) {
#if STM32_ADC_USE_ADC1 #if STM32_ADC_USE_ADC1
if (&ADCD1 == adcp) { if (&ADCD1 == adcp) {
bool b; adcp->dmastp = dmaStreamAllocI(STM32_ADC_ADC1_DMA_STREAM,
b = dmaStreamAllocate(adcp->dmastp, STM32_ADC_ADC1_DMA_IRQ_PRIORITY,
STM32_ADC_ADC1_DMA_IRQ_PRIORITY, (stm32_dmaisr_t)adc_lld_serve_dma_interrupt,
(stm32_dmaisr_t)adc_lld_serve_dma_interrupt, (void *)adcp);
(void *)adcp); osalDbgAssert(adcp->dmastp != NULL, "unable to allocate stream");
osalDbgAssert(!b, "stream already allocated");
clkmask |= (1 << 0); clkmask |= (1 << 0);
#if defined(STM32F3XX) #if defined(STM32F3XX)
@ -579,12 +578,11 @@ void adc_lld_start(ADCDriver *adcp) {
#if STM32_ADC_USE_ADC2 #if STM32_ADC_USE_ADC2
if (&ADCD2 == adcp) { if (&ADCD2 == adcp) {
bool b; adcp->dmastp = dmaStreamAllocI(STM32_ADC_ADC2_DMA_STREAM,
b = dmaStreamAllocate(adcp->dmastp, STM32_ADC_ADC2_DMA_IRQ_PRIORITY,
STM32_ADC_ADC2_DMA_IRQ_PRIORITY, (stm32_dmaisr_t)adc_lld_serve_dma_interrupt,
(stm32_dmaisr_t)adc_lld_serve_dma_interrupt, (void *)adcp);
(void *)adcp); osalDbgAssert(adcp->dmastp != NULL, "unable to allocate stream");
osalDbgAssert(!b, "stream already allocated");
clkmask |= (1 << 1); clkmask |= (1 << 1);
#if defined(STM32F3XX) #if defined(STM32F3XX)
@ -598,12 +596,11 @@ void adc_lld_start(ADCDriver *adcp) {
#if STM32_ADC_USE_ADC3 #if STM32_ADC_USE_ADC3
if (&ADCD3 == adcp) { if (&ADCD3 == adcp) {
bool b; adcp->dmastp = dmaStreamAllocI(STM32_ADC_ADC3_DMA_STREAM,
b = dmaStreamAllocate(adcp->dmastp, STM32_ADC_ADC3_DMA_IRQ_PRIORITY,
STM32_ADC_ADC3_DMA_IRQ_PRIORITY, (stm32_dmaisr_t)adc_lld_serve_dma_interrupt,
(stm32_dmaisr_t)adc_lld_serve_dma_interrupt, (void *)adcp);
(void *)adcp); osalDbgAssert(adcp->dmastp != NULL, "unable to allocate stream");
osalDbgAssert(!b, "stream already allocated");
clkmask |= (1 << 2); clkmask |= (1 << 2);
#if defined(STM32F3XX) #if defined(STM32F3XX)
@ -617,12 +614,11 @@ void adc_lld_start(ADCDriver *adcp) {
#if STM32_ADC_USE_ADC4 #if STM32_ADC_USE_ADC4
if (&ADCD4 == adcp) { if (&ADCD4 == adcp) {
bool b; adcp->dmastp = dmaStreamAllocI(STM32_ADC_ADC4_DMA_STREAM,
b = dmaStreamAllocate(adcp->dmastp, STM32_ADC_ADC4_DMA_IRQ_PRIORITY,
STM32_ADC_ADC4_DMA_IRQ_PRIORITY, (stm32_dmaisr_t)adc_lld_serve_dma_interrupt,
(stm32_dmaisr_t)adc_lld_serve_dma_interrupt, (void *)adcp);
(void *)adcp); osalDbgAssert(adcp->dmastp != NULL, "unable to allocate stream");
osalDbgAssert(!b, "stream already allocated");
clkmask |= (1 << 3); clkmask |= (1 << 3);
#if defined(STM32F3XX) #if defined(STM32F3XX)
@ -671,7 +667,8 @@ void adc_lld_stop(ADCDriver *adcp) {
if (adcp->state == ADC_READY) { if (adcp->state == ADC_READY) {
/* Releasing the associated DMA channel.*/ /* Releasing the associated DMA channel.*/
dmaStreamRelease(adcp->dmastp); dmaStreamFreeI(adcp->dmastp);
adcp->dmastp = NULL;
/* Stopping the ongoing conversion, if any.*/ /* Stopping the ongoing conversion, if any.*/
adc_lld_stop_adc(adcp); adc_lld_stop_adc(adcp);
@ -727,16 +724,16 @@ void adc_lld_stop(ADCDriver *adcp) {
#if defined(STM32F3XX) #if defined(STM32F3XX)
if ((clkmask & 0x3) == 0) { if ((clkmask & 0x3) == 0) {
rccDisableADC12(FALSE); rccDisableADC12();
} }
if ((clkmask & 0xC) == 0) { if ((clkmask & 0xC) == 0) {
rccDisableADC34(FALSE); rccDisableADC34();
} }
#endif #endif
#if defined(STM32L4XX) #if defined(STM32L4XX)
if ((clkmask & 0x7) == 0) { if ((clkmask & 0x7) == 0) {
rccDisableADC123(FALSE); rccDisableADC123();
} }
#endif #endif
} }

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

@ -526,7 +526,10 @@ void ili9341_init(void)
LCD_CS_HIGH; 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 // Any LCD exchange start from this
#ifdef __USE_DISPLAY_DMA__ #ifdef __USE_DISPLAY_DMA__
dmaChannelWaitCompletionRxTx(); dmaChannelWaitCompletionRxTx();
@ -663,8 +666,11 @@ void ili9341_bulk_finish(void){
} }
#endif #endif
// Copy part of spi_buffer to region, no wait completion after if buffer count !=1 // Copy part of spi_buffer to region, no wait completion after if buffer count !=1
#ifndef ili9341_bulk_continue #ifndef ili9341_bulk_continue
void ili9341_bulk_continue(int x, int y, int w, int h) // 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_bulk_finish(); // Wait DMA
ili9341_DMA_bulk(x, y, w, h, ili9341_get_cell_buffer()); // Send new cell data 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); 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; pixel_t *buf = spi_buffer;
uint8_t bits = 0; 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 // Init small lcd print stream
struct lcd_printStreamVMT { struct lcd_printStreamVMT {
_base_sequential_stream_methods _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}; lcdPrintStream ps = {&lcd_vmt, x, y, x, y};
// Performing the print operation using the common code. // Performing the print operation using the common code.
va_list ap; va_list ap;
@ -1357,7 +1372,7 @@ static uint8_t SD_WaitNotBusy(uint32_t wait_time) {
// Receive data block from SD // Receive data block from SD
static bool SD_RxDataBlock(uint8_t *buff, uint16_t len, uint8_t token) { static bool SD_RxDataBlock(uint8_t *buff, uint16_t len, uint8_t token) {
// loop until receive read response token or timeout ~50ms // 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"); DEBUG_PRINT(" rx SD_WaitDataToken err\r\n");
return FALSE; return FALSE;
} }
@ -1408,7 +1423,7 @@ static bool SD_TxDataBlock(const uint8_t *buff, uint16_t len, uint8_t token) {
} }
#if 1 #if 1
// Wait busy (recommended timeout is 250ms (500ms for SDXC) set 250ms // 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) if (resp == 0xFF)
return TRUE; return TRUE;
#else #else
@ -1427,7 +1442,7 @@ static uint8_t SD_SendCmd(uint8_t cmd, uint32_t arg) {
uint8_t buf[6]; uint8_t buf[6];
volatile uint8_t r1; volatile uint8_t r1;
// wait SD ready after last Tx (recommended timeout is 250ms (500ms for SDXC) set 250ms // 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); DEBUG_PRINT(" SD_WaitNotBusy CMD%d err, %02x\r\n", cmd-0x40, (uint32_t)r1);
return 0xFF; 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 // Nothing to do for this command if each write operation to the media is completed
// within the disk_write function. // within the disk_write function.
case CTRL_SYNC: case CTRL_SYNC:
if (SD_WaitNotBusy(MS2ST(200)) == 0xFF) res = RES_OK; if (SD_WaitNotBusy(TIME_MS2I(200)) == 0xFF) res = RES_OK;
break; break;
#if FF_USE_TRIM == 1 #if FF_USE_TRIM == 1
// Informs the device the data on the block of sectors is no longer needed and it can be erased. // 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) { while (1) {
// START_PROFILE // START_PROFILE
if (sweep_mode&(SWEEP_ENABLE|SWEEP_ONCE)) { 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.frequency0 = setting.frequency0;
b.data.frequency1 = setting.frequency1; b.data.frequency1 = setting.frequency1;
if (setting.auto_attenuation) if (setting.auto_attenuation)
@ -209,7 +210,7 @@ static THD_FUNCTION(Thread1, arg)
{ {
completed = sweep(true); completed = sweep(true);
#ifdef __USE_SD_CARD__ #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; uint16_t old_mode = config._mode;
config._mode |= _MODE_AUTO_FILENAME; config._mode |= _MODE_AUTO_FILENAME;
save_csv(1+(2<<0)); // frequencies + trace 1 save_csv(1+(2<<0)); // frequencies + trace 1
@ -455,7 +456,7 @@ VNA_SHELL_FUNCTION(cmd_restart)
(void)argc; (void)argc;
(void)argv; (void)argv;
if (argc == 1) { if (argc == 1) {
restart_interval = S2ST(my_atoi(argv[0])); restart_interval = TIME_S2I(my_atoi(argv[0]));
if (restart_interval) { if (restart_interval) {
restart_set_time = chVTGetSystemTimeX(); restart_set_time = chVTGetSystemTimeX();
if (restart_set_time == 0) if (restart_set_time == 0)
@ -2418,7 +2419,7 @@ VNA_SHELL_FUNCTION(cmd_threads)
#endif #endif
shell_printf("%08x|%08x|%08x|%08x|%4u|%4u|%9s|%12s"VNA_SHELL_NEWLINE_STR, 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, 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->name == NULL ? "" : tp->name);
tp = chRegNextThread(tp); tp = chRegNextThread(tp);
} while (tp != NULL); } while (tp != NULL);
@ -2697,18 +2698,21 @@ void shell_update_speed(void){
} }
void shell_reset_console(void){ void shell_reset_console(void){
osalSysLock();
// Reset I/O queue over USB (for USB need also connect/disconnect) // Reset I/O queue over USB (for USB need also connect/disconnect)
if (usb_IsActive()){ if (usb_IsActive()){
if (config._mode & _MODE_SERIAL) if (config._mode & _MODE_SERIAL)
sduDisconnectI(&SDU1); sduSuspendHookI(&SDU1);
else else
sduConfigureHookI(&SDU1); sduConfigureHookI(&SDU1);
} }
// Reset I/O queue over Serial // Reset I/O queue over Serial
// oqResetI(&SD1.oqueue); // oqResetI(&SD1.oqueue);
// iqResetI(&SD1.iqueue); // iqResetI(&SD1.iqueue);
qResetI(&SD1.oqueue); oqResetI(&SD1.oqueue);
qResetI(&SD1.iqueue); iqResetI(&SD1.iqueue);
osalOsRescheduleS();
osalSysUnlock();
} }
@ -2886,7 +2890,7 @@ static void VNAShell_executeLine(char *line)
int timeout_count = 0; int timeout_count = 0;
msg_t result; msg_t result;
do { do {
result = osalThreadEnqueueTimeoutS(&shell_thread, MS2ST(5000)); // 5 second timeout result = osalThreadEnqueueTimeoutS(&shell_thread, TIME_MS2I(5000)); // 5 second timeout
if (result == MSG_TIMEOUT) { if (result == MSG_TIMEOUT) {
timeout_count++; timeout_count++;
if (timeout_count > 3) { if (timeout_count > 3) {
@ -3004,6 +3008,7 @@ static PWMConfig pwmcfg = {
{PWM_OUTPUT_DISABLED, NULL} {PWM_OUTPUT_DISABLED, NULL}
}, },
0, 0,
0,
0 0
}; };
@ -3446,8 +3451,35 @@ int main(void)
} }
} }
/* The prototype shows it is a naked function - in effect this is just an #ifdef TINYSA4
assembly function. */ 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 HardFault_Handler(void);
void hard_fault_handler_c(uint32_t *sp) __attribute__((naked)); 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)); __asm volatile("mrs %0, psp \n\t" : "=r"(sp));
hard_fault_handler_c(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) void hard_fault_handler_c(uint32_t *sp)
#endif
{ {
#ifdef TINYSA4 #ifdef TINYSA4
uint32_t r0 = sp[0]; uint32_t r0 = sp[0];
uint32_t r1 = sp[1]; uint32_t r1 = sp[1];
uint32_t r2 = sp[2]; uint32_t r2 = sp[2];
uint32_t r3 = sp[3]; uint32_t r3 = sp[3];
register uint32_t r4 __asm("r4"); uint32_t r4 = callee[0];
register uint32_t r5 __asm("r5"); uint32_t r5 = callee[1];
register uint32_t r6 __asm("r6"); uint32_t r6 = callee[2];
register uint32_t r7 __asm("r7"); uint32_t r7 = callee[3];
register uint32_t r8 __asm("r8"); uint32_t r8 = callee[4];
register uint32_t r9 __asm("r9"); uint32_t r9 = callee[5];
register uint32_t r10 __asm("r10"); uint32_t r10 = callee[6];
register uint32_t r11 __asm("r11"); uint32_t r11 = callee[7];
uint32_t r12 = sp[4]; uint32_t r12 = sp[4];
uint32_t lr = sp[5]; uint32_t lr = sp[5];
uint32_t pc = sp[6]; uint32_t pc = sp[6];
@ -3516,7 +3553,7 @@ void hard_fault_handler_c(uint32_t *sp)
#endif #endif
lcd_printf(x, y+=FONT_STR_HEIGHT, "%08x|%08x|%08x|%08x|%4u|%4u|%9s|%12s", 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, 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->name == NULL ? "" : tp->name);
tp = chRegNextThread(tp); tp = chRegNextThread(tp);
} while (tp != NULL); } 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 plot_init(void);
void update_grid(void); void update_grid(void);
void update_grid_if_changed(void);
void request_to_redraw_grid(void); void request_to_redraw_grid(void);
void redraw_frame(void); void redraw_frame(void);
//void redraw_all(void); //void redraw_all(void);

@ -110,19 +110,24 @@ float2int(float v)
} }
#endif #endif
void update_grid(void) static void calculate_grid(int16_t *offset, int16_t *width, freq_t *span)
{ {
freq_t gdigit = 1000000000; freq_t gdigit = 1000000000;
freq_t fstart = get_sweep_frequency(ST_START) + (setting.frequency_offset - FREQUENCY_SHIFT); freq_t fstart = get_sweep_frequency(ST_START) + (setting.frequency_offset - FREQUENCY_SHIFT);
freq_t fspan = get_sweep_frequency(ST_SPAN); freq_t fspan = get_sweep_frequency(ST_SPAN);
freq_t grid; freq_t grid;
bool time_domain = fspan == 0;
if (fspan == 0) { if (time_domain) {
fspan = setting.actual_sweep_time_us; // Time in uS fspan = setting.actual_sweep_time_us; // Time in uS
fstart = 0; fstart = 0;
} }
if (fspan == 0)
fspan = 1;
if (config.gridlines == 0) { if (config.gridlines == 0) {
grid = fspan/10; grid = fspan/10;
if (grid == 0)
grid = 1;
} else { } else {
if (config.gridlines < 3) if (config.gridlines < 3)
config.gridlines = 6; config.gridlines = 6;
@ -139,21 +144,54 @@ void update_grid(void)
gdigit /= 10; gdigit /= 10;
} }
} }
grid_span = grid; *span = grid;
if (grid > 1000) { if (time_domain) {
grid_offset = (WIDTH) * ((fstart % grid) / 100) / (fspan / 100); // The zero-span x axis is measured in microseconds. Keep the full ratio
grid_width = (WIDTH) * (grid / 100) / (fspan / 1000); // 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 { } else {
grid_offset = (WIDTH) * ((fstart % grid)) / (fspan); *offset = (WIDTH) * ((fstart % grid)) / (fspan);
grid_width = (WIDTH) * (grid) / (fspan/10); *width = (WIDTH) * (grid) / (fspan/10);
} }
if (*width < 1)
*width = 1;
if (config.gridlines == 0) 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) // if (setting.waterfall)
set_level_meter_or_waterfall(); set_level_meter_or_waterfall();
redraw_request |= REDRAW_FREQUENCY | REDRAW_AREA; 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 #if 0
static int static int
rectangular_grid(int x, int y) 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 // Init small cell print stream
struct cellprintStreamVMT { struct cellprintStreamVMT {
_base_sequential_stream_methods _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}; screenPrintStream ps = {&cell_vmt, x, y};
// Select font and skip print if not on cell (at top/bottom) // Select font and skip print if not on cell (at top/bottom)
switch (*fmt++){ switch (*fmt++){

@ -499,6 +499,9 @@ const freq_t fh_high[] = { 480000000, 960000000, 1920000000, 2880000000, 3840000
uint8_t in_selftest = false; uint8_t in_selftest = false;
uint8_t ignore_stored = 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_step_test = false;
uint8_t in_calibration = false; uint8_t in_calibration = false;
uint8_t calibration_stage; 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;
static pureRSSI_t correct_RSSI_freq; static pureRSSI_t correct_RSSI_freq;
systime_t start_of_sweep_timestamp; 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 static systime_t sweep_elapsed = 0; // Time since first start of sweeping, used only for auto attenuate
uint8_t signal_is_AM = false; uint8_t signal_is_AM = false;
static uint8_t check_for_AM = false; static uint8_t check_for_AM = false;
@ -3637,6 +3654,9 @@ bool depth_error = false;
#endif #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 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; int modulation_delay = 0;
@ -4761,7 +4781,7 @@ again: // Spur redu
skip_LO_setting: skip_LO_setting:
if (i == 0 && t == 0) // if first point in scan (here is get 1 point data) 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 (MODE_OUTPUT(setting.mode)) { // No substepping and no RSSI in output mode
if (break_on_operation && operation_requested) // break subscanning if requested if (break_on_operation && operation_requested) // break subscanning if requested
@ -4893,7 +4913,7 @@ again: // Spur redu
if (setting.trigger == T_SINGLE) { if (setting.trigger == T_SINGLE) {
set_trigger(T_DONE); set_trigger(T_DONE);
} }
start_of_sweep_timestamp = chVTGetSystemTimeX(); start_of_sweep_timestamp = SWEEP_CLOCK_NOW();
} }
TRACE(5); TRACE(5);
#ifdef TINYSA4 #ifdef TINYSA4
@ -5067,6 +5087,9 @@ void reset_band(void) {
#endif #endif
// main loop for measurement // main loop for measurement
#ifdef TINYSA4
__attribute__((optimize("O2,no-strict-aliasing")))
#endif
static bool sweep(bool break_on_operation) static bool sweep(bool break_on_operation)
{ {
float RSSI; float RSSI;
@ -5187,6 +5210,7 @@ static bool sweep(bool break_on_operation)
#endif #endif
setting.measure_sweep_time_us = 0; // start measure sweep time setting.measure_sweep_time_us = 0; // start measure sweep time
// start_of_sweep_timestamp = chVTGetSystemTimeX(); // Will be set in perform // 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. 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 ( if (
#ifdef TINYSA4 #ifdef TINYSA4
progress_bar && progress_bar &&
#endif #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; // Expected long sweeps can use their known duration directly. For an
ili9341_set_background(LCD_SWEEP_LINE_COLOR); // expected fast sweep, sample every 64th point until an unexpected
ili9341_fill(OFFSETX, CHART_BOTTOM+1, pos, 1); // update sweep progress bar // one-second overrun is observed, then resume the normal 8-point rate.
ili9341_set_background(LCD_BG_COLOR); // This retains overrun progress while avoiding timer traffic in the
ili9341_fill(OFFSETX+pos, CHART_BOTTOM+1, WIDTH-pos, 1); // common sub-second path.
systime_t local_sweep_time = setting.actual_sweep_time_us;
if (local_sweep_time > 10 * ONE_SECOND_TIME) { if (local_sweep_time <= ONE_SECOND_TIME)
plot_into_index(measured); local_sweep_time = sa_ST2US(SWEEP_CLOCK_NOW() - start_of_sweep_timestamp);
redraw_request |= REDRAW_CELLS | REDRAW_BATTERY | REDRAW_INBETWEEN; if (local_sweep_time > ONE_SECOND_TIME) {
// plot trace and other indications as raster progress_mask = 0x07;
draw_all(true); // flush markmap only if scan completed to prevent 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__ #ifdef __SWEEP_RESTART__
if (MODE_OUTPUT(setting.mode) && (setting.level_sweep != 0 || get_sweep_frequency(ST_SPAN) != 0)) if (MODE_OUTPUT(setting.mode) && (setting.level_sweep != 0 || get_sweep_frequency(ST_SPAN) != 0))
refresh_sweep_menu(i); refresh_sweep_menu(i);
#endif #endif
}
} }
// ----------------------- debug avoid -------------------------------- // ----------------------- debug avoid --------------------------------
if (debug_avoid) { if (debug_avoid) {
@ -5651,6 +5683,14 @@ static volatile int dummy;
// add_to_peak_finding(actual_t, i); // 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 ----------------- // ---------------------- process measured actual sweep time -----------------
// For CW mode value calculated in SI4432_Fill // For CW mode value calculated in SI4432_Fill
if (setting.measure_sweep_time_us == 0) 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 // Update actual time on change on status panel
uint32_t delta = abs((int)(setting.actual_sweep_time_us - setting.measure_sweep_time_us)); 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; redraw_request|=REDRAW_CAL_STATUS | REDRAW_FREQUENCY;
} }
setting.actual_sweep_time_us = setting.measure_sweep_time_us; 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! // Not possible reduce sweep time, it minimum!
if (setting.sweep_time_us < setting.actual_sweep_time_us && setting.additional_step_delay_us == 0){ 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!! // 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) { } else if (actual_max_level > target_level && setting.attenuate_x2 < 60) {
delta = actual_max_level - target_level; 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 ) { if (( delta < -5 || delta > +5) || delta > 10 ) {
setting.attenuate_x2 += delta + delta; setting.attenuate_x2 += delta + delta;
if (setting.attenuate_x2 < 0) if (setting.attenuate_x2 < 0)
@ -7117,6 +7163,7 @@ void selftest(int test)
{ {
bool no_wait = false; bool no_wait = false;
#ifdef TINYSA4 #ifdef TINYSA4
factory_selftest_direct_scratch = false;
bool old_ultra = config.ultra; bool old_ultra = config.ultra;
config.ultra = true; config.ultra = true;
// if (adc_vbat_read() < 3800) { // if (adc_vbat_read() < 3800) {
@ -7158,7 +7205,33 @@ void selftest(int test)
} }
do { do {
test_prepare(test_step); 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 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 test_status[test_step] = test_validate(test_step); // Validate test
if (test_step == 2) { if (test_step == 2) {

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

75
ui.c

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

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

Loading…
Cancel
Save

Powered by TurnKey Linux.