生成的代码包

This commit is contained in:
2026-09-08 10:02:27 +08:00
commit 21a6f93b3f
905 changed files with 216720 additions and 0 deletions
+363
View File
@@ -0,0 +1,363 @@
/******************************************************************************
* @file usr_rtc.c
* @brief 板级 RTC 外设实现(BR28 硬件 rtc_dev_ops
* @author cyWu <1917507415@qq.com>
* @date 2026.08.19
* @version V1.1.0
* @history
* - V1.0.0, 2026.08.19, cyWu, 从模组固件移植至 SOC SDK
* - V1.1.0, 2026.08.19, cyWu, 精简公共接口与缓存逻辑
******************************************************************************/
#include "system/includes.h"
#include "app_config.h"
#include "usr_rtc.h"
#include "asm/rtc.h"
#define LOG_TAG_CONST APP
#define LOG_TAG "[USR_RTC]"
#define LOG_ERROR_ENABLE
#define LOG_DEBUG_ENABLE
#define LOG_INFO_ENABLE
#include "debug.h"
/*============================================================================*/
/* 私有宏 / 类型 */
/*============================================================================*/
#define USR_RTC_TZ_MAGIC (0x52544331u) /**< 'RTC1',校验 VM 时区 */
typedef struct {
uint32_t magic;
int32_t tz_s;
} UsrRtcTzVm_t;
typedef struct {
uint8_t inited;
uint8_t tz_valid;
int32_t tz_s;
void *dev;
} UsrRtc_t;
/*============================================================================*/
/* 私有变量 */
/*============================================================================*/
static UsrRtc_t s_rtc;
/*============================================================================*/
/* 私有函数声明 */
/*============================================================================*/
static uint8_t usr_rtc_is_leap(uint16_t year);
static uint8_t usr_rtc_days_in_month(uint16_t year, uint8_t month);
static uint8_t usr_rtc_year_ok(uint16_t year);
static void usr_rtc_unix_to_calendar(uint32_t unix_utc, int32_t tz_s,
struct sys_time *t);
static UsrRtc_Ret_t usr_rtc_write(const struct sys_time *t);
static void usr_rtc_load_tz(void);
static void usr_rtc_save_tz(int32_t tz_s);
/*============================================================================*/
/* 公有函数 */
/*============================================================================*/
/**
* @brief 打开 rtc 设备并加载时区
* @return UsrRtc_Ret_t
*/
UsrRtc_Ret_t usr_rtc_init(void)
{
struct sys_time t;
if (s_rtc.inited)
{
return USR_RTC_OK;
}
#if TCFG_APP_RTC_EN
s_rtc.dev = dev_open("rtc", NULL);
if (!s_rtc.dev)
{
log_error("open rtc fail");
return USR_RTC_ERR_NOT_INIT;
}
#else
log_error("TCFG_APP_RTC_EN=0");
return USR_RTC_ERR_NOT_INIT;
#endif
usr_rtc_load_tz();
s_rtc.inited = 1;
memset(&t, 0, sizeof(t));
read_sys_time(&t);
log_info("rtc open %u-%02u-%02u %02u:%02u:%02u tz=%ld tz_ok=%u",
t.year, t.month, t.day, t.hour, t.min, t.sec,
(long)s_rtc.tz_s, s_rtc.tz_valid);
return USR_RTC_OK;
}
/**
* @brief 获取当前本地时间
* @param t 成功时赋值;失败不改动
* @return 1/0
*/
uint8_t usr_rtc_get_time(struct sys_time *t)
{
struct sys_time tmp;
if (!t || !s_rtc.inited || !s_rtc.tz_valid)
{
return 0;
}
memset(&tmp, 0, sizeof(tmp));
read_sys_time(&tmp);
if (!usr_rtc_year_ok(tmp.year))
{
return 0;
}
*t = tmp;
return 1;
}
/**
* @brief UTC 秒 + 时区 → 本地日历写入 RTC
* @param unix_utc UTC 秒
* @param tz_s 时区偏移秒
* @return UsrRtc_Ret_t
*/
UsrRtc_Ret_t usr_rtc_set_from_unix(uint64_t unix_utc, int32_t tz_s)
{
struct sys_time t;
UsrRtc_Ret_t ret;
if (!s_rtc.inited)
{
return USR_RTC_ERR_NOT_INIT;
}
if (unix_utc == 0)
{
log_debug("unix=0, ignore");
return USR_RTC_ERR_PARAM;
}
/* 网关采样到写入大约慢 1s,在 UTC 上补偿 */
unix_utc += USR_RTC_SYNC_COMPENSATE_S;
if ((tz_s > USR_RTC_TZ_ABS_MAX_S) || (tz_s < -USR_RTC_TZ_ABS_MAX_S))
{
log_error("tz out of range %ld", (long)tz_s);
return USR_RTC_ERR_PARAM;
}
if (unix_utc > 0xFFFFFFFFull)
{
log_error("unix too large");
return USR_RTC_ERR_PARAM;
}
usr_rtc_unix_to_calendar((uint32_t)unix_utc, tz_s, &t);
if (!usr_rtc_year_ok(t.year))
{
log_error("year %u not in %u~%u, wait sync",
t.year, USR_RTC_YEAR_MIN, USR_RTC_YEAR_MAX);
return USR_RTC_ERR_INVALID;
}
ret = usr_rtc_write(&t);
if (ret != USR_RTC_OK)
{
return ret;
}
usr_rtc_save_tz(tz_s);
log_info("set rtc %u-%02u-%02u %02u:%02u:%02u tz=%ld",
t.year, t.month, t.day, t.hour, t.min, t.sec, (long)tz_s);
return USR_RTC_OK;
}
/*============================================================================*/
/* 私有函数 */
/*============================================================================*/
/**
* @brief 写硬件日历
* @param t 本地日历
* @return UsrRtc_Ret_t
*/
static UsrRtc_Ret_t usr_rtc_write(const struct sys_time *t)
{
struct sys_time tmp;
if (!t)
{
return USR_RTC_ERR_PARAM;
}
if (!s_rtc.inited)
{
return USR_RTC_ERR_NOT_INIT;
}
if (!usr_rtc_year_ok(t->year) || (t->month < 1) || (t->month > 12) ||
(t->day < 1) || (t->hour > 23) || (t->min > 59) || (t->sec > 59))
{
return USR_RTC_ERR_PARAM;
}
if (t->day > usr_rtc_days_in_month(t->year, t->month))
{
return USR_RTC_ERR_PARAM;
}
tmp = *t;
write_sys_time(&tmp);
return USR_RTC_OK;
}
/**
* @brief 是否闰年
* @param year 公历年
* @return 1/0
*/
static uint8_t usr_rtc_is_leap(uint16_t year)
{
if ((year % 400u) == 0)
{
return 1;
}
if ((year % 100u) == 0)
{
return 0;
}
return ((year % 4u) == 0) ? 1 : 0;
}
/**
* @brief 某月天数
* @param year 年
* @param month 月 1~12
* @return 天数,非法月返回 0
*/
static uint8_t usr_rtc_days_in_month(uint16_t year, uint8_t month)
{
static const uint8_t days[12] = {
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
if ((month < 1) || (month > 12))
{
return 0;
}
if ((month == 2) && usr_rtc_is_leap(year))
{
return 29;
}
return days[month - 1];
}
/**
* @brief 年份是否在合法窗口
* @param year 年
* @return 1/0
*/
static uint8_t usr_rtc_year_ok(uint16_t year)
{
return ((year >= USR_RTC_YEAR_MIN) && (year <= USR_RTC_YEAR_MAX)) ? 1 : 0;
}
/**
* @brief UTC 秒 + 时区 → 本地日历
* @param unix_utc UTC 秒
* @param tz_s 时区偏移
* @param t 输出
*/
static void usr_rtc_unix_to_calendar(uint32_t unix_utc, int32_t tz_s,
struct sys_time *t)
{
int64_t local;
uint32_t days;
uint32_t tod;
uint16_t y;
uint8_t m;
uint8_t dim;
memset(t, 0, sizeof(*t));
local = (int64_t)unix_utc + (int64_t)tz_s;
if (local < 0)
{
local = 0;
}
tod = (uint32_t)(local % 86400);
days = (uint32_t)(local / 86400);
t->sec = (uint8_t)(tod % 60u);
t->min = (uint8_t)((tod / 60u) % 60u);
t->hour = (uint8_t)(tod / 3600u);
y = 1970;
while (1)
{
uint32_t diy = usr_rtc_is_leap(y) ? 366u : 365u;
if (days < diy)
{
break;
}
days -= diy;
y++;
if (y > 4095u)
{
break;
}
}
t->year = y;
for (m = 1; m <= 12u; m++)
{
dim = usr_rtc_days_in_month(y, m);
if (days < dim)
{
break;
}
days -= dim;
}
t->month = m;
t->day = (uint8_t)(days + 1u);
}
/**
* @brief 从 VM 加载时区
*/
static void usr_rtc_load_tz(void)
{
UsrRtcTzVm_t vm;
int ret;
s_rtc.tz_valid = 0;
s_rtc.tz_s = 0;
memset(&vm, 0, sizeof(vm));
ret = syscfg_read(CFG_USER_TIM_FLAG, (u8 *)&vm, sizeof(vm));
if ((ret == (int)sizeof(vm)) && (vm.magic == USR_RTC_TZ_MAGIC))
{
if ((vm.tz_s <= USR_RTC_TZ_ABS_MAX_S) && (vm.tz_s >= -USR_RTC_TZ_ABS_MAX_S))
{
s_rtc.tz_s = vm.tz_s;
s_rtc.tz_valid = 1;
log_info("tz from vm %ld", (long)s_rtc.tz_s);
return;
}
}
log_debug("tz vm empty");
}
/**
* @brief 时区写入 VM
* @param tz_s 时区偏移秒
*/
static void usr_rtc_save_tz(int32_t tz_s)
{
UsrRtcTzVm_t vm;
s_rtc.tz_s = tz_s;
s_rtc.tz_valid = 1;
vm.magic = USR_RTC_TZ_MAGIC;
vm.tz_s = tz_s;
syscfg_write(CFG_USER_TIM_FLAG, (u8 *)&vm, sizeof(vm));
}