fix hardware timers interrupting flash writes

This commit is contained in:
wiredopposite
2025-01-20 11:50:17 -07:00
parent 12654e351c
commit 43bb4408af
4 changed files with 92 additions and 2 deletions

View File

@@ -9,6 +9,7 @@
#include "Board/board_api.h" #include "Board/board_api.h"
#include "Board/ogxm_log.h" #include "Board/ogxm_log.h"
#include "Board/board_api_private/board_api_private.h" #include "Board/board_api_private/board_api_private.h"
#include "TaskQueue/TaskQueue.h"
namespace board_api { namespace board_api {
@@ -60,10 +61,11 @@ void usb::disconnect_all()
{ {
OGXM_LOG("Disconnecting USB and resetting Core1\n"); OGXM_LOG("Disconnecting USB and resetting Core1\n");
TaskQueue::suspend_delayed_tasks();
multicore_reset_core1(); multicore_reset_core1();
sleep_ms(300); sleep_ms(500);
tud_disconnect(); tud_disconnect();
sleep_ms(300); sleep_ms(500);
} }
// If using PicoW, only use this method from the core running btstack and after you've called init_bluetooth // If using PicoW, only use this method from the core running btstack and after you've called init_bluetooth

View File

@@ -157,6 +157,11 @@ void TaskQueue::timer_irq_handler()
uint64_t now = get_time_64_us(); uint64_t now = get_time_64_us();
uint32_t irq_state = spin_lock_blocking(spinlock_delayed_); uint32_t irq_state = spin_lock_blocking(spinlock_delayed_);
if (suspended_)
{
spin_unlock(spinlock_delayed_, irq_state);
return;
}
for (auto& task : task_queue_delayed_) for (auto& task : task_queue_delayed_)
{ {
@@ -185,5 +190,63 @@ void TaskQueue::timer_irq_handler()
timer_hw->alarm[alarm_num_] = static_cast<uint32_t>(next_target_time); timer_hw->alarm[alarm_num_] = static_cast<uint32_t>(next_target_time);
} }
spin_unlock(spinlock_delayed_, irq_state);
}
void TaskQueue::suspend_delayed_tasks()
{
get_core0().suspend_delayed();
#if (OGXM_BOARD != PI_PICOW) && (OGXM_BOARD != PI_PICO2W)
get_core1().suspend_delayed();
#endif
}
void TaskQueue::resume_delayed_tasks()
{
get_core0().resume_delayed();
#if (OGXM_BOARD != PI_PICOW) && (OGXM_BOARD != PI_PICO2W)
get_core1().resume_delayed();
#endif
}
void TaskQueue::suspend_delayed()
{
uint32_t irq_state = spin_lock_blocking(spinlock_delayed_);
if (suspended_)
{
spin_unlock(spinlock_delayed_, irq_state);
return;
}
hw_clear_bits(&timer_hw->intr, 1u << alarm_num_);
suspended_time_ = get_time_64_us();
suspended_ = true;
spin_unlock(spinlock_delayed_, irq_state);
}
void TaskQueue::resume_delayed()
{
uint32_t irq_state = spin_lock_blocking(spinlock_delayed_);
if (!suspended_)
{
spin_unlock(spinlock_delayed_, irq_state);
return;
}
uint64_t now = get_time_64_us();
uint64_t elapsed_time = now - suspended_time_;
for (auto& task : task_queue_delayed_)
{
if (task.function)
{
task.target_time = std::max(task.target_time + elapsed_time, now + 10);
}
}
int64_t next_target_time = get_next_target_time_unsafe(task_queue_delayed_);
if (next_target_time >= 0)
{
timer_hw->alarm[alarm_num_] = static_cast<uint32_t>(next_target_time);
}
suspended_ = false;
spin_unlock(spinlock_delayed_, irq_state); spin_unlock(spinlock_delayed_, irq_state);
} }

View File

@@ -36,6 +36,14 @@ public:
{ {
get_core0().process_tasks(); get_core0().process_tasks();
} }
static inline void suspend_delayed_tasks()
{
get_core0().suspend_delayed();
}
static inline void resume_delayed_tasks()
{
get_core0().resume_delayed();
}
}; };
#if (OGXM_BOARD != PI_PICOW) && (OGXM_BOARD != PI_PICO2W) //BTstack uses core1 #if (OGXM_BOARD != PI_PICOW) && (OGXM_BOARD != PI_PICO2W) //BTstack uses core1
@@ -61,9 +69,20 @@ public:
{ {
get_core1().process_tasks(); get_core1().process_tasks();
} }
static inline void suspend_delayed_tasks()
{
get_core1().suspend_delayed();
}
static inline void resume_delayed_tasks()
{
get_core1().resume_delayed();
}
}; // Core1 }; // Core1
#endif // OGXM_BOARD != PI_PICOW #endif // OGXM_BOARD != PI_PICOW
static void suspend_delayed_tasks();
static void resume_delayed_tasks();
private: private:
enum class CoreNum : uint8_t enum class CoreNum : uint8_t
{ {
@@ -99,6 +118,9 @@ private:
uint32_t alarm_num_; uint32_t alarm_num_;
uint32_t new_task_id_ = 1; uint32_t new_task_id_ = 1;
bool suspended_ = false;
uint64_t suspended_time_ = 0;
int spinlock_queue_num_ = spin_lock_claim_unused(true); int spinlock_queue_num_ = spin_lock_claim_unused(true);
int spinlock_delayed_num_ = spin_lock_claim_unused(true); int spinlock_delayed_num_ = spin_lock_claim_unused(true);
spin_lock_t* spinlock_queue_ = spin_lock_instance(static_cast<uint>(spinlock_queue_num_)); spin_lock_t* spinlock_queue_ = spin_lock_instance(static_cast<uint>(spinlock_queue_num_));
@@ -124,6 +146,8 @@ private:
bool queue_task(const std::function<void()>& function); bool queue_task(const std::function<void()>& function);
void process_tasks(); void process_tasks();
void suspend_delayed();
void resume_delayed();
void timer_irq_handler(); void timer_irq_handler();
static uint64_t get_time_64_us(); static uint64_t get_time_64_us();

View File

@@ -95,6 +95,7 @@ Please visit [**this page**](https://bluepad32.readthedocs.io/en/latest/supporte
- OG Xbox communicator support (in some form) - OG Xbox communicator support (in some form)
- Generic bluetooth dongle support - Generic bluetooth dongle support
- Button macros - Button macros
- Rumble settings (intensity, enabled/disable, etc.)
## Hardware ## Hardware
For Pi Pico, RP2040-Zero, 4 channel, and ESP32 configurations, please see the hardware folder for diagrams. For Pi Pico, RP2040-Zero, 4 channel, and ESP32 configurations, please see the hardware folder for diagrams.