From 05b2fb4fcbbce9738ec947a2433c8e1984b3ed8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kuba=20Szczodrzy=C5=84ski?= Date: Wed, 14 Sep 2022 19:56:51 +0200 Subject: [PATCH] [beken-72xx] Implement micros() properly; use high-res timer for OS --- arduino/beken-72xx/cores/arduino/wiring.c | 30 ++++- arduino/libretuya/core/LibreTuyaConfig.h | 4 + builder/frameworks/beken-72xx-sdk.py | 3 + platform/beken-72xx/fixups/clock_cal.c | 127 ++++++++++++++++++++++ platform/beken-72xx/fixups/clock_rtos.c | 125 +++++++++++++++++++++ 5 files changed, 288 insertions(+), 1 deletion(-) create mode 100644 platform/beken-72xx/fixups/clock_cal.c create mode 100644 platform/beken-72xx/fixups/clock_rtos.c diff --git a/arduino/beken-72xx/cores/arduino/wiring.c b/arduino/beken-72xx/cores/arduino/wiring.c index 43ea08b..f8932aa 100644 --- a/arduino/beken-72xx/cores/arduino/wiring.c +++ b/arduino/beken-72xx/cores/arduino/wiring.c @@ -1,6 +1,9 @@ /* Copyright (c) Kuba SzczodrzyƄski 2022-06-19. */ #include +#include +#include +#include #include #include @@ -22,8 +25,33 @@ unsigned long millis() { } unsigned long micros() { - // TODO implement this properly + // copied from bk_timer_ctrl(), for speeds + uint32_t timeout = 0; + +#if (CFG_SOC_NAME == SOC_BK7231) +#error "Not implemented" +#endif + +#if LT_MICROS_HIGH_RES + REG_WRITE(TIMER0_2_READ_CTL, (BKTIMER0 << 2) | 1); + while (REG_READ(TIMER0_2_READ_CTL) & 1) { + timeout++; + if (timeout > (120 * 1000)) + return 0; + } + return millis() * 1000 + REG_READ(TIMER0_2_READ_VALUE) / (CFG_XTAL_FREQUENCE / 1000 / 1000); +#else +#if 0 + REG_WRITE(TIMER3_5_READ_CTL, (BKTIMER3 << 2) | 1); + while (REG_READ(TIMER3_5_READ_CTL) & 1) { + timeout++; + if (timeout > (120 * 1000)) + return 0; + } + return millis() * 1000 + REG_READ(TIMER3_5_READ_VALUE) / 32; +#endif return millis() * 1000; +#endif } void yield() { diff --git a/arduino/libretuya/core/LibreTuyaConfig.h b/arduino/libretuya/core/LibreTuyaConfig.h index 448d61e..0a5a5ea 100644 --- a/arduino/libretuya/core/LibreTuyaConfig.h +++ b/arduino/libretuya/core/LibreTuyaConfig.h @@ -82,6 +82,10 @@ #define LT_USE_TIME 0 #endif +#ifndef LT_MICROS_HIGH_RES // NOTE: this is also defined in fixups/clock_rtos.c +#define LT_MICROS_HIGH_RES 1 +#endif + // Per-module logging output - applies to all loglevels #ifndef LT_DEBUG_ALL #define LT_DEBUG_ALL 0 diff --git a/builder/frameworks/beken-72xx-sdk.py b/builder/frameworks/beken-72xx-sdk.py index db2d2b3..d058e50 100644 --- a/builder/frameworks/beken-72xx-sdk.py +++ b/builder/frameworks/beken-72xx-sdk.py @@ -160,6 +160,8 @@ env.AddLibrary( srcs=[ "+", "+", + "+", + "+", "+", "+", *srcs_fixups, @@ -266,6 +268,7 @@ env.AddLibrary( "+", "+", "+", + "-", # fixups "+", "+", "+", diff --git a/platform/beken-72xx/fixups/clock_cal.c b/platform/beken-72xx/fixups/clock_cal.c new file mode 100644 index 0000000..f68059d --- /dev/null +++ b/platform/beken-72xx/fixups/clock_cal.c @@ -0,0 +1,127 @@ +#include "include.h" + +#include "bk_timer_pub.h" +#include "drv_model_pub.h" +#include "fake_clock_pub.h" +#include "mcu_ps_pub.h" +#include "power_save_pub.h" +#include "pwm_pub.h" +#include "sys_rtos.h" + +static CAL_TICK_T cal_tick_save; +UINT32 use_cal_net = 0; + +UINT32 fclk_cal_endvalue(UINT32 mode) { + UINT32 value = 1; + + if (PWM_CLK_32K == mode) { + /* 32 kHz clock */ + value = FCLK_DURATION_MS * 32; + } else if (PWM_CLK_26M == mode) { + /* 26 MHz clock */ + value = FCLK_DURATION_MS * 26000; + } + + return value; +} + +#if CFG_USE_TICK_CAL +static UINT32 timer_cal_init(void) { + UINT32 fclk; + + fclk = BK_TICKS_TO_MS(fclk_get_tick()); + + cal_tick_save.fclk_tick = fclk; + cal_tick_save.tmp1 = 0; + return 0; +} + +extern int increase_tick; + +static UINT32 timer_cal_tick(void) { + UINT32 fclk, tmp2; + UINT32 machw = 0; + INT32 lost; + GLOBAL_INT_DECLARATION(); + + GLOBAL_INT_DISABLE(); + + fclk = BK_TICKS_TO_MS(fclk_get_tick()); + cal_tick_save.tmp1 += ONE_CAL_TIME; + + tmp2 = fclk; + + lost = (INT32)(cal_tick_save.tmp1 - (UINT32)tmp2); + + if ((lost >= (2 * FCLK_DURATION_MS))) { + lost -= FCLK_DURATION_MS; + fclk_update_tick(BK_MS_TO_TICKS(lost)); + increase_tick = 0; + } else { + if (lost <= (-(2 * FCLK_DURATION_MS))) { + if (lost < (-50000)) { + os_printf("m reset:%x %x\r\n", lost, machw); + } + increase_tick = lost + FCLK_DURATION_MS; + } + } + + mcu_ps_machw_init(); + GLOBAL_INT_RESTORE(); + return 0; +} + +static void cal_timer_hdl(UINT8 param) { + timer_cal_tick(); +} + +static void cal_timer_set(void) { + timer_param_t param; + UINT32 ret; + UINT32 timer_channel; + + timer_cal_init(); + + param.channel = CAL_TIMER_ID; + param.div = 1; + param.period = ONE_CAL_TIME; + param.t_Int_Handler = cal_timer_hdl; + + ret = sddev_control(TIMER_DEV_NAME, CMD_TIMER_INIT_PARAM, ¶m); + ASSERT(BK_TIMER_SUCCESS == ret); + timer_channel = param.channel; + ret = sddev_control(TIMER_DEV_NAME, CMD_TIMER_UNIT_ENABLE, &timer_channel); + ASSERT(BK_TIMER_SUCCESS == ret); +} + +static void cal_timer_deset(void) { + UINT32 ret; + UINT32 timer_channel; + + timer_channel = CAL_TIMER_ID; + ret = sddev_control(TIMER_DEV_NAME, CMD_TIMER_UNIT_DISABLE, &timer_channel); + ASSERT(BK_TIMER_SUCCESS == ret); + timer_cal_init(); +} + +UINT32 bk_cal_init(UINT32 setting) { + GLOBAL_INT_DECLARATION(); + GLOBAL_INT_DISABLE(); + + if (1 == setting) { + cal_timer_deset(); + use_cal_net = 1; + mcu_ps_machw_init(); + os_printf("decset:%d %d %d %d\r\n", use_cal_net, fclk_get_tick(), fclk_get_second(), xTaskGetTickCount()); + } else { + mcu_ps_machw_cal(); + cal_timer_set(); + use_cal_net = 0; + mcu_ps_machw_reset(); + os_printf("cset:%d %d %d %d\r\n", use_cal_net, fclk_get_tick(), fclk_get_second(), xTaskGetTickCount()); + } + GLOBAL_INT_RESTORE(); + + return 0; +} +#endif diff --git a/platform/beken-72xx/fixups/clock_rtos.c b/platform/beken-72xx/fixups/clock_rtos.c new file mode 100644 index 0000000..2926cb4 --- /dev/null +++ b/platform/beken-72xx/fixups/clock_rtos.c @@ -0,0 +1,125 @@ +#include "include.h" + +#include "bk_timer_pub.h" +#include "drv_model_pub.h" +#include "fake_clock_pub.h" +#include "icu_pub.h" +#include "mcu_ps_pub.h" +#include "power_save_pub.h" +#include "pwm_pub.h" +#include "rtos_pub.h" +#include "sys_rtos.h" +#include "uart_pub.h" + +// from LibreTuyaConfig.h +#ifndef LT_MICROS_HIGH_RES +#define LT_MICROS_HIGH_RES 1 +#endif + +// main FreeRTOS timer ID +static BK_HW_TIMER_INDEX fclk_id = BK_PWM_TIMER_ID0; + +extern UINT32 bk_cal_init(UINT32 setting); +extern void mcu_ps_increase_clr(void); +extern uint32_t preempt_delayed_schedule_get_flag(void); +extern void preempt_delayed_schedule_clear_flag(void); + +// forward definitions +static void fclk_timer_hw_init(BK_HW_TIMER_INDEX timer_id); +static void fclk_hdl(UINT8 param); + +void fclk_init(void) { +#if (CFG_SOC_NAME == SOC_BK7231) + fclk_timer_hw_init(BK_PWM_TIMER_ID0); +#elif LT_MICROS_HIGH_RES + fclk_timer_hw_init(BK_TIMER_ID0); +#else + fclk_timer_hw_init(BK_TIMER_ID3); +#endif + +#if CFG_USE_TICK_CAL + bk_cal_init(0); +#endif +} + +/* timer_id: BK_PWM_TIMER_ID0 or BK_TIMER_ID3 */ +static void fclk_timer_hw_init(BK_HW_TIMER_INDEX timer_id) { +#if (CFG_SOC_NAME == SOC_BK7231) + ASSERT(timer_id >= BK_PWM_TIMER_ID0); +#endif + + fclk_id = timer_id; + if (fclk_id >= BK_PWM_TIMER_ID0) { // pwm timer + pwm_param_t param; + param.channel = (fclk_id - PWM0); + param.cfg.bits.en = PWM_ENABLE; + param.cfg.bits.int_en = PWM_INT_EN; + param.cfg.bits.mode = PWM_TIMER_MODE; + param.cfg.bits.clk = PWM_CLK_26M; + param.p_Int_Handler = fclk_hdl; +#if (CFG_SOC_NAME == SOC_BK7231N) + param.duty_cycle1 = 0; +#else + param.duty_cycle = 0; +#endif + param.end_value = fclk_cal_endvalue((UINT32)param.cfg.bits.clk); + + sddev_control(PWM_DEV_NAME, CMD_PWM_INIT_PARAM, ¶m); + } else { // timer + timer_param_t param; + param.channel = fclk_id; + param.div = 1; +#if LT_MICROS_HIGH_RES + param.period = FCLK_DURATION_MS * 1000; +#else + param.period = FCLK_DURATION_MS; +#endif + param.t_Int_Handler = fclk_hdl; + +#if LT_MICROS_HIGH_RES + UINT32 ret = sddev_control(TIMER_DEV_NAME, CMD_TIMER_INIT_PARAM_US, ¶m); +#else + UINT32 ret = sddev_control(TIMER_DEV_NAME, CMD_TIMER_INIT_PARAM, ¶m); +#endif + ASSERT(BK_TIMER_SUCCESS == ret); + sddev_control(TIMER_DEV_NAME, CMD_TIMER_UNIT_ENABLE, ¶m.channel); + } +} + +static void fclk_hdl(UINT8 param) { +#if CFG_USE_TICK_CAL + if (!mcu_ps_need_pstick()) + return; +#endif + GLOBAL_INT_DECLARATION(); + GLOBAL_INT_DISABLE(); + if (xTaskIncrementTick() != pdFALSE || preempt_delayed_schedule_get_flag()) { + preempt_delayed_schedule_clear_flag(); + /* Select a new task to run. */ + vTaskSwitchContext(); + } + GLOBAL_INT_RESTORE(); +} + +UINT32 fclk_update_tick(UINT32 tick) { + GLOBAL_INT_DECLARATION(); + if (tick == 0) + return 0; + GLOBAL_INT_DISABLE(); + mcu_ps_increase_clr(); + vTaskStepTick(tick); + GLOBAL_INT_RESTORE(); + return 0; +} + +UINT64 fclk_get_tick(void) { + return xTaskGetTickCount(); +} + +UINT32 fclk_get_second(void) { + return xTaskGetTickCount() / FCLK_SECOND; +} + +BK_HW_TIMER_INDEX fclk_get_tick_id(void) { + return fclk_id; +}