[beken-72xx] Implement micros() properly; use high-res timer for OS

This commit is contained in:
Kuba Szczodrzyński
2022-09-14 19:56:51 +02:00
parent 830d8762cd
commit 05b2fb4fcb
5 changed files with 288 additions and 1 deletions

View File

@@ -1,6 +1,9 @@
/* Copyright (c) Kuba Szczodrzyński 2022-06-19. */
#include <Arduino.h>
#include <arm_arch.h>
#include <bk_timer.h>
#include <bk_timer_pub.h>
#include <rtos_pub.h>
#include <sys_rtos.h>
@@ -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() {

View File

@@ -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

View File

@@ -160,6 +160,8 @@ env.AddLibrary(
srcs=[
"+<arch_main.c>",
"+<ate_app.c>",
"+<clock_cal.c>",
"+<clock_rtos.c>",
"+<intc.c>",
"+<wrap_BkDriverFlash.c>",
*srcs_fixups,
@@ -266,6 +268,7 @@ env.AddLibrary(
"+<joint_up/*.c>",
"+<lwip_intf/dhcpd/*.c>",
"+<misc/*.c>",
"-<misc/fake_clock.c>", # fixups
"+<net_param_intf/*.c>",
"+<power_save/*.c>",
"+<rwnx_intf/*.c>",

View File

@@ -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, &param);
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

View File

@@ -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, &param);
} 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, &param);
#else
UINT32 ret = sddev_control(TIMER_DEV_NAME, CMD_TIMER_INIT_PARAM, &param);
#endif
ASSERT(BK_TIMER_SUCCESS == ret);
sddev_control(TIMER_DEV_NAME, CMD_TIMER_UNIT_ENABLE, &param.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;
}