提交 fff5439a 编写于 作者: 福明 提交者: yilu.myl

IssueID:1909:New RTC device driver framework

[Detail]
New RTC device driver framework.

[Verified Cases]
Build Pass: helloworld_demo@haaseduk1
Test Pass: helloworld_demo@haaseduk1
上级 fa1cf94c
/*
* Copyright (C) 2021-2022 Alibaba Group Holding Limited
*/
#ifndef AOS_RTC_H
#define AOS_RTC_H
#ifdef AOS_KERNEL_BUILD
#include <aos/device.h>
#else
#include <stdint.h>
#endif
/**
* @defgroup rtc_api RTC
* @ingroup driver_api
* @brief AOS API for RTC.
* @{
*/
typedef struct {
uint64_t year : 22;
uint64_t month : 4; /* 1 ~ 12 */
uint64_t mday : 5;
uint64_t hour : 5;
uint64_t min : 6;
uint64_t sec : 6;
uint64_t reserved : 16; /* Reserved for millisecond, leap second flag, etc. */
} aos_rtc_time_t;
#if (defined(AOS_KERNEL_BUILD) && defined(AOS_COMP_DEVFS)) || !defined(AOS_KERNEL_BUILD)
#define AOS_RTC_IOC_GET_TIME 0x5201
#define AOS_RTC_IOC_SET_TIME 0x5202
#endif /* (defined(AOS_KERNEL_BUILD) && defined(AOS_COMP_DEVFS)) || !defined(AOS_KERNEL_BUILD) */
#ifdef AOS_KERNEL_BUILD
typedef aos_dev_ref_t aos_rtc_ref_t;
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Get an RTC device.
* @param ref RTC ref to operate.
* @param id RTC device ID.
* @return 0: on success; < 0: on failure.
*/
aos_status_t aos_rtc_get(aos_rtc_ref_t *ref, uint32_t id);
/**
* @brief Release an RTC device.
* @param ref RTC ref to operate.
* @return None.
*/
void aos_rtc_put(aos_rtc_ref_t *ref);
/**
* @brief Read time from an RTC device.
* @param ref RTC ref to operate.
* @param time Time buffer.
* @return 0: on success; < 0: on failure.
*/
aos_status_t aos_rtc_get_time(aos_rtc_ref_t *ref, aos_rtc_time_t *time);
/**
* @brief Write time to an RTC device.
* @param ref RTC ref to operate.
* @param time Time buffer.
* @return 0: on success; < 0: on failure.
*/
aos_status_t aos_rtc_set_time(aos_rtc_ref_t *ref, const aos_rtc_time_t *time);
#ifdef __cplusplus
}
#endif
#endif /* AOS_KERNEL_BUILD */
/** @} */
#endif /* AOS_RTC_H */
/*
* Copyright (C) 2021-2022 Alibaba Group Holding Limited
*/
#ifndef AOS_RTC_CORE_H
#define AOS_RTC_CORE_H
#include <aos/device_core.h>
#include <aos/rtc.h>
struct aos_rtc_ops;
typedef struct {
aos_dev_t dev;
/* must be initialized before registration */
const struct aos_rtc_ops *ops;
} aos_rtc_t;
typedef struct aos_rtc_ops {
void (*unregister)(aos_rtc_t *);
aos_status_t (*startup)(aos_rtc_t *);
void (*shutdown)(aos_rtc_t *);
aos_status_t (*get_time)(aos_rtc_t *, aos_rtc_time_t *);
aos_status_t (*set_time)(aos_rtc_t *, const aos_rtc_time_t *);
} aos_rtc_ops_t;
#ifdef __cplusplus
extern "C" {
#endif
aos_status_t aos_rtc_register(aos_rtc_t *rtc);
aos_status_t aos_rtc_register_argumented(aos_rtc_t *rtc, uint32_t id, const aos_rtc_ops_t *ops);
aos_status_t aos_rtc_unregister(uint32_t id);
#ifdef __cplusplus
}
#endif
#endif /* AOS_RTC_CORE_H */
## 第一部分:基础信息
name: rtc # <必选项> 包名称 (符合C语言变量命名规则),长度少于等于64字节
version: master # <必选项> 组件版本号
description: RTC通用驱动 # <必选项> 建议至少20字以上
type: common # <必选项> 组件类型,为:solution, chip, board, common, sdk
tag: 第三方驱动 # <可选项> 组件分类,缺省值: ''
keywords: # <可选项> 标签,会影响到组件被搜索的效果,合理的标签很重要
- rtc driver
license: Apache license v2.0 # <可选项> 源代码的许可证,要确保所有代码、文件的许可证不冲突。如:MIT,Apache license v2.0,BSD
## 第二部分:依赖信息
# 指定该组件依赖的组件及版本,版本支持条件比较,支持:>=v1.0, >v1.0, ==v1.0, <=v1.0, <v1.0, v1.0
# 未指定条件时,默认为 ==,如 v1.0 与 ==v1.0
# depends: # <可选项> 该组件依赖其他的组件,合理的依赖才能保证组件能编译、使用
# - minilibc: v7.2.0
# - aos: >=v7.2.0
depends:
- base: master
## 第四部分:编译连接信息
# build_config: # <可选项> 编译配置项
# include: # <可选项> 编译时,影响编译器的-I 参数 ,全局有效
# - src # include 只能是该软件包下的目录,不能使用外部目录
# internal_include: # <可选项> 编译时,影响编译器的-I 参数 ,组件内有效
# - include
# cflag: '' # <可选项> C 编译器所需要要的编译参数
# cxxflag: '' # <可选项> CXX 编译器所需要要的编译参数
# asmflag: '' # <可选项> 汇编器所需要要参数
# define: # <可选项> 宏定义, 增加编译器的-D 选项,如:
# XXX: 1 # -DXXX=1
# AAA: 1 # -DAAA
# STR: "abc" # -DSTR="abc"
# libs: # 该组件中支持的二进制静态库,如:libxxx.a, libyyy.a
# - xxx # -lxxx
# - yyy # -lyyy
# libpath: # 指定静态库所在的路径(相对于该组件路径)
# - libs # -Llibs
build_config:
include:
- include
define:
# source_file: # <可选项> 指定参与编译的源代码文件,支持通配符,采用相对路径
# - src/*.c # 例:组件 src 目录下所有的扩展名为 c 的源代码文件
source_file:
- src/rtc.c
## 第五部分:配置信息
# def_config: # 组件的可配置项
# CONFIG_DEBUG: y
# CONFIG_PARAM_NOT_CHECK: y
# CONFIG_CLI: y
def_config:
AOS_COMP_RTC: 1
## 第六部分:安装信息
# install:
# - dest: include/ # 安装的目的路径 dest是相当路径,通常是相对于YoC SDK 安装目录
# source: # 安装源列表
# - src/*.h # 支持通配符,相对路径
install:
- dest: "include/aos"
source:
- "include/aos/rtc.h"
## 第七部分:导出部分
# export:
# - dest: "<SOLUTION_PATH>/generated/data" # 安装的目的路径 dest是相当路径
# source: # 安装源列表
# - "bootimgs/boot"
# - "bootimgs/tee"
# - "bootimgs/mtb"
# - "configs/config.yaml"
/*
* Copyright (C) 2021-2022 Alibaba Group Holding Limited
*/
#include <aos/rtc_core.h>
#ifdef AOS_COMP_DEVFS
#include <stdio.h>
#include <inttypes.h>
#endif
aos_status_t aos_rtc_get(aos_rtc_ref_t *ref, uint32_t id)
{
return aos_dev_get(ref, AOS_DEV_TYPE_RTC, id);
}
void aos_rtc_put(aos_rtc_ref_t *ref)
{
aos_dev_put(ref);
}
static bool is_valid_time(const aos_rtc_time_t *time)
{
int mdays;
if (time->year < 1)
return false;
switch (time->month) {
case 1:
mdays = 31;
break;
case 2:
mdays = 28;
if (time->year % 100 == 0) {
if (time->year % 400 == 0)
mdays++;
} else {
if (time->year % 4 == 0)
mdays++;
}
break;
case 3:
mdays = 32;
break;
case 4:
mdays = 30;
break;
case 5:
mdays = 31;
break;
case 6:
mdays = 30;
break;
case 7:
mdays = 31;
break;
case 8:
mdays = 31;
break;
case 9:
mdays = 30;
break;
case 10:
mdays = 31;
break;
case 11:
mdays = 30;
break;
case 12:
mdays = 31;
break;
default:
return false;
}
if (time->mday < 1 || time->mday > mdays)
return false;
if (time->hour >= 24 || time->min >= 60 || time->sec >= 60)
return false;
return true;
}
aos_status_t aos_rtc_get_time(aos_rtc_ref_t *ref, aos_rtc_time_t *time)
{
aos_rtc_t *rtc;
aos_status_t ret;
if (!ref || !aos_dev_ref_is_valid(ref) || !time)
return -EINVAL;
rtc = aos_container_of(ref->dev, aos_rtc_t, dev);
aos_dev_lock(ref->dev);
ret = rtc->ops->get_time(rtc, time);
aos_dev_unlock(ref->dev);
if (ret)
return ret;
return is_valid_time(time) ? 0 : -EBADMSG;
}
aos_status_t aos_rtc_set_time(aos_rtc_ref_t *ref, const aos_rtc_time_t *time)
{
aos_rtc_t *rtc;
aos_status_t ret;
if (!ref || !aos_dev_ref_is_valid(ref) || !time || !is_valid_time(time))
return -EINVAL;
rtc = aos_container_of(ref->dev, aos_rtc_t, dev);
aos_dev_lock(ref->dev);
ret = rtc->ops->set_time(rtc, time);
aos_dev_unlock(ref->dev);
return ret;
}
static void dev_rtc_unregister(aos_dev_t *dev)
{
aos_rtc_t *rtc = aos_container_of(dev, aos_rtc_t, dev);
if (rtc->ops->unregister)
rtc->ops->unregister(rtc);
}
static aos_status_t dev_rtc_get(aos_dev_ref_t *ref)
{
aos_rtc_t *rtc = aos_container_of(ref->dev, aos_rtc_t, dev);
if (!aos_dev_ref_is_first(ref))
return 0;
return rtc->ops->startup(rtc);
}
static void dev_rtc_put(aos_dev_ref_t *ref)
{
aos_rtc_t *rtc = aos_container_of(ref->dev, aos_rtc_t, dev);
if (!aos_dev_ref_is_last(ref))
return;
rtc->ops->shutdown(rtc);
}
static const aos_dev_ops_t dev_rtc_ops = {
.unregister = dev_rtc_unregister,
.get = dev_rtc_get,
.put = dev_rtc_put,
};
#ifdef AOS_COMP_DEVFS
static aos_status_t devfs_rtc_ioctl(aos_devfs_file_t *file, int cmd, uintptr_t arg)
{
aos_rtc_ref_t *ref = aos_devfs_file2ref(file);
aos_status_t ret;
switch (cmd) {
case AOS_RTC_IOC_GET_TIME:
{
aos_rtc_time_t time;
if (!aos_devfs_file_is_readable(file)) {
ret = -EPERM;
break;
}
ret = aos_rtc_get_time(ref, &time);
if (ret)
break;
if (!aos_umem_check((const void *)arg, sizeof(time))) {
ret = -EFAULT;
break;
}
ret = aos_umem_copy((void *)arg, &time, sizeof(time)) ? -EFAULT : 0;
}
break;
case AOS_RTC_IOC_SET_TIME:
{
aos_rtc_time_t time;
if (!aos_devfs_file_is_writable(file)) {
ret = -EPERM;
break;
}
if (!aos_umem_check((const void *)arg, sizeof(time))) {
ret = -EFAULT;
break;
}
if (aos_umem_copy(&time, (const void *)arg, sizeof(time))) {
ret = -EFAULT;
break;
}
ret = aos_rtc_set_time(ref, &time);
}
break;
default:
ret = -EINVAL;
break;
}
return ret;
}
static const aos_devfs_file_ops_t devfs_rtc_ops = {
.ioctl = devfs_rtc_ioctl,
.poll = NULL,
.mmap = NULL,
.read = NULL,
.write = NULL,
.lseek = NULL,
};
#endif /* AOS_COMP_DEVFS */
aos_status_t aos_rtc_register(aos_rtc_t *rtc)
{
#ifdef AOS_COMP_DEVFS
int name_len;
#endif
if (!rtc)
return -EINVAL;
if (!rtc->ops || !rtc->ops->startup || !rtc->ops->shutdown || !rtc->ops->get_time || !rtc->ops->set_time)
return -EINVAL;
rtc->dev.type = AOS_DEV_TYPE_RTC;
rtc->dev.ops = &dev_rtc_ops;
#ifdef AOS_COMP_DEVFS
aos_devfs_node_init(&rtc->dev.devfs_node);
rtc->dev.devfs_node.ops = &devfs_rtc_ops;
name_len = snprintf(rtc->dev.devfs_node.name, sizeof(rtc->dev.devfs_node.name), "rtc%" PRIu32, rtc->dev.id);
if (name_len < 0 || name_len >= sizeof(rtc->dev.devfs_node.name))
return -EINVAL;
#endif
return aos_dev_register(&rtc->dev);
}
aos_status_t aos_rtc_register_argumented(aos_rtc_t *rtc, uint32_t id, const aos_rtc_ops_t *ops)
{
if (!rtc)
return -EINVAL;
rtc->dev.id = id;
rtc->ops = ops;
return aos_rtc_register(rtc);
}
aos_status_t aos_rtc_unregister(uint32_t id)
{
return aos_dev_unregister(AOS_DEV_TYPE_RTC, id);
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册