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

IssueID:1919:improve PWM and ADC driver framework

[Detail]
Improve PWM driver framework.
Improve ADC driver framework.
New VFS support.
Userspace support.

[Verified Cases]
Build Pass: helloworld_demo@haaseduk1
Test Pass: helloworld_demo@haaseduk1
上级 21139e91
......@@ -16,10 +16,10 @@ typedef enum {
AOS_DEV_TYPE_WATCHDOG,
AOS_DEV_TYPE_ETHERNET,
AOS_DEV_TYPE_WLAN,
AOS_DEV_TYPE_BLOCK,
AOS_DEV_TYPE_DISK,
AOS_DEV_TYPE_DISKPART,
AOS_DEV_TYPE_FLASH,
AOS_DEV_TYPE_FLASHPART,
AOS_DEV_TYPE_MTD,
AOS_DEV_TYPE_RTC,
AOS_DEV_TYPE_SPI,
AOS_DEV_TYPE_I2C,
......
......@@ -8,29 +8,22 @@
#include <aos/kernel.h>
#include <aos/list.h>
#include <k_rbtree.h>
#include <aos/device.h>
#ifdef AOS_COMP_DEVFS
#include <aos/devfs.h>
#endif
#if defined(CONFIG_DRV_CORE) && CONFIG_DRV_CORE != 0
#include <drivers/u_ld.h>
#ifdef AOS_COMP_VFS
#include <aos/vfs.h>
#endif
#include <aos/device.h>
struct aos_dev_ops;
#ifdef AOS_COMP_VFS
#define AOS_DEV_NAME_MAX_LEN 63
typedef struct {
char name[AOS_DEV_NAME_MAX_LEN + 1];
const struct file_ops *ops;
} aos_dev_vfs_helper_t;
#endif
typedef struct aos_dev {
aos_dev_type_t type;
uint32_t id;
const struct aos_dev_ops *ops;
#ifdef AOS_COMP_VFS
aos_dev_vfs_helper_t vfs_helper;
#ifdef AOS_COMP_DEVFS
aos_devfs_node_t devfs_node;
#endif
struct k_rbtree_node_t rb_node;
aos_sem_t rb_sem;
......@@ -53,6 +46,9 @@ typedef struct aos_dev_ops {
extern "C" {
#endif
#if !(defined(CONFIG_DRV_CORE) && CONFIG_DRV_CORE != 0)
aos_status_t aos_dev_core_init(void);
#endif
aos_status_t aos_dev_register(aos_dev_t *dev);
aos_status_t aos_dev_unregister(aos_dev_type_t type, uint32_t id);
aos_status_t aos_dev_ref(aos_dev_ref_t *ref, aos_dev_t *dev);
......
......@@ -2,7 +2,6 @@
* Copyright (C) 2020-2021 Alibaba Group Holding Limited
*/
#include <string.h>
#include <aos/device_core.h>
#define REF_COUNT_PENDING UINT32_MAX
......@@ -11,6 +10,24 @@
static struct k_rbtree_root_t device_map = RBT_ROOT;
static aos_mutex_t device_map_mutex;
static aos_status_t device_core_init(void)
{
return aos_mutex_new(&device_map_mutex);
}
#if defined(CONFIG_DRV_CORE) && CONFIG_DRV_CORE != 0
static int dev_core_init(void)
{
return (int)device_core_init();
}
CORE_DRIVER_ENTRY(dev_core_init)
#else
aos_status_t aos_dev_core_init(void)
{
return device_core_init();
}
#endif
static void device_map_lock(void)
{
(void)aos_mutex_lock(&device_map_mutex, AOS_WAIT_FOREVER);
......@@ -96,37 +113,6 @@ static void remove_device(aos_dev_t *dev)
k_rbtree_erase(&dev->rb_node, &device_map);
}
#ifdef AOS_COMP_VFS
static aos_status_t add_to_vfs(aos_dev_t *dev)
{
const char prefix[] = "/dev/";
char path[sizeof(prefix) - 1 + sizeof(dev->vfs_helper.name)];
if (dev->vfs_helper.name[0] == '\0' || !dev->vfs_helper.ops)
return 0;
memcpy(path, prefix, sizeof(prefix) - 1);
strncpy(&path[sizeof(prefix) - 1], dev->vfs_helper.name, sizeof(dev->vfs_helper.name) - 1);
path[sizeof(path) - 1] = '\0';
return aos_register_driver(path, dev->vfs_helper.ops, dev);
}
static void remove_from_vfs(aos_dev_t *dev)
{
const char prefix[] = "/dev/";
char path[sizeof(prefix) - 1 + sizeof(dev->vfs_helper.name)];
if (dev->vfs_helper.name[0] == '\0' || !dev->vfs_helper.ops)
return;
memcpy(path, prefix, sizeof(prefix) - 1);
strncpy(&path[sizeof(prefix) - 1], dev->vfs_helper.name, sizeof(dev->vfs_helper.name) - 1);
path[sizeof(path) - 1] = '\0';
(void)aos_unregister_driver(path);
}
#endif /* AOS_COMP_VFS */
aos_status_t aos_dev_register(aos_dev_t *dev)
{
aos_status_t ret;
......@@ -157,15 +143,17 @@ aos_status_t aos_dev_register(aos_dev_t *dev)
insert_device(dev);
device_map_unlock();
#ifdef AOS_COMP_VFS
ret = add_to_vfs(dev);
if (ret) {
device_map_lock();
remove_device(dev);
device_map_unlock();
aos_mutex_free(&dev->mutex);
aos_sem_free(&dev->rb_sem);
return ret;
#ifdef AOS_COMP_DEVFS
if (aos_devfs_node_is_valid(&dev->devfs_node)) {
ret = aos_devfs_add_node(&dev->devfs_node);
if (ret) {
device_map_lock();
remove_device(dev);
device_map_unlock();
aos_mutex_free(&dev->mutex);
aos_sem_free(&dev->rb_sem);
return ret;
}
}
#endif
......@@ -179,7 +167,6 @@ aos_status_t aos_dev_register(aos_dev_t *dev)
aos_status_t aos_dev_unregister(aos_dev_type_t type, uint32_t id)
{
aos_dev_t *dev;
aos_status_t ret;
device_map_lock();
dev = find_device(type, id);
......@@ -206,8 +193,9 @@ aos_status_t aos_dev_unregister(aos_dev_type_t type, uint32_t id)
aos_dev_unlock(dev);
device_allow_removal(dev);
#ifdef AOS_COMP_VFS
remove_from_vfs(dev);
#ifdef AOS_COMP_DEVFS
if (aos_devfs_node_is_valid(&dev->devfs_node))
(void)aos_devfs_remove_node(&dev->devfs_node);
#endif
device_map_lock();
device_wait_removal(dev);
......@@ -302,10 +290,3 @@ void aos_dev_put(aos_dev_ref_t *ref)
aos_dev_unlock(ref->dev);
aos_dev_ref_init(ref);
}
static int device_core_init(void)
{
return (int)aos_mutex_new(&device_map_mutex);
}
CORE_DRIVER_ENTRY(device_core_init)
......@@ -2,39 +2,61 @@
* Copyright (C) 2021 Alibaba Group Holding Limited
*/
#ifndef _AOS_ADC_H
#define _AOS_ADC_H
#ifndef AOS_ADC_H
#define AOS_ADC_H
#include <stdint.h>
#include <aos/kernel.h>
#ifdef AOS_KERNEL_BUILD
#include <aos/device.h>
#ifdef __cplusplus
extern "C" {
#else
#include <stdint.h>
#endif
/** @defgroup driver_api driver
* @ingroup aos_components
* @{
*/
/** @} */
/**
* @defgroup aos_adc_app ADC
* @defgroup adc_api ADC
* @ingroup driver_api
* 给应用提供ADC操作的AOS API.
*
* @brief AOS API for ADC.
* @{
*/
typedef aos_dev_ref_t aos_adc_ref_t; /**< ADC设备的引用 */
typedef enum {
AOS_ADC_MODE_SINGLE, /**< 单次采样模式 */
AOS_ADC_MODE_CONTINUE, /**< 连续采样模式 */
} aos_adc_mode_t;
#if (defined(AOS_KERNEL_BUILD) && defined(AOS_COMP_DEVFS)) || !defined(AOS_KERNEL_BUILD)
typedef struct {
int32_t channel;
uint32_t time;
} aos_adc_set_sample_time_args_t;
typedef struct {
int32_t channel;
uint32_t range;
} aos_adc_get_range_args_t;
typedef struct {
int32_t channel;
int32_t data;
} aos_adc_read_args_t;
#define AOS_ADC_IOC_SET_SAMPLE_TIME 0x4101
#define AOS_ADC_IOC_SET_MODE 0x4102
#define AOS_ADC_IOC_GET_RESOLUTION 0x4103
#define AOS_ADC_IOC_GET_RANGE 0x4104
#define AOS_ADC_IOC_READ 0x4105
#define AOS_ADC_IOC_READ_VOLTAGE 0x4106
#endif /* (defined(AOS_KERNEL_BUILD) && defined(AOS_COMP_DEVFS)) || !defined(AOS_KERNEL_BUILD) */
#ifdef AOS_KERNEL_BUILD
typedef aos_dev_ref_t aos_adc_ref_t; /**< ADC设备的引用 */
#ifdef __cplusplus
extern "C" {
#endif
/**
* 获取一个ADC设备的引用
*
......@@ -120,9 +142,12 @@ aos_status_t aos_adc_read(aos_adc_ref_t *ref, int32_t channel, int32_t *data);
*/
aos_status_t aos_adc_read_voltage(aos_adc_ref_t *ref, int32_t channel, int32_t *data);
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* _AOS_ADC_H */
#endif /* AOS_KERNEL_BUILD */
/** @} */
#endif /* AOS_ADC_H */
......@@ -2,11 +2,9 @@
* Copyright (C) 2021 Alibaba Group Holding Limited
*/
#ifndef _AOS_ADC_CORE_H
#define _AOS_ADC_CORE_H
#ifndef AOS_ADC_CORE_H
#define AOS_ADC_CORE_H
#include <stdint.h>
#include <aos/kernel.h>
#include <aos/device_core.h>
#include <aos/adc.h>
......@@ -84,4 +82,4 @@ aos_status_t aos_adc_unregister(uint32_t id);
}
#endif
#endif /* _AOS_ADC_CORE_H */
#endif /* AOS_ADC_CORE_H */
## 第一部分: 基础信息
name: adc # <必选项> 包名称 (符合C语言变量命名规则),长度少于等于64字节
version: master # <必选项> 组件版本号
description: ADC 通用驱动 # <必选项> 建议至少20字以上
version: master # <必选项> 组件版本号
description: ADC通用驱动 # <必选项> 建议至少20字以上
type: common # <必选项> 组件类型,为:solution, chip, board, common, sdk
tag: 第三方驱动 # <可选项> 组件分类,缺省值: ''
keywords: # <可选项> 标签,会影响到组件被搜索的效果,合理的标签很重要
- adc core and vfs driver
- adc driver
license: Apache license v2.0 # <可选项> 源代码的许可证,要确保所有代码、文件的许可证不冲突。如:MIT,Apache license v2.0,BSD
## 第二部分:依赖信息
......@@ -18,7 +17,7 @@ license: Apache license v2.0 # <可选项> 源代码的
# - aos: >=v7.2.0
depends:
- base: master
- vfs: master
- csi: master ? <AOS_CONFIG_ADC_CSI>
## 第四部分:编译连接信息
# build_config: # <可选项> 编译配置项
......@@ -47,11 +46,8 @@ build_config:
# source_file: # <可选项> 指定参与编译的源代码文件,支持通配符,采用相对路径
# - src/*.c # 例:组件 src 目录下所有的扩展名为 c 的源代码文件
source_file:
# ADC
- src/adc_dev.c ? <CONFIG_U_ADC_DEV>
- src/adc.c ? <CONFIG_U_ADC_CORE>
- src/adc_csi.c ? <CONFIG_U_ADC_CORE>
- src/adc.c
- src/adc_csi.c ? <AOS_CONFIG_ADC_CSI>
## 第五部分:配置信息
# def_config: # 组件的可配置项
......@@ -59,8 +55,7 @@ source_file:
# CONFIG_PARAM_NOT_CHECK: y
# CONFIG_CLI: y
def_config:
CONFIG_U_ADC_DEV: 1 # ADC device node named witch "/dev/adc[x]"
CONFIG_U_ADC_CORE: 0 # ADC subsys AOS API driver
AOS_COMP_ADC: 1
## 第六部分:安装信息
# install:
......@@ -68,8 +63,9 @@ def_config:
# source: # 安装源列表
# - src/*.h # 支持通配符,相对路径
install:
- dest: "include/devices"
- dest: "include/aos"
source:
- "include/aos/adc.h"
## 第七部分:导出部分
# export:
......
......@@ -2,13 +2,11 @@
* Copyright (C) 2021 Alibaba Group Holding Limited
*/
#include <stdint.h>
#include <errno.h>
#include <stdbool.h>
#include <aos/kernel.h>
#include <aos/list.h>
#include <aos/adc.h>
#include <aos/adc_core.h>
#ifdef AOS_COMP_DEVFS
#include <stdio.h>
#include <inttypes.h>
#endif
#define AOS_ADC_CHECK_NULL(x) \
do { \
......@@ -166,10 +164,155 @@ static const aos_dev_ops_t dev_adc_ops = {
.put = dev_adc_put,
};
aos_status_t aos_adc_register(aos_adc_t *adc)
#ifdef AOS_COMP_DEVFS
static aos_status_t devfs_adc_ioctl(aos_devfs_file_t *file, int cmd, uintptr_t arg)
{
aos_adc_ref_t *ref = aos_devfs_file2ref(file);
aos_status_t ret;
switch (cmd) {
case AOS_ADC_IOC_SET_SAMPLE_TIME:
{
aos_adc_set_sample_time_args_t args;
if (!aos_devfs_file_is_writable(file)) {
ret = -EPERM;
break;
}
if (!aos_umem_check((const void *)arg, sizeof(args))) {
ret = -EFAULT;
break;
}
if (aos_umem_copy(&args, (const void *)arg, sizeof(args))) {
ret = -EFAULT;
break;
}
ret = aos_adc_set_sample_time(ref, args.channel, args.time);
}
break;
case AOS_ADC_IOC_SET_MODE:
{
aos_adc_mode_t mode;
if (!aos_devfs_file_is_writable(file)) {
ret = -EPERM;
break;
}
if (!aos_umem_check((const void *)arg, sizeof(mode))) {
ret = -EFAULT;
break;
}
if (aos_umem_copy(&mode, (const void *)arg, sizeof(mode))) {
ret = -EFAULT;
break;
}
ret = aos_adc_set_mode(ref, mode);
}
break;
case AOS_ADC_IOC_GET_RESOLUTION:
{
uint32_t resolution;
if (!aos_devfs_file_is_readable(file)) {
ret = -EPERM;
break;
}
ret = aos_adc_get_resolution(ref, &resolution);
if (ret)
break;
if (!aos_umem_check((const void *)arg, sizeof(resolution))) {
ret = -EFAULT;
break;
}
ret = aos_umem_copy((void *)arg, &resolution, sizeof(resolution)) ? -EFAULT : 0;
}
break;
case AOS_ADC_IOC_GET_RANGE:
{
aos_adc_get_range_args_t args;
if (!aos_devfs_file_is_readable(file)) {
ret = -EPERM;
break;
}
if (!aos_umem_check((const void *)arg, sizeof(args))) {
ret = -EFAULT;
break;
}
if (aos_umem_copy(&args, (const void *)arg, sizeof(args))) {
ret = -EFAULT;
break;
}
ret = aos_adc_get_range(ref, args.channel, &args.range);
if (ret)
break;
ret = aos_umem_copy((void *)arg, &args, sizeof(args)) ? -EFAULT : 0;
}
break;
case AOS_ADC_IOC_READ:
{
aos_adc_read_args_t args;
if (!aos_devfs_file_is_readable(file)) {
ret = -EPERM;
break;
}
if (!aos_umem_check((const void *)arg, sizeof(args))) {
ret = -EFAULT;
break;
}
if (aos_umem_copy(&args, (const void *)arg, sizeof(args))) {
ret = -EFAULT;
break;
}
ret = aos_adc_read(ref, args.channel, &args.data);
if (ret)
break;
ret = aos_umem_copy((void *)arg, &args, sizeof(args)) ? -EFAULT : 0;
}
break;
case AOS_ADC_IOC_READ_VOLTAGE:
{
aos_adc_read_args_t args;
if (!aos_devfs_file_is_readable(file)) {
ret = -EPERM;
break;
}
if (!aos_umem_check((const void *)arg, sizeof(args))) {
ret = -EFAULT;
break;
}
if (aos_umem_copy(&args, (const void *)arg, sizeof(args))) {
ret = -EFAULT;
break;
}
ret = aos_adc_read_voltage(ref, args.channel, &args.data);
if (ret)
break;
ret = aos_umem_copy((void *)arg, &args, sizeof(args)) ? -EFAULT : 0;
}
break;
default:
ret = -EINVAL;
break;
}
return ret;
}
static const aos_devfs_file_ops_t devfs_adc_ops = {
.ioctl = devfs_adc_ioctl,
.poll = NULL,
.mmap = NULL,
.read = NULL,
.write = NULL,
.lseek = NULL,
};
#endif /* AOS_COMP_DEVFS */
aos_status_t aos_adc_register(aos_adc_t *adc)
{
#ifdef AOS_COMP_DEVFS
int name_len;
#endif
AOS_ADC_CHECK_NULL(adc);
/* startup/shutdown/read must be set. */
......@@ -183,10 +326,12 @@ aos_status_t aos_adc_register(aos_adc_t *adc)
adc->dev.type = AOS_DEV_TYPE_ADC;
adc->dev.ops = &dev_adc_ops;
#ifdef AOS_COMP_VFS
/* TODO: support vfs ops. */
adc->dev.vfs_helper.name[0] = '\0';
adc->dev.vfs_helper.ops = NULL;
#ifdef AOS_COMP_DEVFS
aos_devfs_node_init(&adc->dev.devfs_node);
adc->dev.devfs_node.ops = &devfs_adc_ops;
name_len = snprintf(adc->dev.devfs_node.name, sizeof(adc->dev.devfs_node.name), "adc%" PRIu32, adc->dev.id);
if (name_len < 0 || name_len >= sizeof(adc->dev.devfs_node.name))
return -EINVAL;
#endif
return aos_dev_register(&(adc->dev));
......
......@@ -2,25 +2,22 @@
* Copyright (C) 2021 Alibaba Group Holding Limited
*/
#ifndef _AOS_PWM_H
#define _AOS_PWM_H
#ifndef AOS_PWM_H
#define AOS_PWM_H
#include <stdint.h>
#include <aos/kernel.h>
#ifdef AOS_KERNEL_BUILD
#include <aos/device.h>
#else
#include <stdint.h>
#endif
/**
* @defgroup aos_pwm_app PWM
* @defgroup pwm_api PWM
* @ingroup driver_api
* 给应用提供PWM操作的AOS API.
*
* @brief AOS API for PWM.
* @{
*/
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
AOS_PWM_POLARITY_NORMAL,
AOS_PWM_POLARITY_INVERSE,
......@@ -32,16 +29,22 @@ typedef struct {
aos_pwm_polarity_t polarity;
bool enabled;
} aos_pwm_attr_t;
/**
* @defgroup aos_pwm_app PWM应用操作
* @ingroup driver_api
* 给应用提供PWM操作的AOS PWM API.
*
* @{
*/
#if (defined(AOS_KERNEL_BUILD) && defined(AOS_COMP_DEVFS)) || !defined(AOS_KERNEL_BUILD)
#define AOS_PWM_IOC_GET_ATTR 0x5001
#define AOS_PWM_IOC_SET_ATTR 0x5002
#endif /* (defined(AOS_KERNEL_BUILD) && defined(AOS_COMP_DEVFS)) || !defined(AOS_KERNEL_BUILD) */
#ifdef AOS_KERNEL_BUILD
typedef aos_dev_ref_t aos_pwm_ref_t; /**< PWM设备的引用 */
#ifdef __cplusplus
extern "C" {
#endif
/**
* 获取一个PWM设备的引用
*
......@@ -85,6 +88,8 @@ aos_status_t aos_pwm_get_attr(aos_pwm_ref_t *ref, aos_pwm_attr_t *attr);
}
#endif
#endif /* AOS_KERNEL_BUILD */
/** @} */
#endif /* _AOS_PWM_H */
#endif /* AOS_PWM_H */
......@@ -2,11 +2,9 @@
* Copyright (C) 2021 Alibaba Group Holding Limited
*/
#ifndef _AOS_PWM_CORE_H
#define _AOS_PWM_CORE_H
#ifndef AOS_PWM_CORE_H
#define AOS_PWM_CORE_H
#include <stdint.h>
#include <aos/kernel.h>
#include <aos/device_core.h>
#include <aos/pwm.h>
......@@ -76,4 +74,4 @@ aos_status_t aos_pwm_unregister(uint32_t id);
}
#endif
#endif /* _AOS_PWM_CORE_H */
#endif /* AOS_PWM_CORE_H */
## 第一部分: 基础信息
name: pwm # <必选项> 包名称 (符合C语言变量命名规则),长度少于等于64字节
version: master # <必选项> 组件版本号
description: PWM 通用驱动 # <必选项> 建议至少20字以上
version: master # <必选项> 组件版本号
description: PWM通用驱动 # <必选项> 建议至少20字以上
type: common # <必选项> 组件类型,为:solution, chip, board, common, sdk
tag: 第三方驱动 # <可选项> 组件分类,缺省值: ''
keywords: # <可选项> 标签,会影响到组件被搜索的效果,合理的标签很重要
- pwm core and vfs driver
- pwm driver
license: Apache license v2.0 # <可选项> 源代码的许可证,要确保所有代码、文件的许可证不冲突。如:MIT,Apache license v2.0,BSD
## 第二部分:依赖信息
......@@ -18,7 +17,7 @@ license: Apache license v2.0 # <可选项> 源代码的
# - aos: >=v7.2.0
depends:
- base: master
- vfs: master
- csi: master ? <AOS_CONFIG_PWM_CSI>
## 第四部分:编译连接信息
# build_config: # <可选项> 编译配置项
......@@ -47,19 +46,16 @@ build_config:
# source_file: # <可选项> 指定参与编译的源代码文件,支持通配符,采用相对路径
# - src/*.c # 例:组件 src 目录下所有的扩展名为 c 的源代码文件
source_file:
# PWM
- src/pwm_dev.c ? <CONFIG_U_PWM_DEV>
- src/pwm.c ? <CONFIG_U_PWM_CORE>
- src/pwm_csi.c ? <CONFIG_U_PWM_CORE>
# - example/aos_pwm_example.c ? <CONFIG_U_PWM_CORE>
# - example/pwm_example.c ? <CONFIG_U_PWM_DEV>
- src/pwm.c
- src/pwm_csi.c ? <AOS_CONFIG_PWM_CSI>
## 第五部分:配置信息
# def_config: # 组件的可配置项
# CONFIG_DEBUG: y
# CONFIG_PARAM_NOT_CHECK: y
# CONFIG_CLI: y
def_config:
AOS_COMP_PWM: 1
## 第六部分:安装信息
# install:
......@@ -67,8 +63,9 @@ source_file:
# source: # 安装源列表
# - src/*.h # 支持通配符,相对路径
install:
- dest: "include/devices"
- dest: "include/aos"
source:
- "include/aos/pwm.h"
## 第七部分:导出部分
# export:
......
......@@ -2,14 +2,11 @@
* Copyright (C) 2021 Alibaba Group Holding Limited
*/
#include <stdint.h>
#include <errno.h>
#include <stdbool.h>
#include <aos/kernel.h>
#include <aos/list.h>
#include <aos/pwm.h>
#include <stdio.h>
#include <aos/pwm_core.h>
#include <drivers/ddkc_log.h>
#ifdef AOS_COMP_DEVFS
#include <inttypes.h>
#endif
#define AOS_MAX_PERIOD (1000000000U)
#define AOS_PWM_CHECK_NULL(x) \
......@@ -45,11 +42,11 @@ aos_status_t aos_pwm_set_attr(aos_pwm_ref_t *ref, aos_pwm_attr_t const *attr)
pwm = aos_container_of(ref->dev, aos_pwm_t, dev);
memcpy(&l_attr, attr, sizeof(aos_pwm_attr_t));
if (l_attr.period > AOS_MAX_PERIOD) {
ddkc_warn("warning:period exceeds 1s\r\n");
printf("warning:period exceeds 1s\r\n");
l_attr.period = AOS_MAX_PERIOD;
}
if (l_attr.duty_cycle > l_attr.period) {
ddkc_warn("warning: duty exceeds period\r\n");
printf("warning: duty exceeds period\r\n");
l_attr.duty_cycle = l_attr.period;
}
if (l_attr.period == pwm->period &&
......@@ -74,7 +71,6 @@ aos_status_t aos_pwm_set_attr(aos_pwm_ref_t *ref, aos_pwm_attr_t const *attr)
aos_status_t aos_pwm_get_attr(aos_pwm_ref_t *ref, aos_pwm_attr_t *attr)
{
aos_status_t ret;
aos_pwm_t *pwm;
AOS_PWM_CHECK_NULL(ref);
......@@ -83,7 +79,7 @@ aos_status_t aos_pwm_get_attr(aos_pwm_ref_t *ref, aos_pwm_attr_t *attr)
aos_dev_lock(ref->dev);
attr->period = pwm->period;
attr->duty_cycle = pwm->duty_cycle;
attr->enabled = pwm->enabled;
attr->enabled = pwm->enabled;
attr->polarity = pwm->polarity;
aos_dev_unlock(ref->dev);
return 0;
......@@ -124,10 +120,70 @@ static const aos_dev_ops_t dev_pwm_ops = {
.put = dev_pwm_put,
};
aos_status_t aos_pwm_register(aos_pwm_t *pwm)
#ifdef AOS_COMP_DEVFS
static aos_status_t devfs_pwm_ioctl(aos_devfs_file_t *file, int cmd, uintptr_t arg)
{
aos_pwm_ref_t *ref = aos_devfs_file2ref(file);
aos_status_t ret;
switch (cmd) {
case AOS_PWM_IOC_GET_ATTR:
{
aos_pwm_attr_t attr;
if (!aos_devfs_file_is_readable(file)) {
ret = -EPERM;
break;
}
ret = aos_pwm_get_attr(ref, &attr);
if (ret)
break;
if (!aos_umem_check((const void *)arg, sizeof(attr)))
return -EFAULT;
ret = aos_umem_copy((void *)arg, &attr, sizeof(attr)) ? -EFAULT : 0;
}
break;
case AOS_PWM_IOC_SET_ATTR:
{
aos_pwm_attr_t attr;
if (!aos_devfs_file_is_writable(file)) {
ret = -EPERM;
break;
}
if (!aos_umem_check((const void *)arg, sizeof(attr)))
return -EFAULT;
if (aos_umem_copy(&attr, (const void *)arg, sizeof(attr))) {
ret = -EFAULT;
break;
}
ret = aos_pwm_set_attr(ref, &attr);
}
break;
default:
ret = -EINVAL;
break;
}
return ret;
}
static const aos_devfs_file_ops_t devfs_pwm_ops = {
.ioctl = devfs_pwm_ioctl,
.poll = NULL,
.mmap = NULL,
.read = NULL,
.write = NULL,
.lseek = NULL,
};
#endif /* AOS_COMP_DEVFS */
aos_status_t aos_pwm_register(aos_pwm_t *pwm)
{
#ifdef AOS_COMP_DEVFS
int name_len;
#endif
AOS_PWM_CHECK_NULL(pwm);
/* startup/shutdown/unregister/apply/startup must be set. */
......@@ -142,10 +198,12 @@ aos_status_t aos_pwm_register(aos_pwm_t *pwm)
pwm->duty_cycle = 0;
pwm->period = 0;
pwm->polarity = 0;
#ifdef AOS_COMP_VFS
/* TODO: support vfs ops. */
pwm->dev.vfs_helper.name[0] = '\0';
pwm->dev.vfs_helper.ops = NULL;
#ifdef AOS_COMP_DEVFS
aos_devfs_node_init(&pwm->dev.devfs_node);
pwm->dev.devfs_node.ops = &devfs_pwm_ops;
name_len = snprintf(pwm->dev.devfs_node.name, sizeof(pwm->dev.devfs_node.name), "pwm%" PRIu32, pwm->dev.id);
if (name_len < 0 || name_len >= sizeof(pwm->dev.devfs_node.name))
return -EINVAL;
#endif
return aos_dev_register(&(pwm->dev));
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册