* Refactor clock delays and improve JTAG runtest timing logic
* Refactor time calculations to use CH_FREQUENCY for consistency across modules
* Improve delay mechanism for reference oscillator startup in portapack_tcxo_enable
* comment
* increasing the time
* copilot
This commit is contained in:
Pezsma
2026-08-21 19:56:54 +02:00
committed by GitHub
parent 0840756c0e
commit 84e7f517ba
8 changed files with 69 additions and 35 deletions
+1 -1
View File
@@ -59,7 +59,7 @@ void DfuMenu::paint(Painter& painter) {
text_info_line_7.set(to_string_dec_uint(shared_memory.m4_stack_usage, 6));
text_info_line_8.set(to_string_dec_uint(shared_memory.m4_performance_counter, 6));
text_info_line_9.set(to_string_dec_uint(shared_memory.m4_buffer_missed, 6));
text_info_line_10.set(to_string_dec_uint(chTimeNow() / 1000, 6));
text_info_line_10.set(to_string_dec_uint(chTimeNow() / CH_FREQUENCY, 6));
constexpr auto margin = 5;
+9 -2
View File
@@ -1012,10 +1012,17 @@ void SetTouchscreenThresholdView::focus() {
void SetTouchscreenThresholdView::on_frame_sync() {
if (!in_auto_detect) return;
uint32_t time_now = chTimeNow();
int32_t time_diff = time_now - time_start_auto_detect;
text_wait_timer.set("ETA " + to_string_dec_uint((10 - time_diff / 1000) <= 0 ? 0 : 10 - time_diff / 1000) + "s");
if (time_diff >= 10001 && !auto_detect_succeed_consumed) { // 10s
// Calculate elapsed seconds using CH_FREQUENCY
uint32_t elapsed_seconds = time_diff / CH_FREQUENCY;
int32_t remaining_seconds = 10 - (int32_t)elapsed_seconds;
if (remaining_seconds < 0) remaining_seconds = 0;
text_wait_timer.set("ETA " + to_string_dec_uint(remaining_seconds) + "s");
if (elapsed_seconds >= 10 && !auto_detect_succeed_consumed) { // 10s
in_auto_detect = false;
text_wait_timer.hidden(true);
text_hint.set("OK, press save and reboot");
+13 -13
View File
@@ -428,7 +428,7 @@ void ClockManager::portapack_tcxo_enable() {
/* Delay >10ms at 96MHz clock speed for reference oscillator to start. */
/* Delay an additional 1ms (arbitrary) for the clock generator to detect a signal. */
volatile uint32_t delay = 240000 + 24000;
volatile uint32_t delay = 2400000 + 24000;
while (delay--);
}
@@ -668,37 +668,37 @@ ClockManager::ReferenceSource ClockManager::detect_reference_source() {
}
ClockManager::Reference ClockManager::choose_reference() {
#ifdef PRALINE
const auto detected_reference = detect_reference_source();
if ((detected_reference == ReferenceSource::External) ||
(detected_reference == ReferenceSource::PortaPack)) {
const auto frequency = measure_gp_clkin_frequency();
if ((frequency >= 9850000) && (frequency <= 10150000)) {
return {detected_reference, 10000000};
}
}
#else
#ifndef PRALINE
if (hackrf_r9) {
gpio_control::r9_clkin_en.setActive();
volatile uint32_t delay = 240000 + 24000;
// Allow extra time for slower TCXOs on clone boards to stabilize before measurement
volatile uint32_t delay = 240000 + 240000;
while (delay--);
}
#endif
// Determine reference source (respects user config and Si5351 loss-of-signal)
const auto detected_reference = detect_reference_source();
// If an external or PortaPack source is detected, verify its actual frequency
if ((detected_reference == ReferenceSource::External) ||
(detected_reference == ReferenceSource::PortaPack)) {
const auto frequency = measure_gp_clkin_frequency();
// Check if the measured frequency is within the valid 10 MHz range
if ((frequency >= 9850000) && (frequency <= 10150000)) {
return {detected_reference, 10000000};
}
}
#ifndef PRALINE
if (hackrf_r9) {
// Disable r9 clock input if the 10 MHz validation failed
gpio_control::r9_clkin_en.setInactive();
}
#endif
// Fallback: Disable PortaPack TCXO and default to the HackRF 25 MHz crystal
portapack_tcxo_disable();
return {ReferenceSource::Xtal, 25000000};
}
+9 -4
View File
@@ -1130,13 +1130,18 @@ void SystemView::toggle_overlay() {
}
void SystemView::paint_overlay() {
static bool last_paint_state = false;
// Static variable to store the timestamp of the last update
static systime_t last_update_time = 0;
if (overlay_active) {
// paint background only every other second
if ((((chTimeNow() >> 10) & 0x01) == 0x01) == last_paint_state)
// Update exactly once per second (CH_FREQUENCY equals 1 second of ticks)
// This replaces the old hardcoded bit-shift logic for better portability
if ((chTimeNow() - last_update_time) < CH_FREQUENCY)
return;
last_paint_state = !last_paint_state;
// One second has passed, save the new timestamp
last_update_time = chTimeNow();
if (overlay_active == 1 && overlay)
overlay->set_dirty();
else if (overlay_active == 2 && overlay2)
+1 -1
View File
@@ -1180,7 +1180,7 @@ static void cmd_sysinfo(BaseSequentialStream* chp, int argc, char* argv[]) {
"M4 stack: " + to_string_dec_uint(shared_memory.m4_stack_usage) + "\r\n" +
"M0 cpu%: " + to_string_dec_uint(shared_memory.m4_performance_counter) + "\r\n" +
"M4 miss: " + to_string_dec_uint(shared_memory.m4_buffer_missed) + "\r\n" +
"uptime: " + to_string_dec_uint(chTimeNow() / 1000) + "\r\n";
"uptime: " + to_string_dec_uint(chTimeNow() / CH_FREQUENCY) + "\r\n";
fillOBuffer(&((SerialUSBDriver*)chp)->oqueue, (const uint8_t*)info.c_str(), info.length());
return;
+6 -3
View File
@@ -125,15 +125,18 @@ void update_performance_counters() {
if (performance_counter_active == 0x00)
return;
static bool last_paint_state = false;
if ((((chTimeNow() >> 10) & 0x01) == 0x01) == last_paint_state)
static systime_t last_update_time = 0;
// The MS2ST(1000) guarantees that this is exactly 1 second, regardless of the system clock setting.
if ((chTimeNow() - last_update_time) < MS2ST(1000))
return;
// Idle thread state is sometimes unuseable
if (chThdGetTicks(chSysGetIdleThread()) > 0x10000000)
return;
last_paint_state = !last_paint_state;
// Update the last update time
last_update_time = chTimeNow();
if (performance_counter_active == 0x01) {
auto utilisation = get_cpu_utilisation_in_percent();
+27 -10
View File
@@ -318,29 +318,33 @@ void I2CDevManager::create_thread() {
msg_t I2CDevManager::timer_fn(void* arg) {
(void)arg;
uint16_t curr_timer = 0; // seconds since thread start
while (1) {
systime_t start_time = chTimeNow();
bool changed = false;
// check if i2c scan needed
// Check if i2c scan is needed
if (force_scan || (scan_interval != 0 && curr_timer % scan_interval == 0)) {
changed = changed | scan();
force_scan = false;
}
// Update connected devices based on their own intervals
for (size_t i = 0; i < devlist.size(); i++) {
if (devlist[i].addr != 0 && devlist[i].dev && devlist[i].dev->query_interval != 0) {
if ((curr_timer % devlist[i].dev->query_interval) == 0) { // only if it is device's interval
devlist[i].dev->update(); // updates it's data, and broadcasts it. if there is any error it will handle in it, and later we can remove it
if ((curr_timer % devlist[i].dev->query_interval) == 0) {
devlist[i].dev->update();
}
}
}
// remove all unneeded items
// Remove all unneeded items (dead devices or devices throwing too many errors)
chMtxLock(&mutex_list);
size_t cnt = devlist.size();
devlist.erase(std::remove_if(devlist.begin(), devlist.end(), [](const I2DevListElement& x) {
if (x.addr == 0) return true;
if (x.dev && x.dev->need_del == true) return true; // self destruct on too many errors
return false; // won't remove the unidentified ones, so we can list them, and not trying all the time with them
if (x.dev && x.dev->need_del == true) return true;
return false;
}),
devlist.end());
chMtxUnlock();
@@ -350,11 +354,24 @@ msg_t I2CDevManager::timer_fn(void* arg) {
I2CDevListChangedMessage msg{};
EventDispatcher::send_message(msg);
}
systime_t end_time = chTimeNow();
systime_t delta = (end_time > start_time) ? end_time - start_time : 100; // wont calculate overflow, just guess.
if (delta > 950) delta = 950; // ensure minimum 50 milli sleep
chThdSleepMilliseconds(1000 - delta); // 1sec timer
systime_t end_time = chTimeNow();
// 1. Calculate elapsed ticks safely handling overflow
uint32_t delta_ticks = end_time - start_time;
// 2. Keep EVERYTHING in ticks (No MS conversion!) to prevent truncation drift
if (delta_ticks < CH_FREQUENCY) {
// Calculate exactly how many ticks are missing to complete 1 full second
uint32_t sleep_ticks = CH_FREQUENCY - delta_ticks;
// Sleep using native ticks instead of milliseconds
chThdSleep(sleep_ticks);
} else {
// Safety fallback: if processing took longer than 1 second, sleep 50ms to yield CPU
chThdSleepMilliseconds(50);
}
++curr_timer;
}
return 0;
+3 -1
View File
@@ -59,8 +59,10 @@ class JTAG {
void runtest_ms(const size_t count) {
auto starttime = chTimeNow();
// We convert the count in milliseconds to system ticks:
auto duration_ticks = MS2ST(count) + 1;
while ((chTimeNow() - starttime) < (count + 1))
while ((chTimeNow() - starttime) < duration_ticks)
target.clock(0, 0);
}