Handle button events outside interrupt context (#125)

A lot of the button tasks configure TMOS tasks, which causes a lot of
graphical glitches, when the bluetooth icon is drawn but the other
tasks for rendering the effects still run.

This also fixes the "WFI inside the interrupt handler" issue causing
poweroff to hang.
This commit is contained in:
puckipedia 2026-02-01 13:07:57 +01:00 committed by GitHub
parent 1d46c5edd1
commit 5df3122a75
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 61 additions and 2 deletions

View File

@ -1,4 +1,6 @@
#include "CH58xBLE_LIB.h"
#include "button.h"
#include <stdbool.h>
#define DEBOUNCE_HIGH_THRES (200) // 0-255
#define DEBOUNCE_LOW_THRES (55) // 0-255
@ -8,6 +10,13 @@
static volatile void (*onePressHandler[KEY_INDEX])(void) = { NULL };
static volatile void (*longPressHandler[KEY_INDEX])(void) = { NULL };
static volatile bool onePressPending[KEY_INDEX] = { false };
static volatile bool longPressPending[KEY_INDEX] = { false };
static tmosTaskID button_task_id = INVALID_TASK_ID;
#define BTN_PRESS (1 << 0)
static uint16_t btn_task(tmosTaskID, uint16_t);
void btn_init()
{
GPIOA_ModeCfg(KEY1_PIN, GPIO_ModeIN_PD);
@ -18,6 +27,11 @@ void btn_init()
PFIC_EnableIRQ(TMR3_IRQn);
}
void btn_init_task(void)
{
button_task_id = TMOS_ProcessEventRegister(btn_task);
}
void btn_onOnePress(int key, void (*handler)(void))
{
if (key >= KEY_INDEX) return;
@ -30,6 +44,41 @@ void btn_onLongPress(int key, void (*handler)(void))
longPressHandler[key] = handler;
}
void btn_tick(void)
{
for (int i = 0; i < KEY_INDEX; i++) {
if (onePressPending[i]) {
onePressPending[i] = false;
if (onePressHandler[i]) onePressHandler[i]();
}
if (longPressPending[i]) {
longPressPending[i] = false;
if (longPressHandler[i]) longPressHandler[i]();
}
}
}
static uint16_t btn_task(tmosTaskID id, uint16_t events)
{
if(events & SYS_EVENT_MSG) {
uint8 *pMsg = tmos_msg_receive(button_task_id);
if(pMsg != NULL)
{
tmos_msg_deallocate(pMsg);
}
return (events ^ SYS_EVENT_MSG);
}
if (events & BTN_PRESS) {
btn_tick();
return (events ^ BTN_PRESS);
}
return events;
}
__HIGH_CODE
static int debounce(int key, int is_press)
{
@ -59,11 +108,17 @@ static void check(int k)
hold[k]++;
if (hold[k] >= LONGPRESS_THRES && is_longpress[k] == 0) {
is_longpress[k] = 1;
if (longPressHandler[k]) longPressHandler[k]();
longPressPending[k] = true;
if (button_task_id != INVALID_TASK_ID) {
tmos_set_event(button_task_id, BTN_PRESS);
}
}
} else {
if (hold[k] > 0 && hold[k] < LONGPRESS_THRES) {
if (onePressHandler[k]) onePressHandler[k]();
onePressPending[k] = true;
if (button_task_id != INVALID_TASK_ID) {
tmos_set_event(button_task_id, BTN_PRESS);
}
}
is_longpress[k] = 0;
hold[k] = 0;

View File

@ -19,5 +19,7 @@ enum keys {
void btn_onOnePress(int key, void (*handler)(void));
void btn_onLongPress(int key, void (*handler)(void));
void btn_init();
void btn_init_task(void);
void btn_tick(void);
#endif /* __BUTTON_H__ */

View File

@ -344,6 +344,7 @@ static void disp_charging()
{
int blink = 0;
while (mode == BOOT) {
btn_tick();
int percent = batt_raw2percent(batt_raw());
if (charging_status()) {
@ -446,6 +447,7 @@ int main()
ble_setup();
spawn_tasks();
btn_init_task();
mode = NORMAL;
while (1) {