From 7c45b3a22908846d7e0dabe3f185fbdf73675104 Mon Sep 17 00:00:00 2001 From: yinshuqing Date: Tue, 23 Nov 2021 15:13:15 +0800 Subject: [PATCH] New Mipi_ CSI guidance document Signed-off-by: yinshuqing --- zh-cn/device-dev/apis/driver/adc_if.h | 85 ++ zh-cn/device-dev/apis/driver/hdmi_if.h | 785 +++++++++++++++ zh-cn/device-dev/apis/driver/i3c_if.h | 236 +++++ zh-cn/device-dev/apis/driver/mipi_csi_if.h | 537 +++++++++++ zh-cn/device-dev/driver/Readme-CN.md | 2 + .../driver/driver-platform-mipicsi-des.md | 777 +++++++++++++++ .../driver/driver-platform-mipicsi-develop.md | 312 ++++++ .../driver/driver-platform-mipidsi-des.md | 26 +- .../driver/driver-platform-pwm-des.md | 890 ++++++++---------- ...5\346\224\266\346\216\245\345\217\243.png" | Bin 0 -> 23263 bytes ...7\347\273\223\346\236\204\345\233\276.png" | Bin 0 -> 40274 bytes ...0\346\265\201\347\250\213\345\233\276.png" | Bin 0 -> 13078 bytes ...0\346\265\201\347\250\213\345\233\276.png" | Bin 0 -> 9334 bytes 13 files changed, 3141 insertions(+), 509 deletions(-) create mode 100755 zh-cn/device-dev/apis/driver/adc_if.h create mode 100755 zh-cn/device-dev/apis/driver/hdmi_if.h create mode 100755 zh-cn/device-dev/apis/driver/i3c_if.h create mode 100755 zh-cn/device-dev/apis/driver/mipi_csi_if.h create mode 100755 zh-cn/device-dev/driver/driver-platform-mipicsi-des.md create mode 100755 zh-cn/device-dev/driver/driver-platform-mipicsi-develop.md create mode 100755 "zh-cn/device-dev/driver/figures/CSI\345\217\221\351\200\201-\346\216\245\346\224\266\346\216\245\345\217\243.png" create mode 100755 "zh-cn/device-dev/driver/figures/CSI\346\227\240\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" create mode 100755 "zh-cn/device-dev/driver/figures/MIPI-CSI\344\275\277\347\224\250\346\265\201\347\250\213\345\233\276.png" create mode 100755 "zh-cn/device-dev/driver/figures/PWM\350\256\276\345\244\207\344\275\277\347\224\250\346\265\201\347\250\213\345\233\276.png" diff --git a/zh-cn/device-dev/apis/driver/adc_if.h b/zh-cn/device-dev/apis/driver/adc_if.h new file mode 100755 index 00000000000..a14cdc5d87f --- /dev/null +++ b/zh-cn/device-dev/apis/driver/adc_if.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +/** + * @addtogroup ADC + * @{ + * + * @brief 定义用于模/数转换器驱动程序开发的标准ADC API。 + * 此ADC模块抽象了不同系统平台的ADC功能,以提供稳定的API,用于模/数转换器驱动程序开发。您可以使用此模块获取/释放ADC设备句柄。 + * + * @since 1.0 + */ + +/** + * @file adc_if.h + * + * @brief 声明标准ADC接口函数。 + * + * @since 1.0 + */ + +#ifndef ADC_IF_H +#define ADC_IF_H + +#include "hdf_platform.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif /* __cplusplus */ + +struct AdcIoMsg { + /** ADC设备号 */ + uint32_t number; + /** ADC设备通道号 */ + uint32_t channel; +}; + +/** + * @brief 获取ADC设备的句柄。 + * 在访问ADC设备之前,必须调用此函数。 + * + * @param number ADC设备ID。 + * + * @return 如果操作成功,则返回指向ADC设备的DevHandle的指针;否则返回NULL。 + * + * @since 1.0 + */ +DevHandle AdcOpen(uint32_t number); + + /** + * @brief 释放ADC设备的句柄。 + * 如果不再需要访问ADC设备,则应调用此函数关闭其句柄,以便释放未使用的内存资源。 + * + * @param handle 指向通过{@link AdcOpen}获得的ADC设备的设备句柄的指针。 + * + * @since 1.0 + */ +void AdcClose(DevHandle handle); + +/** + * @brief 从ADC设备读取指定大小的数据。 + * + * @param handle 指向通过{@link AdcOpen}获得的ADC设备的设备句柄的指针。 + * @param channel ADC设备通道。 + * @param val 指向存储读出数据指针。 + * + * @return 如果操作成功,则返回0;否则返回负值。 + * @since 1.0 + */ +int32_t AdcRead(DevHandle handle, uint32_t channel, uint32_t *val); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* __cplusplus */ + +#endif /* ADC_IF_H */ diff --git a/zh-cn/device-dev/apis/driver/hdmi_if.h b/zh-cn/device-dev/apis/driver/hdmi_if.h new file mode 100755 index 00000000000..3e3b4bd1a71 --- /dev/null +++ b/zh-cn/device-dev/apis/driver/hdmi_if.h @@ -0,0 +1,785 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +/** + * @addtogroup HDMI + * @{ + * + * @brief 声明基本高清多媒体接口(HDMI)功能的标准API。 + * 您可以使用此模块访问HDMI,并使驱动程序能够操作HDMI接收器设备。 + * 这些功能包括在HDMI上启动和停止传输,设置一些属性,并读取接收器设备的EDID数据。 + * + * @since 1.0 + */ + +/** + * @file hdmi_if.h + * + * @brief 声明标准HDMI接口函数。 + * + * @since 1.0 + */ + +#ifndef HDMI_IF_H +#define HDMI_IF_H + +#include "hdf_platform.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif /* __cplusplus */ + +/** + * @brief HDMI接收器设备的EDID的最大长度为512字节。 + * + * @since 1.0 + */ +#define HDMI_EDID_MAX_LEN 512 + +/** + * @brief 色深 + * 详见HDMI协议1.4第6.2.4节。 + * + * @since 1.0 + */ +enum HdmiDeepColor { + HDMI_DEEP_COLOR_24BITS = 0, + HDMI_DEEP_COLOR_30BITS = 1, + HDMI_DEEP_COLOR_36BITS = 2, + HDMI_DEEP_COLOR_48BITS = 3, + HDMI_DEEP_COLOR_OFF = 0xff, + HDMI_DEEP_COLOR_BUTT, +}; + +/** + * @brief 视频位深度。 + * 详见HDMI协议1.4第6.6节。 + * + * @since 1.0 + */ +enum HdmiVideoBitDepth { + HDMI_VIDEO_BIT_DEPTH_8 = 0, + HDMI_VIDEO_BIT_DEPTH_10 = 1, + HDMI_VIDEO_BIT_DEPTH_12 = 2, + HDMI_VIDEO_BIT_DEPTH_16 = 3, + HDMI_VIDEO_BIT_DEPTH_OFF, +}; + +/** + * @brief 色彩空间。 + * 详见HDMI协议1.4第6节。 + * + * @since 1.0 + */ +enum HdmiColorSpace { + HDMI_COLOR_SPACE_RGB = 0, + HDMI_COLOR_SPACE_YCBCR422 = 1, + HDMI_COLOR_SPACE_YCBCR444 = 2, + HDMI_COLOR_SPACE_YCBCR420 = 3, + HDMI_COLOR_SPACE_BUTT, +}; + +/** + * @brief 比色法。 + * 详见HDMI协议1.4第6.7节和HDMI协议2.0第7.2节。 + * + * @since 1.0 + */ +enum HdmiColorimetry { + HDMI_COLORIMETRY_NO_DATA = 0, + HDMI_COLORIMETRY_ITU601 = 1, + HDMI_COLORIMETRY_ITU709 = 2, + HDMI_COLORIMETRY_EXTENDED = 3, +}; + +/** + * @brief 扩展比色法。 + * 详见HDMI协议1.4第6.7节和HDMI协议2.0第7.2节。 + * + * @since 1.0 + */ +enum HdmiExtendedColorimetry { + HDMI_EXTENDED_COLORIMETRY_XV_YCC_601 = 0, + HDMI_EXTENDED_COLORIMETRY_XV_YCC_709 = 1, + HDMI_EXTENDED_COLORIMETRY_S_YCC_601 = 2, + HDMI_EXTENDED_COLORIMETRY_OPYCC_601 = 3, + HDMI_EXTENDED_COLORIMETRY_OPRGB = 4, + HDMI_EXTENDED_COLORIMETRY_BT2020_CONST_LUM = 5, + HDMI_EXTENDED_COLORIMETRY_BT2020 = 6, + HDMI_EXTENDED_COLORIMETRY_ADDITIONAL = 7, + HDMI_EXTENDED_COLORIMETRY_BUTT, +}; + +/** + * @brief 量化范围。 + * 详见HDMI协议1.4第6.6节和HDMI协议2.0第7.3节。 + * + * @since 1.0 + */ +enum HdmiQuantizationRange { + HDMI_QUANTIZATION_RANGE_DEFAULT = 0, + HDMI_QUANTIZATION_RANGE_LIMITED = 1, + HDMI_QUANTIZATION_RANGE_FULL = 2, + HDMI_QUANTIZATION_RANGE_BUTT, +}; + +/** + * @brief YCC量化范围。 + * 详见HDMI协议1.4第6.6节和HDMI协议2.0第7.3节。 + * + * @since 1.0 + */ +enum HdmiYccQuantizationRange { + HDMI_YCC_QUANTIZATION_RANGE_LIMITED = 0, + HDMI_YCC_QUANTIZATION_RANGE_FULL = 1, + HDMI_YCC_QUANTIZATION_RANGE_BUTT, +}; + +/** + * @brief 视频三维结构。 + * 详见HDMI协议1.4第8.2.3节。 + * + * @since 1.0 + */ +enum HdmiVideo3dStructure { + HDMI_VS_VIDEO_3D_FRAME_PACKING = 0, + HDMI_VS_VIDEO_3D_FIELD_ALTERNATIVE = 1, + HDMI_VS_VIDEO_3D_LINE_ALTERNATIVE = 2, + HDMI_VS_VIDEO_3D_SIDE_BY_SIDE_FULL = 3, + HDMI_VS_VIDEO_3D_L_DEPTH = 4, + HDMI_VS_VIDEO_3D_L_DEPTH_GFX_GFX_DEPTH = 5, + HDMI_VS_VIDEO_3D_TOP_AND_BOTTOM = 6, + HDMI_VS_VIDEO_3D_SIDE_BY_SIDE_HALF = 8, + HDMI_VS_VIDEO_3D_BUTT, +}; + +/** + * @brief 影像时序。 + * 详见HDMI协议1.4第8.2.3节。 + * + * @since 1.0 + */ +enum HdmiVideoTiming { + HDMI_VIDEO_TIMING_NONE = 0, + HDMI_VIDEO_TIMING_640X480P60 = 1, + HDMI_VIDEO_TIMING_720X480P60 = 2, + HDMI_VIDEO_TIMING_720X480P120 = 3, + HDMI_VIDEO_TIMING_720X480P240 = 4, + HDMI_VIDEO_TIMING_720X576P50 = 5, + HDMI_VIDEO_TIMING_720X576P100 = 6, + HDMI_VIDEO_TIMING_720X576P200 = 7, + HDMI_VIDEO_TIMING_1280X720P24 = 8, + HDMI_VIDEO_TIMING_1280X720P25 = 9, + HDMI_VIDEO_TIMING_1280X720P30 = 10, + HDMI_VIDEO_TIMING_1280X720P48 = 11, + HDMI_VIDEO_TIMING_1280X720P50 = 12, + HDMI_VIDEO_TIMING_1280X720P60 = 13, + HDMI_VIDEO_TIMING_1280X720P100 = 14, + HDMI_VIDEO_TIMING_1280X720P120 = 15, + HDMI_VIDEO_TIMING_1440X240P60 = 16, + HDMI_VIDEO_TIMING_1440X288P50 = 17, + HDMI_VIDEO_TIMING_1440X480I60 = 18, + HDMI_VIDEO_TIMING_1440X480P60 = 19, + HDMI_VIDEO_TIMING_1440X480I120 = 20, + HDMI_VIDEO_TIMING_1440X480I240 = 21, + HDMI_VIDEO_TIMING_1440X576I50 = 22, + HDMI_VIDEO_TIMING_1440X576P50 = 23, + HDMI_VIDEO_TIMING_1440X576I60 = 24, + HDMI_VIDEO_TIMING_1440X576I100 = 25, + HDMI_VIDEO_TIMING_1440X576I200 = 26, + HDMI_VIDEO_TIMING_2880X288P50 = 27, + HDMI_VIDEO_TIMING_2880X480I60 = 28, + HDMI_VIDEO_TIMING_2880X480P60 = 29, + HDMI_VIDEO_TIMING_2880X240I60 = 30, + HDMI_VIDEO_TIMING_2880X576I50 = 31, + HDMI_VIDEO_TIMING_2880X576P50 = 32, + HDMI_VIDEO_TIMING_1680X720P24 = 33, + HDMI_VIDEO_TIMING_1680X720P25 = 34, + HDMI_VIDEO_TIMING_1680X720P30 = 35, + HDMI_VIDEO_TIMING_1680X720P48 = 36, + HDMI_VIDEO_TIMING_1680X720P50 = 37, + HDMI_VIDEO_TIMING_1680X720P60 = 38, + HDMI_VIDEO_TIMING_1680X720P100 = 39, + HDMI_VIDEO_TIMING_1680X720P120 = 40, + HDMI_VIDEO_TIMING_2560X1080P24 = 41, + HDMI_VIDEO_TIMING_2560X1080P25 = 42, + HDMI_VIDEO_TIMING_2560X1080P30 = 43, + HDMI_VIDEO_TIMING_2560X1080P48 = 44, + HDMI_VIDEO_TIMING_2560X1080P50 = 45, + HDMI_VIDEO_TIMING_2560X1080P60 = 46, + HDMI_VIDEO_TIMING_2560X1080P100 = 47, + HDMI_VIDEO_TIMING_2560X1080P120 = 48, + HDMI_VIDEO_TIMING_1920X1080I60 = 49, + HDMI_VIDEO_TIMING_1920X1080P60 = 50, + HDMI_VIDEO_TIMING_1920X1080I50 = 51, + HDMI_VIDEO_TIMING_1920X1080P50 = 52, + HDMI_VIDEO_TIMING_1920X1080P24 = 53, + HDMI_VIDEO_TIMING_1920X1080P25 = 54, + HDMI_VIDEO_TIMING_1920X1080P30 = 55, + HDMI_VIDEO_TIMING_1920X1080P48 = 56, + HDMI_VIDEO_TIMING_1920X1080I100 = 57, + HDMI_VIDEO_TIMING_1920X1080I120 = 58, + HDMI_VIDEO_TIMING_1920X1080P120 = 59, + HDMI_VIDEO_TIMING_1920X1080P100 = 60, + HDMI_VIDEO_TIMING_3840X2160P24 = 61, + HDMI_VIDEO_TIMING_3840X2160P25 = 62, + HDMI_VIDEO_TIMING_3840X2160P30 = 63, + HDMI_VIDEO_TIMING_3840X2160P48 = 64, + HDMI_VIDEO_TIMING_3840X2160P50 = 65, + HDMI_VIDEO_TIMING_3840X2160P60 = 66, + HDMI_VIDEO_TIMING_3840X2160P100 = 67, + HDMI_VIDEO_TIMING_3840X2160P120 = 68, + HDMI_VIDEO_TIMING_4096X2160P24 = 69, + HDMI_VIDEO_TIMING_4096X2160P25 = 70, + HDMI_VIDEO_TIMING_4096X2160P30 = 71, + HDMI_VIDEO_TIMING_4096X2160P48 = 72, + HDMI_VIDEO_TIMING_4096X2160P50 = 73, + HDMI_VIDEO_TIMING_4096X2160P60 = 74, + HDMI_VIDEO_TIMING_4096X2160P100 = 75, + HDMI_VIDEO_TIMING_4096X2160P120 = 76, + HDMI_VIDEO_TIMING_5120X2160P24 = 77, + HDMI_VIDEO_TIMING_5120X2160P25 = 78, + HDMI_VIDEO_TIMING_5120X2160P30 = 79, + HDMI_VIDEO_TIMING_5120X2160P48 = 80, + HDMI_VIDEO_TIMING_5120X2160P50 = 81, + HDMI_VIDEO_TIMING_5120X2160P60 = 82, + HDMI_VIDEO_TIMING_5120X2160P100 = 83, + HDMI_VIDEO_TIMING_5120X2160P120 = 84, + HDMI_VIDEO_TIMING_7680X4320P24 = 85, + HDMI_VIDEO_TIMING_7680X4320P25 = 86, + HDMI_VIDEO_TIMING_7680X4320P30 = 87, + HDMI_VIDEO_TIMING_7680X4320P48 = 88, + HDMI_VIDEO_TIMING_7680X4320P50 = 89, + HDMI_VIDEO_TIMING_7680X4320P60 = 90, + HDMI_VIDEO_TIMING_7680X4320P100 = 91, + HDMI_VIDEO_TIMING_7680X4320P120 = 92, + HDMI_VIDEO_TIMING_10240X4320P24 = 93, + HDMI_VIDEO_TIMING_10240X4320P25 = 94, + HDMI_VIDEO_TIMING_10240X4320P30 = 95, + HDMI_VIDEO_TIMING_10240X4320P48 = 96, + HDMI_VIDEO_TIMING_10240X4320P50 = 97, + HDMI_VIDEO_TIMING_10240X4320P60 = 98, + HDMI_VIDEO_TIMING_10240X4320P100 = 99, + HDMI_VIDEO_TIMING_10240X4320P120 = 100, + HDMI_VIDEO_TIMING_VESA_DEFINE = 101, + HDMI_VIDEO_TIMING_VESA_800X600_60 = 102, + HDMI_VIDEO_TIMING_VESA_848X480_60 = 103, + HDMI_VIDEO_TIMING_VESA_1024X768_60 = 104, + HDMI_VIDEO_TIMING_VESA_1280X720_60 = 105, + HDMI_VIDEO_TIMING_VESA_1280X768_60 = 106, + HDMI_VIDEO_TIMING_VESA_1280X768_60_RB = 107, + HDMI_VIDEO_TIMING_VESA_1280X800_60 = 108, + HDMI_VIDEO_TIMING_VESA_1280X800_60_RB = 109, + HDMI_VIDEO_TIMING_VESA_1280X960_60 = 110, + HDMI_VIDEO_TIMING_VESA_1280X1024_60 = 111, + HDMI_VIDEO_TIMING_VESA_1360X768_60 = 112, + HDMI_VIDEO_TIMING_VESA_1366X768_60 = 113, + HDMI_VIDEO_TIMING_VESA_1400X1050_60 = 114, + HDMI_VIDEO_TIMING_VESA_1440X900_60 = 115, + HDMI_VIDEO_TIMING_VESA_1440X900_60_RB = 116, + HDMI_VIDEO_TIMING_VESA_1440X1050_60 = 117, + HDMI_VIDEO_TIMING_VESA_1440X1050_60_RB = 118, + HDMI_VIDEO_TIMING_VESA_1600X900_60_RB = 119, + HDMI_VIDEO_TIMING_VESA_1600X1200_60 = 120, + HDMI_VIDEO_TIMING_VESA_1680X1050_60 = 113, + HDMI_VIDEO_TIMING_VESA_1680X1050_60_RB = 114, + HDMI_VIDEO_TIMING_VESA_1792X1344_60 = 115, + HDMI_VIDEO_TIMING_VESA_1856X1392_60 = 116, + HDMI_VIDEO_TIMING_VESA_1920X1080_60 = 117, + HDMI_VIDEO_TIMING_VESA_1920X1200_60 = 118, + HDMI_VIDEO_TIMING_VESA_1920X1200_60_RB = 119, + HDMI_VIDEO_TIMING_VESA_1920X1440_60 = 120, + HDMI_VIDEO_TIMING_VESA_2048X1152_60 = 121, + HDMI_VIDEO_TIMING_VESA_2560X1440_60_RB = 122, + HDMI_VIDEO_TIMING_VESA_2560X1600_60 = 123, + HDMI_VIDEO_TIMING_VESA_2560X1600_60_RB = 124, + HDMI_VIDEO_TIMING_USER_DEFINE = 125, + HDMI_VIDEO_TIMING_USER_1920X2160_30 = 126, + HDMI_VIDEO_TIMING_USER_2560X1440_30 = 127, + HDMI_VIDEO_TIMING_USER_2560X1440_60 = 128, + HDMI_VIDEO_TIMING_USER_1280X720_60 = 129, + HDMI_VIDEO_TIMING_USER_1366X768_60 = 130, + HDMI_VIDEO_TIMING_USER_1600X900_60_RB = 131, + HDMI_VIDEO_TIMING_USER_1920X1080_60 = 132, + HDMI_VIDEO_TIMING_USER_2048X1152_60 = 133, + HDMI_VIDEO_TIMING_BUTT, +}; + +/** + * @brief 图片的纵横比。 + * 详见HDMI协议1.4第8.2.1节。 + * + * @since 1.0 + */ +enum HdmiPictureAspectRatio { + HDMI_PICTURE_ASPECT_NO_DATA = 0, + HDMI_PICTURE_ASPECT_4_3 = 1, + HDMI_PICTURE_ASPECT_16_9 = 2, + HDMI_PICTURE_ASPECT_64_27 = 3, + HDMI_PICTURE_ASPECT_256_135 = 4, + HDMI_PICTURE_ASPECT_BUTT = 5, +}; + +/** + * @brief 活动格式的长宽比。 + * 详见HDMI协议1.4第8.2.1节。 + * + * @since 1.0 + */ +enum HdmiActiveFormatAspectRatio { + HDMI_ACTIVE_FORMAT_ASPECT_16_9_TOP = 2, + HDMI_ACTIVE_FORMAT_ASPECT_14_9_TOP = 3, + HDMI_ACTIVE_FORMAT_ASPECT_16_9_CENTER = 4, + HDMI_ACTIVE_FORMAT_ASPECT_PICTURE = 8, + HDMI_ACTIVE_FORMAT_ASPECT_4_3 = 9, + HDMI_ACTIVE_FORMAT_ASPECT_16_9 = 10, + HDMI_ACTIVE_FORMAT_ASPECT_14_9 = 11, + HDMI_ACTIVE_FORMAT_ASPECT_4_3_SP_14_9 = 13, + HDMI_ACTIVE_FORMAT_ASPECT_16_9_SP_14_9 = 14, + HDMI_ACTIVE_FORMAT_ASPECT_16_9_SP_4_3 = 15, + HDMI_ACTIVE_FORMAT_ASPECT_BUTT, +}; + +/** + * @brief NUP(非均匀图片缩放)。 + * 详见HDMI协议1.4第8.2.1节。 + * + * @since 1.0 + */ +enum HdmiNups { + HDMI_NUPS_UNKNOWN = 0, /* 没有已知的非均匀缩放 */ + HDMI_NUPS_HORIZONTAL = 1, /* 图片已水平缩放 */ + HDMI_NUPS_VERTICAL = 2, /* 图片已垂直缩放 */ + HDMI_NUPS_BOTH = 3, /* 图片已水平和垂直缩放 */ +}; + +/** + * @brief 定义视频属性结构。 + * + * @since 1.0 + */ +struct HdmiVideoAttr { + uint32_t tmdsClock; /* 单位:千赫 */ + uint32_t pixelClock; /* 单位:千赫 */ + uint32_t pixelRepeat; + enum HdmiColorSpace colorSpace; + enum HdmiColorimetry colorimetry; + enum HdmiExtendedColorimetry extColorimetry; + enum HdmiQuantizationRange quantization; + enum HdmiYccQuantizationRange yccQuantization; + enum HdmiDeepColor deepColor; + enum HdmiVideo3dStructure _3dStruct; + enum HdmiVideoTiming timing; + enum HdmiPictureAspectRatio aspect; + enum HdmiActiveFormatAspectRatio activeAspect; + enum HdmiNups nups; + bool xvycc; +}; + +/** + * @brief 音频编码类型。 + * 详见HDMI协议1.4第7节。 + * + * @since 1.0 + */ +enum HdmiAudioCodingType { + HDMI_AUDIO_CODING_TYPE_STREAM = 0, + HDMI_AUDIO_CODING_TYPE_LPCM = 1, + HDMI_AUDIO_CODING_TYPE_AC3 = 2, + HDMI_AUDIO_CODING_TYPE_MPEG1 = 3, + HDMI_AUDIO_CODING_TYPE_MP3 = 4, + HDMI_AUDIO_CODING_TYPE_MPEG2 = 5, + HDMI_AUDIO_CODING_TYPE_AAC_LC = 6, + HDMI_AUDIO_CODING_TYPE_DTS = 7, + HDMI_AUDIO_CODING_TYPE_ATRAC = 8, + HDMI_AUDIO_CODING_TYPE_OBA = 9, + HDMI_AUDIO_CODING_TYPE_EAC3 = 10, + HDMI_AUDIO_CODING_TYPE_DTS_HD = 11, + HDMI_AUDIO_CODING_TYPE_MLP = 12, + HDMI_AUDIO_CODING_TYPE_DST = 13, + HDMI_AUDIO_CODING_TYPE_WMA_PRO = 14, + HDMI_AUDIO_CODING_TYPE_CXT = 15, +}; + +/** + * @brief 音频接口类型。 + * + * @since 1.0 + */ +enum HdmiAudioInterfaceType { + HDMI_AUDIO_IF_TYPE_I2S = 0, /* I2S总线 */ + HDMI_AUDIO_IF_TYPE_SPDIF = 1, /* 索尼/飞利浦数字接口 */ + HDMI_AUDIO_IF_TYPE_OTHER, +}; + +/** + * @brief 音频位深度。 + * 详见HDMI协议1.4第7节。 + * + * @since 1.0 + */ +enum HdmiAudioBitDepth { + HDMI_ADIO_BIT_DEPTH_UNKNOWN, + HDMI_ADIO_BIT_DEPTH_8 = 8, + HDMI_ADIO_BIT_DEPTH_16 = 16, + HDMI_ADIO_BIT_DEPTH_18 = 18, + HDMI_ADIO_BIT_DEPTH_20 = 20, + HDMI_ADIO_BIT_DEPTH_24 = 24, + HDMI_ADIO_BIT_DEPTH_32 = 32, + HDMI_ADIO_BIT_DEPTH_BUTT, +}; + +/** + * @brief 用于音频的采样率。 + * 详见HDMI协议1.4第7.3节。 + * + * @since 1.0 + */ +enum HdmiSampleRate { + HDMI_SAMPLE_RATE_UNKNOWN, + HDMI_SAMPLE_RATE_8K = 8000, + HDMI_SAMPLE_RATE_11K = 11025, + HDMI_SAMPLE_RATE_12K = 12000, + HDMI_SAMPLE_RATE_16K = 16000, + HDMI_SAMPLE_RATE_22K = 22050, + HDMI_SAMPLE_RATE_24K = 24000, + HDMI_SAMPLE_RATE_32K = 32000, + HDMI_SAMPLE_RATE_44K = 44100, + HDMI_SAMPLE_RATE_48K = 48000, + HDMI_SAMPLE_RATE_88K = 88200, + HDMI_SAMPLE_RATE_96K = 96000, + HDMI_SAMPLE_RATE_176K = 176400, + HDMI_SAMPLE_RATE_192K = 192000, + HDMI_SAMPLE_RATE_768K = 768000, + HDMI_SAMPLE_RATE_BUTT, +}; + +/** + * @brief 音频格式通道。 + * 详见HDMI协议1.4第7节。 + * + * @since 1.0 + */ +enum HdmiAudioFormatChannel { + HDMI_AUDIO_FORMAT_CHANNEL_2 = 2, + HDMI_AUDIO_FORMAT_CHANNEL_3, + HDMI_AUDIO_FORMAT_CHANNEL_4, + HDMI_AUDIO_FORMAT_CHANNEL_5, + HDMI_AUDIO_FORMAT_CHANNEL_6, + HDMI_AUDIO_FORMAT_CHANNEL_7, + HDMI_AUDIO_FORMAT_CHANNEL_8, + HDMI_AUDIO_FORMAT_CHANNEL_BUTT, +}; + +/** + * @brief 定义音频属性结构。 + * + * @since 1.0 + */ +struct HdmiAudioAttr { + enum HdmiAudioCodingType codingType; + enum HdmiAudioInterfaceType ifType; + enum HdmiAudioBitDepth bitDepth; + enum HdmiSampleRate sampleRate; + bool downSample; + enum HdmiAudioFormatChannel channels; +}; + +/** + * @brief 电光传递函数(EOTF)。 + * 详见CTA-861-G第6.9节。 + * + * @since 1.0 + */ +enum HdmiEotfType { + HDMI_EOTF_SDR_LUMIN = 0, /* 传统gamma-SDR亮度范围 */ + HDMI_EOTF_HDR_LUMIN = 1, /* 传统gamma-HDR亮度范围 */ + HDMI_EOTF_SMPTE_ST_2048 = 2, /* SMPTE ST 2048 */ + HDMI_EOTF_HLG = 3, /* 基于ITU-R BT.2100-0的混合对数伽马(HLG) */ + HDMI_EOTF_BUTT, +}; + +/** + * @brief hdr色度计。 + * 详见HDMI协议2.1。 + * + * @since 1.0 + */ +enum HdmiHdrColormetry { + HDMI_HDR_COLORIMETRY_NONE, + HDMI_HDR_COLORIMETRY_ITU_601, + HDMI_HDR_COLORIMETRY_ITU_709, + HDMI_HDR_COLORIMETRY_EXTENDED, + HDMI_HDR_EXTENDED_COLORIMETRY_XV_YCC_601, + HDMI_HDR_EXTENDED_COLORIMETRY_XV_YCC_709, + HDMI_HDR_EXTENDED_COLORIMETRY_S_YCC_601, + HDMI_HDR_EXTENDED_COLORIMETRY_ADOBE_YCC_601, + HDMI_HDR_EXTENDED_COLORIMETRY_ADOBE_RGB, + HDMI_HDR_EXTENDED_COLORIMETRY_2020_CONST_LUMINOUS, /* BT2020 c_ycc */ + HDMI_HDR_EXTENDED_COLORIMETRY_2020_NON_CONST_LUMINOUW +}; + +/** + * @brief hdr模式。 + * 详见HDMI协议2.1。 + * + * @since 1.0 + */ +enum HdmiHdrMode { + HDMI_HDR_MODE_DISABLE, /* HDR和杜比模式禁用 */ + HDMI_HDR_MODE_DOLBY_NORMAL, /* 杜比正常(ycbcr422-12位)模式启用 */ + HDMI_HDR_MODE_DOLBY_TUNNELING, /* 杜比隧道(RGB-8bit)模式启用 */ + HDMI_HDR_MODE_CEA_861_3, /* HDR标准模式启用(根据) */ + HDMI_HDR_MODE_CEA_861_3_AUTHEN, /* HDR授权模式 */ + HDMI_HDR_MODE_BUTT +}; + +/** + * @brief hdr用户模式。 + * 详见HDMI协议2.1。 + * + * @since 1.0 + */ +enum HdmiHdrUserMode { + HDMI_HDR_USERMODE_SDR, + HDMI_HDR_USERMODE_HDR10, + HDMI_HDR_USERMODE_DOLBY, + HDMI_HDR_USERMODE_BUTT +}; + +/** + * @brief 静态元数据类型。 + * 详见CTA-861-G第6.9节。 + * + * @since 1.0 + */ +enum HdmiStaticMetadataType { + HDMI_DRM_STATIC_METADATA_TYPE_1 = 0, /* 静态元数据类型1 */ + HDMI_DRM_STATIC_METADATA_BUTT, +}; + +/** + * @brief 静态元数据描述符1st。 + * 详见CTA-861-G第6.9节。 + * + * @since 1.0 + */ +struct HdmiStaticMetadataDescriptor1st { + uint16_t displayPrimaries0X; /* display_primaries_x[0], in units of 0.00002 */ + uint16_t displayPrimaries0Y; /* display_primaries_y[0], in units of 0.00002 */ + uint16_t displayPrimaries1X; /* display_primaries_x[1], in units of 0.00002 */ + uint16_t displayPrimaries1Y; /* display_primaries_y[1], in units of 0.00002 */ + uint16_t displayPrimaries2X; /* display_primaries_x[2], in units of 0.00002 */ + uint16_t displayPrimaries2Y; /* display_primaries_y[2], in units of 0.00002 */ + uint16_t whitePointX; /* white_point_x, in units of 0.00002 */ + uint16_t whitePointY; /* white_point_y, in units of 0.00002 */ + uint16_t maxDisplayMasteringLuminance; /* max_display_mastering_luminance, in units of 1 cd/m^2 */ + uint16_t minDisplayMasteringLuminance; /* min_display_mastering_luminance, in units of 0.0001 cd/m^2 */ + uint16_t maxContentLightLevel; /* Maximum Content Light Level, in units of 1 cd/m^2 */ + uint16_t maxFrameAverageLightLevel; /* Maximum Frame-average Light Level, in units of 1 cd/m^2 */ +}; + +/** + * @brief 定义静态元数据描述符。 + * 详见CTA-861-G第6.9节。 + * + * @since 1.0 + */ +union HdmiStaticMetadataDescriptor { + struct HdmiStaticMetadataDescriptor1st type1; +}; + +/** + * @brief 定义hdr属性结构。 + * + * @since 1.0 + */ +struct HdmiHdrAttr { + enum HdmiHdrMode mode; + enum HdmiHdrUserMode userMode; + /* 当模式为HDMI_HDR_mode_CEA_861_3时,以下成员有效 */ + enum HdmiEotfType eotfType; + enum HdmiStaticMetadataType metadataType; + union HdmiStaticMetadataDescriptor descriptor; + enum HdmiHdrColormetry colorimetry; +}; + +/** + * @brief 定义hdmi HPD(热插拔检测)回调信息。 + * + * @since 1.0 + */ +struct HdmiHpdCallbackInfo { + void *data; + void (*callbackFunc)(void *data, bool hdp); +}; + +/** + * @brief 打开具有指定总线号的HDMI控制器。 + * 在使用HDMI接口之前,您可以获取HDMI控制器的设备句柄。 + * 通过调用HdmiOpen,此函数与HdmiClose成对使用。 + * + * @param busNum 总线号。 + * + * @return 如果操作成功,则返回HDMI控制器的设备句柄DevHandle;否则返回NULL。 + * + * @since 1.0 + */ +DevHandle HdmiOpen(uint16_t busNum); + +/** + * @brief 启动HDMI传输。 + * 此函数与HdmiStop成对使用。 + * + * @param handle 指向HDMI控制器的设备句柄的指针。 + * + * @return 如果操作成功,则返回0;如果操作失败,则返回负值。 + * + * @since 1.0 + */ +int32_t HdmiStart(DevHandle handle); + +/** + * @brief 停止HDMI传输。 + * 此函数与HdmiStart成对使用。 + * + * @param handle 指向HDMI控制器的设备句柄的指针。 + * + * @return 如果操作成功,则返回0;如果操作失败,则返回负值。 + * + * @since 1.0 + */ +int32_t HdmiStop(DevHandle handle); + +/** + * @brief HDMI声音图像消隐设置。 + * 首先将显示设备置于黑屏静音状态,等待HDMI输出设备开关。接着发送清除AVMute信号,启动显示设备。通过此设置,切换过程中的花屏现象将会被屏蔽掉。 + * + * @param handle 指向HDMI控制器的设备句柄的指针。 + * @param enable 是否启用avmute。 + * + * @return 如果操作成功,则返回0;如果操作失败,则返回负值。 + * + * @since 1.0 + */ +int32_t HdmiAvmuteSet(DevHandle handle, bool enable); + +/** + * @brief 设置色深。 + * + * @param handle 指向HDMI控制器的设备句柄的指针。 + * @param color 要设置的色深,请参见HdmiDeepColor。 + * + * @return 如果操作成功,则返回0;如果操作失败,则返回负值。 + * + * @since 1.0 + */ +int32_t HdmiDeepColorSet(DevHandle handle, enum HdmiDeepColor color); + +/** + * @brief 获取色深。 + * + * @param handle 指向HDMI控制器的设备句柄的指针。 + * @param color 指向要获取的色深的指针,请参见HdmiDeepColor。 + * + * @return 如果操作成功,则返回0;如果操作失败,则返回负值。 + * + * @since 1.0 + */ +int32_t HdmiDeepColorGet(DevHandle handle, enum HdmiDeepColor *color); + +/** + * @brief 设置视频属性。 + * + * @param handle 指向HDMI控制器的设备句柄的指针。 + * @param attr 指向要设置的视频属性的指针,请参见HdmiVideoAttr。 + * + * @return 如果操作成功,则返回0;如果操作失败,则返回负值。 + * + * @since 1.0 + */ +int32_t HdmiSetVideoAttribute(DevHandle handle, struct HdmiVideoAttr *attr); + +/** + * @brief 设置音频属性。 + * + * @param handle 指向HDMI控制器的设备句柄的指针。 + * @param attr 指向要设置的音频属性的指针,请参见HdmiAudioAttr。 + * + * @return 如果操作成功,则返回0;如果操作失败,则返回负值。 + * + * @since 1.0 + */ +int32_t HdmiSetAudioAttribute(DevHandle handle, struct HdmiAudioAttr *attr); + +/** + * @brief 设置HDR属性。 + * + * @param handle 指向HDMI控制器的设备句柄的指针。 + * @param attr 指向要设置的hdr属性的指针,请参见HdmiHdrAttr。 + * + * @return 如果操作成功,则返回0;如果操作失败,则返回负值。 + * + * @since 1.0 + */ +int32_t HdmiSetHdrAttribute(DevHandle handle, struct HdmiHdrAttr *attr); + +/** + * @brief HDMI读取接收器设备的原始EDID数据。 + * + * @param handle 指向HDMI控制器的设备句柄的指针。 + * @param buffer 指向要读取的数据的指针。 + * @param len 要读取的数据的长度。 + * + * @return 如果操作成功,返回读取数据的长度;如果操作失败,则返回负值或0。 + * + * @since 1.0 + */ +int32_t HdmiReadSinkEdid(DevHandle handle, uint8_t *buffer, uint32_t len); + +/** + * @brief 注册HPD(热插拔检测)回调函数。 + * + * @param handle 指向HDMI控制器的设备句柄的指针。 + * @param callback 指向回调信息的指针。 + * + * @return 如果操作成功,则返回0;如果操作失败,则返回负值。 + * + * @since 1.0 + */ +int32_t HdmiRegisterHpdCallbackFunc(DevHandle handle, struct HdmiHpdCallbackInfo *callback); + +/** + * @brief HDMI注销HPD(热插拔检测)回调函数。 + * + * @param handle 指向HDMI控制器的设备句柄的指针。 + * + * @return 如果操作成功,则返回0;如果操作失败,则返回负值。 + * @since 1.0 + */ +int32_t HdmiUnregisterHpdCallbackFunc(DevHandle handle); + +/** + * @brief 关闭HDMI控制器。 + * 使用HDMI接口后,可以通过调用HdmiClose关闭HDMI控制器。此函数与HdmiOpen成对使用。 + * + * @param handle 指向HDMI控制器的设备句柄的指针。 + * + * @since 1.0 + */ +void HdmiClose(DevHandle handle); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* __cplusplus */ + +#endif /* HDMI_IF_H */ diff --git a/zh-cn/device-dev/apis/driver/i3c_if.h b/zh-cn/device-dev/apis/driver/i3c_if.h new file mode 100755 index 00000000000..6130b13920b --- /dev/null +++ b/zh-cn/device-dev/apis/driver/i3c_if.h @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +/** + * @addtogroup I3C + * @{ + * + * @brief 提供改进的Improved Inter-Integrated Circuit (I3C)接口。 + * 该模块允许驱动程序在I3C控制器上执行操作,以访问I3C总线上的设备。 + * 包括创建和销毁I3C控制器句柄以及读取和写入数据。 + * + * @since 1.0 + */ + +/** + * @file i3c_if.h + * + * @brief 声明标准I3C接口函数。 + * + * @since 1.0 + */ + +#ifndef I3C_IF_H +#define I3C_IF_H + +#include "hdf_platform.h" +#include "i3c_ccc.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif /* __cplusplus */ + +enum TransMode { + /** I2C传输模式 */ + I2C_MODE = 0, + /** I3C传输模式 */ + I3C_MODE, + /** CCC(通用命令代码)模式 */ + CCC_CMD_MODE, +}; + +enum I3cBusMode { + /** 单数据速率模式 */ + I3C_BUS_SDR_MODE = 0, + /** 高数据速率模式 */ + I3C_BUS_HDR_MODE, +}; + +/** + * @brief 定义I3C控制器的配置。 + * + * @since 1.0 + */ +struct I3cConfig { + /** I3C总线模式 */ + enum I3cBusMode busMode; + /** 当前主设备,当控制器是主设备时,其为NULL */ + struct I3cDevice *curMaster; +}; + +/** + * @brief 定义I3C传输、I2C传输或发送CCC(通用命令代码)期间使用的I3C传输消息。 + * + * @attention 此结构不限制len指定的数据传输长度,允许的最大长度由特定控制器确定。 + * 设备地址addr表示原始设备地址,不需要包含读/写标志位。 + * @since 1.0 + */ +struct I3cMsg { + /** 目标设备的地址 */ + uint16_t addr; + /** 用于存储传输数据的缓冲区地址 */ + uint8_t *buf; + /** 传输数据的长度 */ + uint16_t len; + /** + * 传输模式标志 | 说明 + * ------------| ----------------------- + * I2C_FLAG_READ | 读标志 + * I2C_FLAG_READ_NO_ACK | 无确认读取标志 + * I2C_FLAG_IGNORE_NO_ACK | 忽略无确认标志 + * I2C_FLAG_NO_START | 无启动条件标志 + * I2C_FLAG_STOP | 停止条件标志 + */ + uint16_t flags; + /** 传输模式选择,默认为I2C_MODE */ + enum TransMode mode; + /** CCC(通用命令代码)结构,用于CCC_CMD_MODE传输模式 */ + struct I3cCccCmd *ccc; + /** I3C错误代码,由驱动程序更新 */ + uint16_t err; +}; + +/** + * @brief 定义I3C IBI(带内中断)的数据。 + * + * @attention 生成IBI时,IBI函数中的有效载荷和buf可获得IBI数据。 + * + * @since 1.0 + */ +struct I3cIbiData { + /** 有效载荷数据长度。IBI有效负载数据的长度。当IBI已生成,读取时请勿修改。 */ + uint32_t payload; + /** 数据缓冲区。有效负载数据的指针。 */ + uint8_t *buf; +}; + +enum I3cFlag { + /** 读标志。值1表示读取操作,0表示写入操作。 */ + I3C_FLAG_READ = (0x1 << 0), + /** 无ACK读标志。值1表示在读取过程中没有发送ACK信号。 */ + I3C_FLAG_READ_NO_ACK = (0x1 << 11), + /** 忽略ACK标志。值1表示忽略非ACK信号。 */ + I3C_FLAG_IGNORE_NO_ACK = (0x1 << 12), + + /** 无启动条件标志。值1表示消息没有启动条件转移。 */ + I3C_FLAG_NO_START = (0x1 << 14), + /** 停止条件标志。值1表示当前传输以停止条件结束。 */ + I3C_FLAG_STOP = (0x1 << 15), +}; + +/** + * @brief IBI(带内中断)回调函数。 + * 使用{@link I3cRequestIbi}将其连接到I3C设备。 + * + * @param handle 指向通过{@link I3cOpen}获得的I3C控制器句柄的指针。 + * @param addr 重新设置IBI(带内中断)的设备地址。 + * @param data IBI的数据结构。 + * + * @return 如果操作成功,则返回0;否则返回负值。 + * @since 1.0 + */ +typedef int32_t (*I3cIbiFunc)(DevHandle handle, uint16_t addr, struct I3cIbiData data); + +/** + * @brief 获取I3C控制器的句柄。 + * 在访问I3C总线之前,必须调用此函数。 + * + * @param number I3C控制器ID。 + * + * @return 如果操作成功,则返回指向I3C控制器的DevHandle的指针;否则返回NULL。 + * + * @since 1.0 + */ +DevHandle I3cOpen(int16_t number); + + /** + * @brief 释放I3C控制器的句柄。 + * 如果不再需要访问I3C控制器,则应调用此函数关闭其句柄,以便释放未使用的内存资源。 + * + * @param handle 指向通过{@link I3cOpen}获得的I3C控制器句柄的指针。 + * + * @since 1.0 + */ +void I3cClose(DevHandle handle); + + /** + * @brief 启动到I3C设备或兼容的I2C设备的传输,或者向支持的I3C设备发送CCC(通用命令代码)。 + * + * @param handle 指向通过{@link I3cOpen}获得的I3C控制器句柄的指针。 + * @param msg 指向I3C传输消息结构数组的指针。 + * @param count 消息结构数组的长度。 + * @param mode 传输模式。 + * + * @return 如果操作成功,返回传输的消息结构数; + * @see I3cMsg + * @attention 此结构不限制len指定的数据传输长度。 特定的 I3C 控制器决定了允许的最大长度。 设备地址addr表示原始设备地址,不需要包含读/写标志位。 + * + * @since 1.0 + */ +int32_t I3cTransfer(DevHandle handle, struct I3cMsg *msg, int16_t count, enum TransMode mode); + + /** + * @brief 重新设置受支持的I3C设备的IBI(带内中断)。 + * + * @param handle 指向通过{@link I3cOpen}获得的I3C控制器句柄的指针。 + * @param addr 重新设置IBI(带内中断)的设备地址。 + * @param func IBI回调函数。 + * @param payload 有效负载数据的长度,以字节为单位。 + * + * @return 如果操作成功,则返回0;否则返回负值。 + * + * @since 1.0 + */ +int32_t I3cRequestIbi(DevHandle handle, uint16_t addr, I3cIbiFunc func, uint32_t payload); + + /** + * @brief 释放{@link I3cRequestIbi}重新设置的IBI(带内中断)。 + * + * @param handle 指向通过{@link I3cOpen}获得的I3C控制器句柄的指针。 + * @param addr 要释放IBI的设备的地址。 + * + * @return 如果操作成功,则返回0;否则返回负值。 + * + * @since 1.0 + */ +int32_t I3cFreeIbi(DevHandle handle, uint16_t addr); + + /** + * @brief 设置I3C控制器的配置。 + * + * @param handle 指向通过{@link I3cOpen}获得的I3C控制器句柄的指针。 + * @param config 要设置的配置结构的指针。 + * + * @return 如果操作成功,则返回0;否则返回负值。 + * + * @since 1.0 + */ +int32_t I3cSetConfig(DevHandle handle, struct I3cConfig *config); + + /** + * @brief 获取I3C控制器的配置。 + * + * @param handle 指向通过{@link I3cOpen}获得的I3C控制器句柄的指针。 + * @param config 用于存储配置的结构体。 + * + * @return 如果操作成功,则返回0;否则返回负值。 + * + * @since 1.0 + */ +int32_t I3cGetConfig(DevHandle handle, struct I3cConfig *config); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* __cplusplus */ + +#endif /* I3C_IF_H */ +/** @} */ diff --git a/zh-cn/device-dev/apis/driver/mipi_csi_if.h b/zh-cn/device-dev/apis/driver/mipi_csi_if.h new file mode 100755 index 00000000000..e5f169e0aa1 --- /dev/null +++ b/zh-cn/device-dev/apis/driver/mipi_csi_if.h @@ -0,0 +1,537 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +/** + * @addtogroup MIPI CSI + * @{ + * + * @brief 定义用于外设接收端驱动程序开发的标准MIPI CSI API。 + * 此MIPI CSI模块抽象了不同系统平台的MIPI CSI功能,以提供稳定的API。 + * 用于外设接收端驱动程序开发。您可以使用此模块获取/释放MIPI CSI设备句柄。 + * + * @since 1.0 + */ + +/** + * @file mipi_csi_if.h + * + * @brief 声明用于显示驱动程序开发的标准MIPI CSI API。 + * + * + * + * @since 1.0 + */ + +#ifndef MIPI_CSI_IF_H +#define MIPI_CSI_IF_H + +#include "hdf_platform.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif /* __cplusplus */ + +/** + * @brief MIPI RX的MIPI设备支持的最大通道数。 + * + * @since 1.0 + */ +#define MIPI_LANE_NUM 4 + +/** + * @brief Mipi Rx的LVDS设备支持的最大通道数。 + * + * @since 1.0 + */ +#define LVDS_LANE_NUM 4 + +/** + * @brief 定义支持的最大虚拟通道数。 + * + * @since 1.0 + */ +#define WDR_VC_NUM 4 + +/** + * @brief 为LVDS的每个虚拟通道定义同步代码的数量。 + * + * @since 1.0 + */ +#define SYNC_CODE_NUM 4 + +/** + * @brief 最多3组扩展数据类型。 + * + * @since 1.0 + */ +#define MAX_EXT_DATA_TYPE_NUM 3 + +/** + * @brief Mipi-Rx的通道分布。 + * + * @since 1.0 + */ +typedef enum { + LANE_DIVIDE_MODE_0 = 0, + LANE_DIVIDE_MODE_1 = 1, + LANE_DIVIDE_MODE_BUTT +} LaneDivideMode; + +/** + * @brief MIPI接收输入接口类型。 + * + * @since 1.0 + */ +typedef enum { + /** mipi */ + INPUT_MODE_MIPI = 0x0, + /** SUB_LVDS */ + INPUT_MODE_SUBLVDS = 0x1, + /** LVDS */ + INPUT_MODE_LVDS = 0x2, + /* HISPI */ + INPUT_MODE_HISPI = 0x3, + /** CMOS */ + INPUT_MODE_CMOS = 0x4, + /** BT601 */ + INPUT_MODE_BT601 = 0x5, + /** BT656 */ + INPUT_MODE_BT656 = 0x6, + /** BT1120 */ + INPUT_MODE_BT1120 = 0x7, + /** MIPI Bypass */ + INPUT_MODE_BYPASS = 0x8, + INPUT_MODE_BUTT +} InputMode; + +/** + * @brief MIPI接收速率。 + * + * @since 1.0 + */ +typedef enum { + /** output 1 pixel per clock */ + MIPI_DATA_RATE_X1 = 0, + /** output 2 pixel per clock */ + MIPI_DATA_RATE_X2 = 1, + MIPI_DATA_RATE_BUTT +} MipiDataRate; + +/** + * @brief Mipi图像区域。 + * + * @since 1.0 + */ +typedef struct { + int x; + int y; + unsigned int width; + unsigned int height; +} ImgRect; + +/** + * @brief 传输的数据类型。 + * + * @since 1.0 + */ +typedef enum { + DATA_TYPE_RAW_8BIT = 0, + DATA_TYPE_RAW_10BIT, + DATA_TYPE_RAW_12BIT, + DATA_TYPE_RAW_14BIT, + DATA_TYPE_RAW_16BIT, + DATA_TYPE_YUV420_8BIT_NORMAL, + DATA_TYPE_YUV420_8BIT_LEGACY, + DATA_TYPE_YUV422_8BIT, + /** YUV422 8位转换用户定义16位原始数据 */ + DATA_TYPE_YUV422_PACKED, + DATA_TYPE_BUTT +} DataType; + +/** + * @brief 定义YUV和原始数据格式以及位深度。 + * + * @since 1.0 + */ +typedef struct { + uint8_t devno; + unsigned int num; + unsigned int extDataBitWidth[MAX_EXT_DATA_TYPE_NUM]; + unsigned int extDataType[MAX_EXT_DATA_TYPE_NUM]; +} ExtDataType; + +/** + * @brief MIPI D-PHY WDR模式定义。 + * + * @since 1.0 + */ +typedef enum { + HI_MIPI_WDR_MODE_NONE = 0x0, + /** Virtual Channel */ + HI_MIPI_WDR_MODE_VC = 0x1, + /** Data Type */ + HI_MIPI_WDR_MODE_DT = 0x2, + /** DOL Mode */ + HI_MIPI_WDR_MODE_DOL = 0x3, + HI_MIPI_WDR_MODE_BUTT +} MipiWdrMode; + +/** + * @brief Mipi设备属性。 + * + * @since 1.0 + */ +typedef struct { + /** 数据类型:8/10/12/14/16位 */ + DataType inputDataType; + /** MIPI WDR模式定义 */ + MipiWdrMode wdrMode; + /** 通道id: -1 - 禁用 */ + short laneId[MIPI_LANE_NUM]; + + union { + /** 由HI_MIPI_WDR_MODE_DT使用 */ + short dataType[WDR_VC_NUM]; + }; +} MipiDevAttr; + +/** + * @brief LVDS WDR模式定义。 + * + * @since 1.0 + */ +typedef enum { + HI_WDR_MODE_NONE = 0x0, + HI_WDR_MODE_2F = 0x1, + HI_WDR_MODE_3F = 0x2, + HI_WDR_MODE_4F = 0x3, + HI_WDR_MODE_DOL_2F = 0x4, + HI_WDR_MODE_DOL_3F = 0x5, + HI_WDR_MODE_DOL_4F = 0x6, + HI_WDR_MODE_BUTT +} WdrMode; + +/** + * @brief LVDS同步模式。 + * + * @since 1.0 + */ +typedef enum { + /** 传感器SOL、EOL、SOF、EOF */ + LVDS_SYNC_MODE_SOF = 0, + /** SAV, EAV */ + LVDS_SYNC_MODE_SAV, + LVDS_SYNC_MODE_BUTT +} LvdsSyncMode; + +/** + * @brief LVDS 列同步类型。 + * + * @since 1.0 + */ +typedef enum { + LVDS_VSYNC_NORMAL = 0x00, + LVDS_VSYNC_SHARE = 0x01, + LVDS_VSYNC_HCONNECT = 0x02, + LVDS_VSYNC_BUTT +} LvdsVsyncType; + +/** + * @brief LVDS-Vsync列同步参数。 + * + * @since 1.0 + */ +typedef struct { + LvdsVsyncType syncType; + + /* 当 sync_type 为 LVDS_VSYNC_HCONNECT 时,需要配置 hblank1 和 hblank2,表示 Hconnect 的消隐区长度 */ + unsigned short hblank1; + unsigned short hblank2; +} LvdsVsyncAttr; + +/** + * @brief 帧ID类型。 + * + * @since 1.0 + */ +typedef enum { + LVDS_FID_NONE = 0x00, + /** SAV 4th中的帧标识id */ + LVDS_FID_IN_SAV = 0x01, + /** 第一个数据中的帧标识id */ + LVDS_FID_IN_DATA = 0x02, + LVDS_FID_BUTT +} LvdsFidType; + +/** + * @brief 帧ID配置信息。 + * + * @since 1.0 + */ +typedef struct { + LvdsFidType fidType; + + /** 索尼DOL有帧信息线,在DOL H连接模式下, + 应将此标志配置为false以禁用输出帧信息行。 */ + unsigned char outputFil; +} LvdsFidAttr; + +/** + * @brief 位大小端模式。 + * + * @since 1.0 + */ +typedef enum { + LVDS_ENDIAN_LITTLE = 0x0, + LVDS_ENDIAN_BIG = 0x1, + LVDS_ENDIAN_BUTT +} LvdsBitEndian; + +/** + * @brief LVDS/SUBSLVDS/HiSPi设备属性。 + * + * @since 1.0 + */ +typedef struct { + /** 数据类型:8/10/12/14位 */ + DataType inputDataType; + /** 波分复用模式 */ + WdrMode wdrMode; + + /** 同步模式:SOF,SAV */ + LvdsSyncMode syncMode; + /** 正常、共享、连接 */ + LvdsVsyncAttr vsyncAttr; + /** 帧识别码 */ + LvdsFidAttr fidAttr; + + /** 数据端:小/大 */ + LvdsBitEndian dataEndian; + /** 同步代码endian:小/大 */ + LvdsBitEndian syncCodeEndian; + /** 通道id: -1 - 禁用 */ + short laneId[LVDS_LANE_NUM]; + + /** 每个vc有4个参数,syncCode[i]: + 同步模式是SYNC_MODE_SOF:SOF、EOF、SOL、EOL + 同步模式是SYNC_MODE_SAV:无效SAV、无效eav、有效SAV、有效eav */ + unsigned short syncCode[LVDS_LANE_NUM][WDR_VC_NUM][SYNC_CODE_NUM]; +} LvdsDevAttr; + +/** + * @brief 组合设备的属性。 + * 组合设备属性,由于 MIPI Rx 能够对接 CSI-2、LVDS、HiSPi 等时序,所以将 MIPI Rx 称为组合设备。 + * + * @since 1.0 + */ +typedef struct { + /** 设备号 */ + uint8_t devno; + /** 输入模式:MIPI/LVDS/SUBSLVDS/HISPI/DC */ + InputMode inputMode; + MipiDataRate dataRate; + /** MIPI Rx设备裁剪区域(与原始传感器输入图像大小相对应) */ + ImgRect imgRect; + + union { + MipiDevAttr mipiAttr; + LvdsDevAttr lvdsAttr; + }; +} ComboDevAttr; + +/** + * @brief 共模电压模式。 + * + * @since 1.0 + */ +typedef enum { + PHY_CMV_GE1200MV = 0x00, + PHY_CMV_LT1200MV = 0x01, + PHY_CMV_BUTT +} PhyCmvMode; + +/** + * @brief 获取具有指定通道ID的MIPI CSI设备句柄。 + * + * @param id 表示 MIPI CSI通道id。 + * + * @return 如果操作成功,则返回MIPI CSI设备句柄;否则返回NULL。 + * + * @since 1.0 + */ +DevHandle MipiCsiOpen(uint8_t id); + +/** + * @brief 释放MIPI CSI设备句柄。 + * + * @param handle 通过{@link MipiCsiOpen}获得的MIPI CSI设备句柄。 + * + * @since 1.0 + */ +void MipiCsiClose(DevHandle handle); + +/** + * @brief 将Mipi、CMOS或LVDS摄像机的参数设置到控制器。 + * 参数包括工作模式、图像面积、图像深度、数据速率和物理通道。 + * + * @param handle 通过{@link MipiCsiOpen}获得的MIPI CSI设备句柄。 + * @param pAttr 指向属性的指针。 + * + * @return 如果操作成功,则返回0;否则返回负值。 + * + * @since 1.0 + */ +int32_t MipiCsiSetComboDevAttr(DevHandle handle, ComboDevAttr *pAttr); + +/** + * @brief 设置共模电压模式。 + * + * @param handle 通过{@link MipiCsiOpen}获得的MIPI CSI设备句柄。 + * @param devno 总共有2个设备编号,指向0或1。 + * @param cmvMode 共模电压模式参数。 + * + * @return 如果操作成功,则返回0;否则返回负值。 + * + * @since 1.0 + */ +int32_t MipiCsiSetPhyCmvmode(DevHandle handle, uint8_t devno, PhyCmvMode cmvMode); + +/** + * @brief 复位传感器。 + * + * @param handle 通过{@link MipiCsiOpen}获得的MIPI CSI设备句柄。 + * @param snsResetSource 传感器的复位信号线号在软件中称为传感器的复位源。 + * sns是传感器的缩写。 + * + * @return 如果操作成功,则返回0;否则返回负值。 + * + * @since 1.0 + */ +int32_t MipiCsiResetSensor(DevHandle handle, uint8_t snsResetSource); + +/** + * @brief 撤销复位传感器。 + * + * @param handle 通过{@link MipiCsiOpen}获得的MIPI CSI设备句柄。 + * @param snsResetSource 传感器的复位信号线号在软件中称为传感器的复位源。 + * sns是传感器的缩写。 + * + * @return 如果操作成功,则返回0;否则返回负值。 + * + * @since 1.0 + */ +int32_t MipiCsiUnresetSensor(DevHandle handle, uint8_t snsResetSource); + +/** + * @brief 复位 MIPI RX。 + * 不同的s32WorkingViNum有不同的enSnsType。 + * + * @param handle 通过{@link MipiCsiOpen}获得的MIPI CSI设备句柄。 + * @param comboDev MIPI Rx或者SLVS 设备类型。 + * + * @return 如果操作成功,则返回0;否则返回负值。 + * + * @since 1.0 + */ +int32_t MipiCsiResetRx(DevHandle handle, uint8_t comboDev); + +/** + * @brief 未设置的MIPI RX. + * + * @param handle 通过{@link MipiCsiOpen}获得的MIPI CSI设备句柄。 + * @param comboDev MIPI Rx或者SLVS 设备类型。 + * + * @return 如果操作成功,则返回0;否则返回负值。 + * + * @since 1.0 + */ +int32_t MipiCsiUnresetRx(DevHandle handle, uint8_t comboDev); + +/** + * @brief 设置Mipi Rx的通道分布。 + * 根据硬件连接形式选择具体模式。 + * + * @param handle 通过{@link MipiCsiOpen}获得的MIPI CSI设备句柄。 + * @param laneDivideMode 通道划分模式参数。 + * + * @since 1.0 + */ +int32_t MipiCsiSetHsMode(DevHandle handle, LaneDivideMode laneDivideMode); + +/** + * @brief 使能mipi的时钟。 + * 根据上层函数电泳传递的enSnsType参数决定是用 MIPI 还是LVDS。 + * + * @param handle 通过{@link MipiCsiOpen}获得的MIPI CSI设备句柄。 + * @param comboDev MIPI接收或LVDS设备类型。 + * + * @return 如果操作成功,则返回0;否则返回负值。 + * + * @since 1.0 + */ +int32_t MipiCsiEnableClock(DevHandle handle, uint8_t comboDev); + +/** + * @brief 关闭Mipi的时钟。 + * + * @param handle 通过{@link MipiCsiOpen}获得的MIPI CSI设备句柄。 + * @param comboDev MIPI接收或LVDS设备类型。 + * + * @return 如果操作成功,则返回0;否则返回负值。 + * + * @since 1.0 + */ +int32_t MipiCsiDisableClock(DevHandle handle, uint8_t comboDev); + +/** + * @brief 启用Mipi上的传感器时钟。 + * + * @param handle 通过{@link MipiCsiOpen}获得的MIPI CSI设备句柄。 + * @param snsClkSource 传感器的时钟信号线号,在软件中称为传感器的时钟源。 + * sns是传感器的缩写。 + * + * @return 如果操作成功,则返回0;否则返回负值。 + * + * @since 1.0 + */ +int32_t MipiCsiEnableSensorClock(DevHandle handle, uint8_t snsClkSource); + +/** + * @brief 关闭传感器时钟。 + * + * @param handle 通过{@link MipiCsiOpen}获得的MIPI CSI设备句柄。 + * @param snsClkSource 传感器的时钟信号线号,在软件中称为传感器的时钟源。 + * sns是传感器的缩写。 + * + * @return 如果操作成功,则返回0;否则返回负值。 + * + * @since 1.0 + */ +int32_t MipiCsiDisableSensorClock(DevHandle handle, uint8_t snsClkSource); + +/** + * @brief 设置YUV和原始数据格式以及位深度。 + * + * @param handle 通过{@link MipiCsiOpen}获得的MIPI CSI设备句柄。 + * @param dataType 指向图像数据格式的指针。 + * + * @return 如果操作成功,则返回0;否则返回负值。 + * + * @since 1.0 + */ +int32_t MipiCsiSetExtDataType(DevHandle handle, ExtDataType* dataType); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* __cplusplus */ + +#endif /* MIPI_CSI_IF_H */ diff --git a/zh-cn/device-dev/driver/Readme-CN.md b/zh-cn/device-dev/driver/Readme-CN.md index 17116f4e45c..07b7835b944 100755 --- a/zh-cn/device-dev/driver/Readme-CN.md +++ b/zh-cn/device-dev/driver/Readme-CN.md @@ -19,6 +19,7 @@ - [SPI](driver-platform-spi-develop.md) - [UART](driver-platform-uart-develop.md) - [WatchDog](driver-platform-watchdog-develop.md) + - [MIPI_CSI](driver-platform-mipicsi-develop.md) - [平台驱动使用](driver-platform.md) - [GPIO](driver-platform-gpio-des.md) - [I2C](driver-platform-i2c-des.md) @@ -29,6 +30,7 @@ - [WATCHDOG](driver-platform-watchdog-des.md) - [MIPI DSI](driver-platform-mipidsi-des.md) - [PWM](driver-platform-pwm-des.md) + - [MIPI_CSI](driver-platform-mipicsi-des.md) - [外设驱动使用](driver-peripherals.md) - [LCD](driver-peripherals-lcd-des.md) - [TOUCHSCREEN](driver-peripherals-touch-des.md) diff --git a/zh-cn/device-dev/driver/driver-platform-mipicsi-des.md b/zh-cn/device-dev/driver/driver-platform-mipicsi-des.md new file mode 100755 index 00000000000..4c5903b4d6c --- /dev/null +++ b/zh-cn/device-dev/driver/driver-platform-mipicsi-des.md @@ -0,0 +1,777 @@ +# MIPI CSI + +- [概述](#section1_MIPI_CSIDes) + - [ComboDevAttr结构体](#section1.1_MIPI_CSIDes) + - [ExtDataType结构体](#section1.2_MIPI_CSIDes) + - [接口说明](#section1.3_MIPI_CSIDes) + +- [使用指导](#section2_MIPI_CSIDes) + - [使用流程](#section2.1_MIPI_CSIDes) + - [获取MIPI-CSI控制器操作句柄](#section2.2_MIPI_CSIDes) + - [MIPI-CSI相应配置](#section2.3_MIPI_CSIDes) + - [复位/撤销复位sensor](#section2.4_MIPI_CSIDes) + - [复位/撤销复位MIPI RX](#section2.5_MIPI_CSIDes) + - [使能/关闭MIPI的时钟](#section2.6_MIPI_CSIDes) + - [使能/关闭MIPI上的sensor时钟](#section2.7_MIPI_CSIDes) + - [释放MIPI-CSI控制器操作句柄](#section2.8_MIPI_CSIDes) +- [使用实例](#section3_MIPI_CSIDes) + +## 概述 + +- CSI(Camera Serial Interface)是由MIPI联盟下Camera工作组指定的接口标准。CSI-2是MIPI CSI第二版,主要由应用层、协议层、物理层组成,最大支持4通道数据传输、单线传输速度高达1Gb/s。 + +- 物理层支持HS(High Speed)和LP(Low Power)两种工作模式。HS模式下采用低压差分信号,功耗较大,但数据传输速率可以很高(数据速率为80M~1Gbps);LP模式下采用单端信号,数据速率很低(<10Mbps),但是相应的功耗也很低。两种模式的结合保证了MIPI总线在需要传输大量数据(如图像)时可以高速传输,而在不需要传输大数据量时又能够减少功耗。 + +- 图1显示了简化的CSI接口。D-PHY采用1对源同步的差分时钟和1~4对差分数据线来进行数据传输。数据传输采用DDR方式,即在时钟的上下边沿都有数据传输。 + + **图 1** CSI发送、接收接口 + ![](figures/CSI发送-接收接口.png) + +### ComboDevAttr结构体 + +**表** **1** ComboDevAttr结构体介绍 + + + +| 名称 | 描述 | +| --------- | ----------------------------------------------------- | +| devno | 设备号 | +| inputMode | 输入模式:MIPI/LVDS/SUBSLVDS/HISPI/DC | +| dataRate | Mipi Rx,SLVS输入速率 | +| imgRect | MIPI Rx设备裁剪区域(与原始传感器输入图像大小相对应) | +| MIPIAttr | Mipi设备属性 | +| lvdsAttr | LVDS/SubLVDS/HiSPi设备属性 | + +### ExtDataType结构体 + +**表** **2** ExtDataType结构体介绍 + + + +| 名称 | 描述 | +| --------------- | ------------------------------- | +| devno | 设备号 | +| num | sensor号 | +| extDataBitWidth | 图片的位深 | +| extDataType | 定义YUV和原始数据格式以及位深度 | + +### 接口说明 + +**表 3** MIPI-CSI API接口功能介绍 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
功能分类接口名描述
获取/释放MIPI-CSI控制器操作句柄MipiCsiOpen获取MIPI-CSI控制器操作句柄
MipiCsiClose释放MIPI-CSI控制器操作句柄
MIPI-CSI相应配置MipiCsiSetComboDevAttr设置MIPI,CMOS 或者 + LVDS相机的参数给控制器,参数包括工作模式,图像区域,图像深度,数据速率和物理通道等
MipiCsiSetExtDataType(可选)设置YUV和RAW数据格式和位深
MipiCsiSetHsMode设置MIPI RX的 Lane + 分布。根据硬件连接的形式选择具体的mode
MipiCsiSetPhyCmvmode设置共模电压模式
复位/撤销复位 sensorMipiCsiResetSensor复位 sensor
MipiCsiUnresetSensor撤销复位 sensor
复位/撤销复位 MIPI RXMipiCsiResetRx复位 MIPI + RX。不同的s32WorkingViNum有不同的enSnsType
MipiCsiUnresetRx撤销复位 MIPI RX
使能/关闭MIPI的时钟MipiCsiEnableClock使能MIPI的时钟。根据上层函数电泳传递的enSnsType参数决定是用 + MIPI 还是LVDS
MipiCsiDisableClock关闭MIPI设备的时钟
使能/禁用MIPI上的sensor时钟MipiCsiEnableSensorClock使能MIPI上的sensor时钟
MipiCsiDisableSensorClock关闭 sensor 的时钟
+ + + + +## 使用指导 + +### 使用流程 + +使用MIPI-CSI的一般流程如[图2](#fig99821771782)所示。 + +**图 2** MIPI-CSI使用流程图 + + +![](figures/MIPI-CSI使用流程图.png) + +### 获取MIPI-CSI控制器操作句柄 + +在进行MIPI-CSI进行通信前,首先要调用MipiCsiOpen获取控制器操作句柄,该函数会返回指定通道ID的控制器操作句柄。 + +```c +DevHandle MipiCsiOpen(uint8_t id); +``` + +**表 4** MipiCsiOpen的参数和返回值描述 + + + +| 参数 | 参数描述 | +| ---------- | ----------------------------------------------- | +| id | MIPI CSI通道ID | +| **返回值** | **返回值描述** | +| NULL | 获取失败 | +| 设备句柄 | 获取到指令通道的控制器操作句柄,类型为DevHandle | + +假设系统中的MIPI-CSI通道为0,获取该通道控制器操作句柄的示例如下: + +```c +DevHandle MipiCsiHandle = NULL; /* 设备句柄 */ +id = 0; /* MiPi-Csi通道ID */ + +/* 获取控制器操作句柄 */ +MipiCsiHandle = MipiCsiOpen(id); +if (MipiCsiHandle == NULL) { + HDF_LOGE("MipiCsiOpen: failed\n"); + return; +} +``` + +### MIPI-CSI相应配置 + +- 写入MIPI-CSI配置 + +```c +int32_t MipiCsiSetComboDevAttr(DevHandle handle, ComboDevAttr *pAttr); +``` + +**表 5** MipiCsiSetComboDevAttr的参数和返回值描述 + + + +| 参数 | 参数描述 | +| ---------- | -------------------------- | +| handle | 控制器操作句柄 | +| pAttr | MIPI-CSI相应配置结构体指针 | +| **返回值** | **返回值描述** | +| 0 | 设置成功 | +| 负数 | 设置失败 | + +```c +int32_t ret; +struct ComboDevAttr attr; + +/* 当前配置如下 */ +(void)memset_s(&attr, sizeof(ComboDevAttr), 0, sizeof(ComboDevAttr)); +attr.devno = 0; /* 设备0 */ +attr.inputMode = INPUT_MODE_MIPI; /* 输入模式为MIPI */ +attr.dataRate = MIPI_DATA_RATE_X1; /* 每时钟输出1像素 */ +attr.imgRect.x = 0; /* 0: 图像传感器左上位置 */ +attr.imgRect.y = 0; /* 0: 图像传感器右上位置 */ +attr.imgRect.width = 2592; /* 2592: 图像传感器宽度大小 */ +attr.imgRect.height = 1944; /* 1944: 图像传感器高度尺寸 */ +/* 写入配置数据 */ +ret = MipiCsiSetComboDevAttr(MipiCsiHandle, &attr); +if (ret != 0) { + HDF_LOGE("%s: MipiCsiSetComboDevAttr fail! ret=%d\n", __func__, ret); + return -1; +} +``` + +- 设置YUV和RAW数据格式和位深 + +```c +int32_t MipiCsiSetExtDataType(DevHandle handle, ExtDataType* dataType); +``` + +**表 6** MipiCsiSetExtDataType的参数和返回值描述 + + + +| 参数 | 参数描述 | +| ---------- | ------------------------------- | +| handle | 控制器操作句柄 | +| dataType | 定义YUV和原始数据格式以及位深度 | +| **返回值** | **返回值描述** | +| 0 | 设置成功 | +| 负数 | 设置失败 | + +```c +int32_t ret; +struct ExtDataType dataType; + +/* 配置YUV和RAW数据格式和位深参数 */ +dataType.devno = 0; /* 设备0 */ +dataType.num = 0; /* sensor 0 */ +dataType.extDataBitWidth[0] = 12; /* 位深数组元素0 */ +dataType.extDataBitWidth[1] = 12; /* 位深数组元素1 */ +dataType.extDataBitWidth[2] = 12; /* 位深数组元素2 */ + +dataType.extDataType[0] = 0x39; /* 定义YUV和原始数据格式以及位深度元素0 */ +dataType.extDataType[1] = 0x39; /* 定义YUV和原始数据格式以及位深度元素1 */ +dataType.extDataType[2] = 0x39; /* 定义YUV和原始数据格式以及位深度元素2 */ +/* 设置YUV和RAW数据格式和位深 */ +ret = MipiCsiSetExtDataType(MipiCsiHandle, &dataType); +if (ret != 0) { + HDF_LOGE("%s: MipiCsiSetExtDataType fail! ret=%d\n", __func__, ret); + return -1; +} +``` + +- 设置MIPI RX的 Lane分布 + +```c +int32_t MipiCsiSetHsMode(DevHandle handle, LaneDivideMode laneDivideMode); +``` + +**表 7** MipiCsiSetHsMode的参数和返回值描述 + + + +| 参数 | 参数描述 | +| -------------- | -------------- | +| handle | 控制器操作句柄 | +| laneDivideMode | lane模式参数 | +| **返回值** | **返回值描述** | +| 0 | 设置成功 | +| 负数 | 设置失败 | + +```c +int32_t ret; +enum LaneDivideMode mode; + +/* lane模式参数为0 */ +mode = LANE_DIVIDE_MODE_0; +/* 设置MIPI RX的 Lane分布 */ +ret = MipiCsiSetHsMode(MipiCsiHandle, mode); +if (ret != 0) { + HDF_LOGE("%s: MipiCsiSetHsMode fail! ret=%d\n", __func__, ret); + return -1; +} +``` + +- 设置共模电压模式 + +```c +int32_t MipiCsiSetPhyCmvmode(DevHandle handle, uint8_t devno, PhyCmvMode cmvMode); +``` + +**表 8** MipiCsiSetPhyCmvmode的参数和返回值描述 + + + +| 参数 | 参数描述 | +| ---------- | ---------------- | +| handle | 控制器操作句柄 | +| cmvMode | 共模电压模式参数 | +| devno | 设备编号 | +| **返回值** | **返回值描述** | +| 0 | 设置成功 | +| 负数 | 设置失败 | + +```c +int32_t ret; +enum PhyCmvMode mode; +uint8_t devno; + +/* 共模电压模式参数为0 */ +mode = PHY_CMV_GE1200MV; +/* 设备编号为0 */ +devno = 0; +/* 设置共模电压模式 */ +ret = MipiCsiSetPhyCmvmode(MipiCsiHandle, devno, mode); +if (ret != 0) { + HDF_LOGE("%s: MipiCsiSetPhyCmvmode fail! ret=%d\n", __func__, ret); + return -1; +} +``` + +### 复位/撤销复位sensor + +- 复位sensor + +```c +int32_t MipiCsiResetSensor(DevHandle handle, uint8_t snsResetSource); +``` + +**表 9** MipiCsiResetSensor的参数和返回值描述 + + + +| 参数 | 参数描述 | +| -------------- | ------------------------------------------------ | +| handle | 控制器操作句柄 | +| snsResetSource | 传感器的复位信号线号,在软件中称为传感器的复位源 | +| **返回值** | **返回值描述** | +| 0 | 复位成功 | +| 负数 | 复位失败 | + +```c +int32_t ret; +uint8_t snsResetSource; + +/* 传感器复位信号线号为0 */ +snsResetSource = 0; +/* 复位sensor */ +ret = MipiCsiResetSensor(MipiCsiHandle, snsResetSource); +if (ret != 0) { + HDF_LOGE("%s: MipiCsiResetSensor fail! ret=%d\n", __func__, ret); + return -1; +} +``` + +- 撤销复位sensor + +```c +int32_t MipiCsiUnresetSensor(DevHandle handle, uint8_t snsResetSource); +``` + +**表 10** MipiCsiUnresetSensor的参数和返回值描述 + + + +| 参数 | 参数描述 | +| -------------- | ------------------------------------------------ | +| handle | 控制器操作句柄 | +| snsResetSource | 传感器的复位信号线号,在软件中称为传感器的复位源 | +| **返回值** | **返回值描述** | +| 0 | 撤销复位成功 | +| 负数 | 撤销复位失败 | + +```c +int32_t ret; +uint8_t snsResetSource; + +/* 传感器撤销复位信号线号为0 */ +snsResetSource = 0; +/* 撤销复位sensor */ +ret = MipiCsiUnresetSensor(MipiCsiHandle, snsResetSource); +if (ret != 0) { + HDF_LOGE("%s: MipiCsiUnresetSensor fail! ret=%d\n", __func__, ret); + return -1; +} +``` + +### 复位/撤销复位MIPI RX + +- 复位MIPI RX + +```c +int32_t MipiCsiResetRx(DevHandle handle, uint8_t comboDev); +``` + +**表 11** MipiCsiResetRx的参数和返回值描述 + + + +| 参数 | 参数描述 | +| ---------- | --------------------- | +| handle | 控制器操作句柄 | +| comboDev | MIPI RX或LVDS通路序号 | +| **返回值** | **返回值描述** | +| 0 | 复位成功 | +| 负数 | 复位失败 | + +```c +int32_t ret; +uint8_t comboDev; + +/* 通路序号为0 */ +comboDev = 0; +/* 复位MIPI RX */ +ret = MipiCsiResetRx(MipiCsiHandle, comboDev); +if (ret != 0) { + HDF_LOGE("%s: MipiCsiResetRx fail! ret=%d\n", __func__, ret); + return -1; +} +``` + +- 撤销复位MIPI RX + +```c +int32_t MipiCsiUnresetRx(DevHandle handle, uint8_t comboDev); +``` + +**表 12** MipiCsiUnresetRx的参数和返回值描述 + + + +| 参数 | 参数描述 | +| ---------- | --------------------- | +| handle | 控制器操作句柄 | +| comboDev | MIPI RX或LVDS通路序号 | +| **返回值** | **返回值描述** | +| 0 | 撤销复位成功 | +| 负数 | 撤销复位失败 | + +```c +int32_t ret; +uint8_t comboDev; + +/* 通路序号为0 */ +comboDev = 0; +/* 撤销复位MIPI RX */ +ret = MipiCsiUnresetRx(MipiCsiHandle, comboDev); +if (ret != 0) { + HDF_LOGE("%s: MipiCsiUnresetRx fail! ret=%d\n", __func__, ret); + return -1; +} +``` + +### 使能/关闭MIPI的时钟 + +- 使能MIPI的时钟 + +```c +int32_t MipiCsiEnableClock(DevHandle handle, uint8_t comboDev); +``` + +**表 13** MipiCsiEnableClock的参数和返回值描述 + + + +| 参数 | 参数描述 | +| ---------- | -------------- | +| handle | 控制器操作句柄 | +| comboDev | 通路序号 | +| **返回值** | **返回值描述** | +| 0 | 使能成功 | +| 负数 | 使能失败 | + +```c +int32_t ret; +uint8_t comboDev; + +/* 通路序号为0 */ +comboDev = 0; +/* 使能MIPI的时钟 */ +ret = MipiCsiEnableClock(MipiCsiHandle, comboDev); +if (ret != 0) { + HDF_LOGE("%s: MipiCsiEnableClock fail! ret=%d\n", __func__, ret); + return -1; +} +``` + +- 关闭MIPI的时钟 + +```c +int32_t MipiCsiDisableClock(DevHandle handle, uint8_t comboDev); +``` + +**表 14** MipiCsiDisableClock的参数和返回值描述 + + + +| 参数 | 参数描述 | +| ---------- | -------------- | +| handle | 控制器操作句柄 | +| comboDev | 通路序号 | +| **返回值** | **返回值描述** | +| 0 | 关闭成功 | +| 负数 | 关闭失败 | + +```c +int32_t ret; +uint8_t comboDev; + +/* 通路序号为0 */ +comboDev = 0; +/* 关闭MIPI的时钟 */ +ret = MipiCsiDisableClock(MipiCsiHandle, comboDev); +if (ret != 0) { + HDF_LOGE("%s: MipiCsiDisableClock fail! ret=%d\n", __func__, ret); + return -1; +} +``` + +### 使能/关闭MIPI上的sensor时钟 + +- 使能MIPI上的sensor时钟 + +```c +int32_t MipiCsiEnableSensorClock(DevHandle handle, uint8_t snsClkSource); +``` + +**表 15** MipiCsiEnableSensorClock的参数和返回值描述 + + + +| 参数 | 参数描述 | +| ------------ | ------------------------------------------------ | +| handle | 控制器操作句柄 | +| snsClkSource | 传感器的时钟信号线号,在软件中称为传感器的时钟源 | +| **返回值** | **返回值描述** | +| 0 | 使能成功 | +| 负数 | 使能失败 | + +```c +int32_t ret; +uint8_t snsClkSource; + +/* 传感器的时钟信号线号为0 */ +snsClkSource = 0; +/* 使能MIPI上的sensor时钟 */ +ret = MipiCsiEnableSensorClock(MipiCsiHandle, snsClkSource); +if (ret != 0) { + HDF_LOGE("%s: MipiCsiEnableSensorClock fail! ret=%d\n", __func__, ret); + return -1; +} +``` + +- 关闭MIPI上的sensor时钟 + +```c +int32_t MipiCsiDisableSensorClock(DevHandle handle, uint8_t snsClkSource); +``` + +**表 16** MipiCsiDisableSensorClock的参数和返回值描述 + + + +| 参数 | 参数描述 | +| ------------ | ------------------------------------------------ | +| handle | 控制器操作句柄 | +| snsClkSource | 传感器的时钟信号线号,在软件中称为传感器的时钟源 | +| **返回值** | **返回值描述** | +| 0 | 关闭成功 | +| 负数 | 关闭失败 | + +```c +int32_t ret; +uint8_t snsClkSource; + +/* 传感器的时钟信号线号为0 */ +snsClkSource = 0; +/* 关闭MIPI上的sensor时钟 */ +ret = MipiCsiDisableSensorClock(MipiCsiHandle, snsClkSource); +if (ret != 0) { + HDF_LOGE("%s: MipiCsiDisableSensorClock fail! ret=%d\n", __func__, ret); + return -1; +} +``` + +### 释放MIPI-CSI控制器操作句柄 + +MIPI-CSI使用完成之后,需要释放控制器操作句柄,释放句柄的函数如下所示: + +```c +void MipiCsiClose(DevHandle handle); +``` + +该函数会释放掉由MipiCsiOpen申请的资源。 + +**表 17** MipiCsiClose的参数和返回值描述 + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

MIPI-CSI控制器操作句柄

+
+ +```c +MipiCsiClose(MIPIHandle); /* 释放掉MIPI-CSI控制器操作句柄 */ +``` + +## 使用实例 + +MIPI-CSI完整的使用示例如下所示: + +```c +#include "hdf.h" +#include "MIPI_csi_if.h" + +void PalMipiCsiTestSample(void) +{ + uint8_t id; + int32_t ret; + uint8_t comboDev; + uint8_t snsClkSource; + uint8_t devno; + enum LaneDivideMode mode; + enum PhyCmvMode mode; + struct ComboDevAttr attr; + struct ExtDataType dataType; + DevHandle MipiCsiHandle = NULL; + + /* 控制器ID号 */ + id = 0; + /* 获取控制器操作句柄 */ + MipiCsiHandle = MipiCsiOpen(id); + if (MipiCsiHandle == NULL) { + HDF_LOGE("MipiCsiOpen: failed!\n"); + return; + } + + /* lane模式参数为0 */ + mode = LANE_DIVIDE_MODE_0; + /* 设置MIPI RX的 Lane分布 */ + ret = MipiCsiSetHsMode(MipiCsiHandle, mode); + if (ret != 0) { + HDF_LOGE("%s: MipiCsiSetHsMode fail! ret=%d\n", __func__, ret); + return; + } + + /* 通路序号为0 */ + comboDev = 0; + /* 使能MIPI的时钟 */ + ret = MipiCsiEnableClock(MipiCsiHandle, comboDev); + if (ret != 0) { + HDF_LOGE("%s: MipiCsiEnableClock fail! ret=%d\n", __func__, ret); + return; + } + + /* 复位MIPI RX */ + ret = MipiCsiResetRx(MipiCsiHandle, comboDev); + if (ret != 0) { + HDF_LOGE("%s: MipiCsiResetRx fail! ret=%d\n", __func__, ret); + return; + } + + /* 传感器的时钟信号线号为0 */ + snsClkSource = 0; + /* 使能MIPI上的sensor时钟 */ + ret = MipiCsiEnableSensorClock(MipiCsiHandle, snsClkSource); + if (ret != 0) { + HDF_LOGE("%s: MipiCsiEnableSensorClock fail! ret=%d\n", __func__, ret); + return; + } + + /* 复位sensor */ + ret = MipiCsiResetSensor(MipiCsiHandle, snsResetSource); + if (ret != 0) { + HDF_LOGE("%s: MipiCsiResetSensor fail! ret=%d\n", __func__, ret); + return; + } + + /* MIPI参数配置如下 */ + (void)memset_s(&attr, sizeof(ComboDevAttr), 0, sizeof(ComboDevAttr)); + attr.devno = 0; /* 设备0 */ + attr.inputMode = INPUT_MODE_MIPI; /* 输入模式为MIPI */ + attr.dataRate = MIPI_DATA_RATE_X1; /* 每时钟输出1像素 */ + attr.imgRect.x = 0; /* 0: 图像传感器左上位置 */ + attr.imgRect.y = 0; /* 0: 图像传感器右上位置 */ + attr.imgRect.width = 2592; /* 2592: 图像传感器宽度大小 */ + attr.imgRect.height = 1944; /* 1944: 图像传感器高度尺寸 */ + /* 写入配置数据 */ + ret = MipiCsiSetComboDevAttr(MipiCsiHandle, &attr); + if (ret != 0) { + HDF_LOGE("%s: MipiCsiSetComboDevAttr fail! ret=%d\n", __func__, ret); + return; + } + + /* 共模电压模式参数为0 */ + mode = PHY_CMV_GE1200MV; + /* 设备编号为0 */ + devno = 0; + /* 设置共模电压模式 */ + ret = MipiCsiSetPhyCmvmode(MipiCsiHandle, devno, mode); + if (ret != 0) { + HDF_LOGE("%s: MipiCsiSetPhyCmvmode fail! ret=%d\n", __func__, ret); + return; + } + + /* 通路序号为0 */ + comboDev = 0; + /* 撤销复位MIPI RX */ + ret = MipiCsiUnresetRx(MipiCsiHandle, comboDev); + if (ret != 0) { + HDF_LOGE("%s: MipiCsiUnresetRx fail! ret=%d\n", __func__, ret); + return; + } + + /* 关闭MIPI的时钟 */ + ret = MipiCsiDisableClock(MipiCsiHandle, comboDev); + if (ret != 0) { + HDF_LOGE("%s: MipiCsiDisableClock fail! ret=%d\n", __func__, ret); + return; + } + + /* 传感器撤销复位信号线号为0 */ + snsResetSource = 0; + /* 撤销复位sensor */ + ret = MipiCsiUnresetSensor(MipiCsiHandle, snsResetSource); + if (ret != 0) { + HDF_LOGE("%s: MipiCsiUnresetSensor fail! ret=%d\n", __func__, ret); + return; + } + + /* 关闭MIPI上的sensor时钟 */ + ret = MipiCsiDisableSensorClock(MipiCsiHandle, snsClkSource); + if (ret != 0) { + HDF_LOGE("%s: MipiCsiDisableSensorClock fail! ret=%d\n", __func__, ret); + return; + } + + /* 释放MIPI DSI设备句柄 */ + MipiCsiClose(MipiCsiHandle); +} +``` + diff --git a/zh-cn/device-dev/driver/driver-platform-mipicsi-develop.md b/zh-cn/device-dev/driver/driver-platform-mipicsi-develop.md new file mode 100755 index 00000000000..2ce904f2f90 --- /dev/null +++ b/zh-cn/device-dev/driver/driver-platform-mipicsi-develop.md @@ -0,0 +1,312 @@ +# MIPI-CSI + +- [概述](#section1_MIPI_CSIDevelop) +- [开发步骤](#section2_MIPI_CSIDevelop) +- [开发实例](#section3_MIPI_CSIDevelop) + +## 概述 + +CSI(Camera Serial Interface)是由MIPI联盟下Camera工作组指定的接口标准。在HDF框架中,MIPI-CSI的接口适配模式采用无服务模式,用于不需要在用户态提供API的设备类型,或者没有用户态和内核区分的OS系统,MIPI-CSI的接口关联方式是DevHandle直接指向设备对象内核态地址(DevHandle是一个void类型指针)。 + +图 1 无服务模式结构图 +![image1](figures/CSI无服务模式结构图.png) + +## 开发步骤 + +MIPI-CSI模块适配的三个环节是配置属性文件、实例化驱动入、以及实例化核心层接口函数。 + +1. **实例化驱动入口:** + - 实例化HdfDriverEntry结构体成员。 + - 调用HDF_INIT将HdfDriverEntry实例化对象注册到HDF框架中。 + +2. **配置属性文件:** + + - 在device_info.hcs文件中添加deviceNode描述。 + - 【可选】添加mipicsi_config.hcs器件属性文件。 + +3. **实例化MIPICSI控制器对象:** + - 初始化MipiCsiCntlr成员。 + - 实例化MipiCsiCntlr成员MipiCsiCntlrMethod,其定义和成员**说明**见下 + +4. **驱动调试:** + - 【可选】针对新增驱动程序,建议验证驱动基本功能,例如挂载后的信息反馈,数据传输的成功与否等。 + +> ![](W:\doc\docs\zh-cn\device-dev\public_sys-resources\icon-note.gif) **说明:** +> +> MipiCsiCntlrMethod定义 +> +> ```c +> struct MipiCsiCntlrMethod { +> int32_t (*setComboDevAttr)(struct MipiCsiCntlr *cntlr, ComboDevAttr *pAttr); +> int32_t (*setPhyCmvmode)(struct MipiCsiCntlr *cntlr, uint8_t devno, PhyCmvMode cmvMode); +> int32_t (*setExtDataType)(struct MipiCsiCntlr *cntlr, ExtDataType* dataType); +> int32_t (*setHsMode)(struct MipiCsiCntlr *cntlr, LaneDivideMode laneDivideMode); +> int32_t (*enableClock)(struct MipiCsiCntlr *cntlr, uint8_t comboDev); +> int32_t (*disableClock)(struct MipiCsiCntlr *cntlr, uint8_t comboDev); +> int32_t (*resetRx)(struct MipiCsiCntlr *cntlr, uint8_t comboDev); +> int32_t (*unresetRx)(struct MipiCsiCntlr *cntlr, uint8_t comboDev); +> int32_t (*enableSensorClock)(struct MipiCsiCntlr *cntlr, uint8_t snsClkSource); +> int32_t (*disableSensorClock)(struct MipiCsiCntlr *cntlr, uint8_t snsClkSource); +> int32_t (*resetSensor)(struct MipiCsiCntlr *cntlr, uint8_t snsResetSource); +> int32_t (*unresetSensor)(struct MipiCsiCntlr *cntlr, uint8_t snsResetSource); +> }; +> ``` +> +> 表1 MipiCsiCntlrMethod成员的回调函数功能说明 +> +> | 成员函数 | 入参 | 出参 | 返回状态 | 功能 | +> | ------------------ | ------------------------------------------------------------ | ---- | ------------------ | -------------------------- | +> | setComboDevAttr | **cntlr**: 结构体指针,MipiCsi控制器 ;
**pAttr**: 结构体指针,MIPI-CSI相应配置结构体指针 | 无 | HDF_STATUS相关状态 | 写入MIPI-CSI配置 | +> | setPhyCmvmode | **cntlr**: 结构体指针,MipiCsi控制器 ;
**devno**: uint8_t,设备编号;
**cmvMode**: 枚举类型,共模电压模式参数 | 无 | HDF_STATUS相关状态 | 设置共模电压模式 | +> | setExtDataType | **cntlr**: 结构体指针,MipiCsi控制器 ;
**dataType**: 结构体指针,定义YUV和原始数据格式以及位深度 | 无 | HDF_STATUS相关状态 | 设置YUV和RAW数据格式和位深 | +> | setHsMode | **cntlr**: 结构体指针,MipiCsi控制器 ;
**laneDivideMode**: 枚举类型,lane模式参数 | 无 | HDF_STATUS相关状态 | 设置MIPI RX的 Lane分布 | +> | enableClock | **cntlr**: 结构体指针,MipiCsi控制器 ;
**comboDev**: uint8_t,通路序号 | 无 | HDF_STATUS相关状态 | 使能mipi的时钟 | +> | disableClock | **cntlr**: 结构体指针,MipiCsi控制器 ;
**comboDev**: uint8_t,通路序号 | 无 | HDF_STATUS相关状态 | 关闭mipi的时钟 | +> | resetRx | **cntlr**: 结构体指针,MipiCsi控制器 ;
**comboDev**: uint8_t,通路序号 | 无 | HDF_STATUS相关状态 | 复位MIPI RX | +> | unresetRx | **cntlr**: 结构体指针,MipiCsi控制器 ;
**comboDev**: uint8_t,通路序号 | 无 | HDF_STATUS相关状态 | 撤销复位MIPI RX | +> | enableSensorClock | **cntlr**: 结构体指针,MipiCsi控制器 ;
**snsClkSource**: uint8_t,传感器的时钟信号线号 | 无 | HDF_STATUS相关状态 | 使能mipi上的sensor时钟 | +> | disableSensorClock | **cntlr**: 结构体指针,MipiCsi控制器 ;
**snsClkSource**: uint8_t,传感器的时钟信号线号 | 无 | HDF_STATUS相关状态 | 关闭mipi上的sensor时钟 | +> | resetSensor | **cntlr**: 结构体指针,MipiCsi控制器 ;
**snsClkSource**: uint8_t,传感器的时钟信号线号 | 无 | HDF_STATUS相关状态 | 复位sensor | +> | unresetSensor | **cntlr**: 结构体指针,MipiCsi控制器 ;
**snsClkSource**: uint8_t,传感器的时钟信号线号 | 无 | HDF_STATUS相关状态 | 撤销复位sensor | + +## 开发实例 + +下方将以mipi_rx_hi35xx.c为示例,展示需要厂商提供哪些内容来完整实现设备功能。 + + +1. 一般来说,驱动开发首先需要在 busxx_config.hcs 中配置器件属性,并在device_info.hcs文件中添加deviceNode描述。器件属性值与核心层MipiCsiCntlr 成员的默认值或限制范围有密切关系,deviceNode信息与驱动入口注册相关。 + + **本例中MIPI控制器自身属性在源文件文件中,如有厂商需要,则在device_info文件的deviceNode增加deviceMatchAttr信息,相应增加mipicsi_config.hcs文件**。 + +- device_info.hcs 配置参考 + + ```c + root { + device_info { + match_attr = "hdf_manager"; + platform :: host { + hostName = "platform_host"; + priority = 50; + device_mipi_csi:: device { + device0 :: deviceNode { + policy = 0; + priority = 160; + permission = 0644; + moduleName = "HDF_MIPI_RX"; //【必要】用于指定驱动名称,需要与期望的驱动Entry中的moduleName一致; + serviceName = "HDF_MIPI_RX"; //【必要且唯一】驱动对外发布服务的名称 + } + } + } + } + } + ``` + +2. 完成器件属性文件的配置之后,下一步请实例化驱动入口,驱动入口必须为HdfDriverEntry(在 hdf_device_desc.h 中定义)类型的全局变量,且moduleName要和device_info.hcs中保持一致。HdfDriverEntry结构体的函数指针成员会被厂商操作函数填充,HDF框架会将所有加载的驱动的HdfDriverEntry对象首地址汇总,形成一个类似数组,方便调用。 + + 一般在加载驱动时HDF框架会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。 + +- MIPI-CSI驱动入口参考 + + ```c + struct HdfDriverEntry g_mipiCsiDriverEntry = { + .moduleVersion = 1, + .Init = Hi35xxMipiCsiInit, //见Init参考 + .Release = Hi35xxMipiCsiRelease, //见Release参考 + .moduleName = "HDF_MIPI_RX", //【必要】需要与device_info.hcs 中保持一致。 + }; + HDF_INIT(g_mipiCsiDriverEntry); //调用HDF_INIT将驱动入口注册到HDF框架中 + ``` + +3. 完成驱动入口注册之后,最后一步就是以核心层MipiCsiCntlr对象的初始化为核心,实现HdfDriverEntry成员函数(Bind,Init,Release)。MipiCsiCntlr对象的初始化包括厂商自定义结构体(用于传递参数和数据)和实例化MipiCsiCntlr成员MipiCsiCntlrMethod(让用户可以通过接口来调用驱动底层函数)。 + +- 自定义结构体参考 + + > 从驱动的角度看,自定义结构体是参数和数据的载体,一般来说,config文件中的数值也会用来初始化结构体成员,本例的mipicsi器件属性在源文件中,故基本成员结构与MipiCsiCntlr无太大差异。 + + ```c + typedef struct { + /** 数据类型:8/10/12/14/16位 */ + DataType inputDataType; + /** MIPI波分复用模式 */ + MipiWdrMode wdrMode; + /** laneId: -1 - 禁用 */ + short laneId[MIPI_LANE_NUM]; + + union { + /** 用于 HI_MIPI_WDR_MODE_DT */ + short dataType[WDR_VC_NUM]; + }; + } MipiDevAttr; + + typedef struct { + /** 设备号 */ + uint8_t devno; + /** 输入模式: MIPI/LVDS/SUBLVDS/HISPI/DC */ + InputMode inputMode; + MipiDataRate dataRate; + /** MIPI Rx设备裁剪区域(与原始传感器输入图像大小相对应) */ + ImgRect imgRect; + + union { + MipiDevAttr mipiAttr; + LvdsDevAttr lvdsAttr; + }; + } ComboDevAttr; + + //MipiCsiCntlr是核心层控制器结构体,其中的成员在Init函数中会被赋值 + struct MipiCsiCntlr { + /** 当驱动程序绑定到HDF框架时,将发送此控制器提供的服务 */ + struct IDeviceIoService service; + /** 当驱动程序绑定到HDF框架时,将传入设备端指针 */ + struct HdfDeviceObject *device; + /** 设备号 */ + unsigned int devNo; + /** 控制器提供的所有接口 */ + struct MipiCsiCntlrMethod *ops; + /** 对于控制器调试的所有接口,如果未实现驱动程序,则需要null */ + struct MipiCsiCntlrDebugMethod *debugs; + /** 控制器上下文参数变量 */ + MipiDevCtx ctx; + /** 访问控制器上下文参数变量时锁定 */ + OsalSpinlock ctxLock; + /** 操作控制器时锁定方法 */ + struct OsalMutex lock; + /** 匿名数据指针,用于存储csi设备结构 */ + void *priv; + }; + ``` + +- **【重要】** MipiCsiCntlr成员回调函数结构体MipiCsiCntlrMethod的实例化,其他成员在Init函数中初始化。 + + ```c + static struct MipiCsiCntlrMethod g_method = { + .setComboDevAttr = Hi35xxSetComboDevAttr, + .setPhyCmvmode = Hi35xxSetPhyCmvmode, + .setExtDataType = Hi35xxSetExtDataType, + .setHsMode = Hi35xxSetHsMode, + .enableClock = Hi35xxEnableClock, + .disableClock = Hi35xxDisableClock, + .resetRx = Hi35xxResetRx, + .unresetRx = Hi35xxUnresetRx, + .enableSensorClock = Hi35xxEnableSensorClock, + .disableSensorClock = Hi35xxDisableSensorClock, + .resetSensor = Hi35xxResetSensor, + .unresetSensor = Hi35xxUnresetSensor + }; + ``` + +- **Init函数参考** + + > **入参:** + > HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息 + > + > **返回值:** + > HDF_STATUS相关状态 (下表为部分展示,如需使用其他状态,可见//drivers/framework/include/utils/hdf_base.h中HDF_STATUS 定义) + > + > | 状态(值) | 问题描述 | + > | :--------------------- | :----------: | + > | HDF_ERR_INVALID_OBJECT | 无效对象 | + > | HDF_ERR_MALLOC_FAIL | 内存分配失败 | + > | HDF_ERR_INVALID_PARAM | 无效参数 | + > | HDF_ERR_IO | I/O 错误 | + > | HDF_SUCCESS | 执行成功 | + > | HDF_FAILURE | 执行失败 | + > + > **函数说明:** + > MipiCsiCntlrMethod的实例化对象的挂载,调用MipiCsiRegisterCntlr,以及其他厂商自定义初始化操作。 + + ```c + static int32_t Hi35xxMipiCsiInit(struct HdfDeviceObject *device) + { + int32_t ret; + + HDF_LOGI("%s: enter!", __func__); + g_mipiCsi.priv = NULL; //g_mipiTx是定义的全局变量 + //static struct MipiCsiCntlr g_mipiCsi = { + //.devNo = 0 + //}; + g_mipiCsi.ops = &g_method; //MipiCsiCntlrMethod的实例化对象的挂载 + #ifdef CONFIG_HI_PROC_SHOW_SUPPORT + g_mipiCsi.debugs = &g_debugMethod; + #endif + ret = MipiCsiRegisterCntlr(&g_mipiCsi, device); //【必要】调用核心层函数和g_mipiTx初始化核心层全局变量 + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: [MipiCsiRegisterCntlr] failed!", __func__); + return ret; + } + + ret = MipiRxDrvInit(); //【必要】厂商对设备的初始化,形式不限 + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: [MipiRxDrvInit] failed.", __func__); + return ret; + } + #ifdef MIPICSI_VFS_SUPPORT + ret = MipiCsiDevModuleInit(g_mipiCsi.devNo); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: [MipiCsiDevModuleInit] failed!", __func__); + return ret; + } + #endif + + OsalSpinInit(&g_mipiCsi.ctxLock); + HDF_LOGI("%s: load mipi csi driver success!", __func__); + + return ret; + } + + //mipi_dsi_core.c核心层 + int32_t MipiCsiRegisterCntlr(struct MipiCsiCntlr *cntlr, struct HdfDeviceObject *device) + { + ... + //定义的全局变量:static struct MipiCsiHandle g_mipiCsihandle[MAX_CNTLR_CNT]; + if (g_mipiCsihandle[cntlr->devNo].cntlr == NULL) { + (void)OsalMutexInit(&g_mipiCsihandle[cntlr->devNo].lock); + (void)OsalMutexInit(&(cntlr->lock)); + + g_mipiCsihandle[cntlr->devNo].cntlr = cntlr; //初始化MipiCsiHandle成员 + g_mipiCsihandle[cntlr->devNo].priv = NULL; + cntlr->device = device; //使HdfDeviceObject与MipiCsiHandle可以相互转化的前提 + device->service = &(cntlr->service); //使HdfDeviceObject与MipiCsiHandle可以相互转化的前提 + cntlr->priv = NULL; + HDF_LOGI("%s: success.", __func__); + + return HDF_SUCCESS; + } + + HDF_LOGE("%s: cntlr already exists.", __func__); + return HDF_FAILURE; + } + ``` + +- **Release函数参考** + + > **入参:** + > HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息。 + > + > **返回值:** + > 无 + > + > **函数说明:** + > 该函数需要在驱动入口结构体中赋值给Release接口,当HDF框架调用Init函数初始化驱动失败时,可以调用Release释放驱动资源,该函数中需包含释放内存和删除控制器等操作。所有强制转换获取相应对象的操作**前提**是在Init函数中具备对应赋值的操作。 + + ```c + static void Hi35xxMipiCsiRelease(struct HdfDeviceObject *device) + { + struct MipiCsiCntlr *cntlr = NULL; + ... + cntlr = MipiCsiCntlrFromDevice(device); //这里有HdfDeviceObject到MipiCsiCntlr的强制转化 + //return (device == NULL) ? NULL : (struct MipiCsiCntlr *)device->service; + ... + + OsalSpinDestroy(&cntlr->ctxLock); + #ifdef MIPICSI_VFS_SUPPORT + MipiCsiDevModuleExit(cntlr->devNo); + #endif + MipiRxDrvExit(); //【必要】对厂商设备所占资源的释放 + MipiCsiUnregisterCntlr(&g_mipiCsi); //空函数 + g_mipiCsi.priv = NULL; + + HDF_LOGI("%s: unload mipi csi driver success!", __func__); + } + ``` + diff --git a/zh-cn/device-dev/driver/driver-platform-mipidsi-des.md b/zh-cn/device-dev/driver/driver-platform-mipidsi-des.md index 3e8de1b4db8..6be428a3027 100644 --- a/zh-cn/device-dev/driver/driver-platform-mipidsi-des.md +++ b/zh-cn/device-dev/driver/driver-platform-mipidsi-des.md @@ -96,7 +96,7 @@ 使用MIPI-DSI的一般流程如[图2](#fig129103491241)所示。 **图 2** MIPI-DSI使用流程图 -![](figures/MIPI-DSI使用流程图.png "MIPI-DSI使用流程图") +![](figures/MIPI-DSI使用流程图.png) ### 获取MIPI-DSI操作句柄 @@ -213,7 +213,7 @@ cfg.timingInfo.vsaLines = 76; cfg.timingInfo.vfpLines = 120; cfg.timingInfo.xResPixels = 1342; /* 写入配置数据 */ -ret = MipiDsiSetCfg(g_handle, &cfg); +ret = MipiDsiSetCfg(mipiDsiHandle, &cfg); if (ret != 0) { HDF_LOGE("%s: SetMipiCfg fail! ret=%d\n", __func__, ret); return -1; @@ -265,7 +265,7 @@ int32\_t MipiDsiGetCfg\(DevHandle handle, struct MipiCfg \*cfg\); int32_t ret; struct MipiCfg cfg; memset(&cfg, 0, sizeof(struct MipiCfg)); -ret = MipiDsiGetCfg(g_handle, &cfg); +ret = MipiDsiGetCfg(mipiDsiHandle, &cfg); if (ret != HDF_SUCCESS) { HDF_LOGE("%s: GetMipiCfg fail!\n", __func__); return HDF_FAILURE; @@ -409,9 +409,9 @@ if (cmdRead->payload == NULL) { return HDF_FAILURE; } *(cmdRead->payload) = DDIC_REG_STATUS; -MipiDsiSetLpMode(g_handle); -ret = MipiDsiRx(g_handle, cmdRead, sizeof(readVal), &readVal); -MipiDsiSetHsMode(g_handle); +MipiDsiSetLpMode(mipiDsiHandle); +ret = MipiDsiRx(mipiDsiHandle, cmdRead, sizeof(readVal), &readVal); +MipiDsiSetHsMode(mipiDsiHandle); if (ret != HDF_SUCCESS) { HDF_LOGE("%s: MipiDsiRx fail! ret=%d\n", __func__, ret); HdfFree(cmdRead->payload); @@ -463,13 +463,13 @@ void PalMipiDsiTestSample(void) { uint8_t chnId; int32_t ret; - DevHandle handle = NULL; + DevHandle mipiDsiHandle = NULL; /* 设备通道编号 */ chnId = 0; /* 获取操作句柄 */ - handle = MipiDsiOpen(chnId); - if (handle == NULL) { + mipiDsiHandle = MipiDsiOpen(chnId); + if (mipiDsiHandle == NULL) { HDF_LOGE("MipiDsiOpen: failed!\n"); return; } @@ -490,7 +490,7 @@ void PalMipiDsiTestSample(void) cfg.timingInfo.vfpLines = 120; cfg.timingInfo.xResPixels = 1342; /* 写入配置数据 */ - ret = MipiDsiSetCfg(g_handle, &cfg); + ret = MipiDsiSetCfg(mipiDsiHandle, &cfg); if (ret != 0) { HDF_LOGE("%s: SetMipiCfg fail! ret=%d\n", __func__, ret); return; @@ -533,9 +533,9 @@ void PalMipiDsiTestSample(void) return; } *(cmdRead->payload) = DDIC_REG_STATUS; - MipiDsiSetLpMode(g_handle); - ret = MipiDsiRx(g_handle, cmdRead, sizeof(readVal), &readVal); - MipiDsiSetHsMode(g_handle); + MipiDsiSetLpMode(mipiDsiHandle); + ret = MipiDsiRx(mipiDsiHandle, cmdRead, sizeof(readVal), &readVal); + MipiDsiSetHsMode(mipiDsiHandle); if (ret != HDF_SUCCESS) { HDF_LOGE("%s: MipiDsiRx fail! ret=%d\n", __func__, ret); HdfFree(cmdRead->payload); diff --git a/zh-cn/device-dev/driver/driver-platform-pwm-des.md b/zh-cn/device-dev/driver/driver-platform-pwm-des.md index 80d67a89dc0..b6679b4739f 100644 --- a/zh-cn/device-dev/driver/driver-platform-pwm-des.md +++ b/zh-cn/device-dev/driver/driver-platform-pwm-des.md @@ -1,579 +1,477 @@ -# PWM - -- [概述](#section1043395117296) -- [接口说明](#section3939192652418) -- [使用指导](#section435718267334) - - [使用流程](#section113655616347) - - [获取PWM设备句柄](#section17816586359) - - [设置PWM周期](#section920214812397) - - [设置PWM占空比](#section519712820405) - - [设置PWM极性](#section12383334115) - - [使能PWM](#section382684811414) - - [禁用PWM](#section16545114404218) - - [获取PWM设备配置信息](#section117101243144311) - - [设置PWM设备配置信息](#section13834163604414) - - [释放PWM设备句柄](#section12987111511450) - -- [使用实例](#section138636719469) - -## 概述 - -PWM是脉冲宽度调制(Pulse Width Modulation)的缩写,是一种对模拟信号电平进行数字编码并将其转换为脉冲的技术。常用于马达控制、背光亮度调节等。 - -PWM接口定义了操作PWM设备的通用方法集合,包括: - -- PWM设备句柄获取和释放。 -- PWM周期、占空比、极性的设置。 -- PWM使能和关闭。 -- PWM配置信息的获取和设置 - -## 接口说明 - -**表 1** PWM驱动API接口功能介绍 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

功能分类

-

接口名

-

描述

-

PWM设备句柄获取和释放

-

PwmOpen

-

获取PWM设备句柄

-

PwmClose

-

释放PWM设备句柄

-

PWM周期、占空比、极性的设置

-

PwmSetPeriod

-

设置PWM周期

-

PwmSetDuty

-

设置PWM占空比

-

PwmSetPolarity

-

设置PWM极性

-

PWM使能和关闭

-

PwmEnable

-

使能PWM

-

PwmDisable

-

禁用PWM

-

PWM配置信息的获取和设置

-

-

PwmSetConfig

-

设置PWM设备配置信息

-

PwmGetConfig

-

获取PWM设备配置信息

-
- ->![](../public_sys-resources/icon-note.gif) **说明:** ->本文涉及的所有接口,仅限内核态使用,不支持在用户态使用。 - -## 使用指导 - -### 使用流程 - -使用PWM的一般流程如[图1](#fig23885455594)所示。 - -**图 1** PWM使用流程图 - - -![](figures/zh-cn_image_0000001206372673.png) - -### 获取PWM设备句柄 +# PWM + +- [概述](#section1_PWM_des) + - [PwmConfig结构体](#section1.1_PWM_des) +- [接口说明](#section2_PWM_des) +- [使用指导](#section3_PWM_des) + - [使用流程](#section3.1_PWM_des) + - [获取PWM设备句柄](#section3.2_PWM_des) + - [销毁PWM设备句柄](#section3.3_PWM_des) + - [使能](#section3.4_PWM_des) + - [禁用](#section3.5_PWM_des) + - [设置PWM设备周期](#section3.6_PWM_des) + - [设置PWM设备占空时间](#section3.7_PWM_des) + - [设置PWM设备极性](#section3.8_PWM_des) + - [设置PWM设备参数](#section3.9_PWM_des) + - [获取PWM设备参数](#section3.10_PWM_des) + +- [使用实例](#section3_PWM_des) + +## 概述 + +- PWM是脉冲宽度调制(Pulse Width Modulation)的缩写,是一种对模拟信号电平进行数字编码,转换为脉冲的一种技术。常用于马达控制、背光亮度调节等。 + +- PWM接口定义了操作PWM设备的通用方法集合,包括: + - PWM设备句柄获取和销毁。 + - PWM周期、占空比、极性的设置。 + - PWM使能和关闭。 + - PWM配置信息的获取和设置 + +### PwmConfig结构体 + +**表1** PwmConfig结构体介绍 + + + +| 名称 | 描述 | +| -------- | ------------------------------------------------------------ | +| duty | 占空时间,以纳秒为单位 | +| period | PWM周期,以纳秒为单位 | +| number | 要生成的方波数。正值表示将生成指定数量的方波,0表示方波将不断产生 | +| polarity | 极性:正极性/反极性 | +| status | 状态:启用状态/禁用状态 | + +## 接口说明 + +**表2** PWM设备API接口功能介绍 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
功能分类接口名描述
PWM句柄操作PwmOpen获取PWM设备驱动句柄
PwmClose释放PWM设备驱动句柄
使能/禁用PWMPwmEnable使能PWM
PwmDisable禁用PWM
PWM配置操作PwmSetPeriod设置PWM周期
PwmSetDuty设置PWM占空时间
PwmSetPolarity设置PWM极性
设置/获取PWM配置信息PwmSetConfig设置PWM设备参数
PwmGetConfig获取PWM设备参数
+ + + +>![](W:\doc\docs\zh-cn\device-dev\public_sys-resources\icon-note.gif) **说明:** +>PWM当前仅限内核态使用,不支持在用户态使用。 + +## 使用指导 + +### 使用流程 + +在操作系统启动过程中,驱动管理模块根据配置文件加载PWM驱动,PWM驱动会检测PWM器件并初始化驱动。 + +使用PWM设备的一般流程如[图1](#fig1_PWM_des)所示。 + +**图 1** PWM设备使用流程图 + + +![](figures/PWM设备使用流程图.png) + +### 获取PWM设备句柄 在操作PWM设备时,首先要调用PwmOpen获取PWM设备句柄,该函数会返回指定设备号的PWM设备句柄。 -DevHandle PwmOpen\(uint32\_t num\); - -**表 2** PwmOpen参数和返回值描述 - - - - - - - - - - - - - - - - - - -

参数

-

参数描述

-

num

-

PWM设备号

-

返回值

-

返回值描述

-

NULL

-

获取PWM设备句柄失败

-

设备句柄

-

对应的PWM设备句柄

-
- -假设系统中的PWM设备号为0,获取该PWM设备句柄的示例如下: - +```c +DevHandle PwmOpen(uint32_t num); ``` + +**表3** PwmOpen参数和返回值描述 + + + +| 参数 | 参数描述 | +| ---------- | ----------------------- | +| void | NA | +| num | PWM设备编号 | +| **返回值** | **返回值描述** | +| handle | 获取成功返回PWM设备句柄 | +| NULL | 获取失败 | + + +```c uint32_t num = 0; /* PWM设备号 */ -DevHandle pwm = NULL; /* PWM设备句柄 / +DevHandle handle = NULL; /* 获取PWM设备句柄 */ -pwm = PwmOpen(num); -if (pwm == NULL) { - HDF_LOGE("PwmOpen: pwm%d failed", num); - return; +handle = PwmOpen(num); +if (handle == NULL) { + /* 错误处理 */ } ``` -### 设置PWM周期 - -int32\_t PwmSetPeriod\(DevHandle handle, uint32\_t period\); - -**表 3** PwmSetPeriod参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - -

参数

-

参数描述

-

handle

-

PWM设备句柄

-

period

-

周期,单位纳秒

-

返回值

-

返回值描述

-

0

-

设置周期成功

-

负数

-

设置周期失败

-
+### 销毁PWM设备句柄 + +关闭PWM设备,系统释放对应的资源。 +```c +void PwmClose(DevHandle handle); ``` -int32_t ret; -uint32_t period = 1000; /* 周期1000纳秒 */ -ret = PwmSetPeriod(pwm, period); /* 设置PWM周期 */ -if (ret != 0) { - HDF_LOGE("PwmSetPeriod: failed, ret %d", ret); -} + +**表4** PwmClose参数描述 + + + +| 参数 | 参数描述 | +| ------ | ----------- | +| handle | PWM设备句柄 | + + +```c +/* 销毁PWM设备句柄 */ +PwmClose(handle); ``` -### 设置PWM占空比 - -int32\_t PwmSetDuty\(DevHandle handle, uint32\_t duty\); - -**表 4** PwmSetDuty参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - -

参数

-

参数描述

-

handle

-

PWM设备句柄

-

duty

-

占空比,单位纳秒

-

返回值

-

返回值描述

-

0

-

设置占空比成功

-

负数

-

设置占空比失败

-
+### 使能 + +启用PWM设备。 +```c +int32_t PwmEnable(DevHandle handle); ``` + +**表5** PwmEnable参数描述 + + + +| 参数 | 参数描述 | +| ---------- | -------------- | +| handle | PWM设备句柄 | +| **返回值** | **返回值描述** | +| 0 | 使能成功 | +| 负数 | 使能失败 | + +```c int32_t ret; -uint32_t duty = 500; /* 占空比500纳秒 */ -ret = PwmSetDuty(pwm, duty); /* 设置PWM占空比 */ + +/*启用PWM设备*/ +ret = PwmEnable(handle); if (ret != 0) { - HDF_LOGE("PwmSetDuty: failed, ret %d", ret); + /*错误处理*/ } ``` -### 设置PWM极性 - -int32\_t PwmSetPolarity\(DevHandle handle, uint8\_t polarity\); - -**表 5** PwmSetPolarity参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - -

参数

-

参数描述

-

handle

-

PWM设备句柄

-

polarity

-

极性,PWM_NORMAL_POLARITY为正常极性,PWM_INVERTED_POLARITY为反转极性。

-

返回值

-

返回值描述

-

0

-

设置极性成功

-

负数

-

设置极性失败

-
+### 禁用 +禁用PWM设备。 + +```c +int32_t PwmDisable(DevHandle handle); ``` + +**表6** PwmDisable参数描述 + + + +| 参数 | 参数描述 | +| ---------- | -------------- | +| handle | PWM设备句柄 | +| **返回值** | **返回值描述** | +| 0 | 禁用成功 | +| 负数 | 禁用失败 | + +```c int32_t ret; -uint8_t polarity = PWM_INVERTED_POLARITY; /* 反转极性 */ -ret = PwmSetPolarity(pwm, polarity); /* 设置PWM反转极性 */ + +/*禁用PWM设备*/ +ret = PwmDisable(handle); if (ret != 0) { - HDF_LOGE("PwmSetPolarity: failed, ret %d", ret); + /*错误处理*/ } ``` -### 使能PWM - -int32\_t PwmEnable\(DevHandle handle\); - -**表 6** PwmEnable参数和返回值描述 - - - - - - - - - - - - - - - - - - -

参数

-

参数描述

-

handle

-

PWM设备句柄

-

返回值

-

返回值描述

-

0

-

使能PWM成功

-

负数

-

使能PWM失败

-
+### 设置PWM设备周期 +设置PWM设备周期。 + +```c +int32_t PwmSetPeriod(DevHandle handle, uint32_t period); ``` + +**表7** PwmSetPeriod参数描述 + + + +| 参数 | 参数描述 | +| ---------- | ------------------------ | +| handle | PWM设备句柄 | +| period | 要设置的周期,单位为纳秒 | +| **返回值** | **返回值描述** | +| 0 | 设置成功 | +| 负数 | 设置失败 | + +```c int32_t ret; -ret = PwmEnable(pwm); /* 使能PWM */ + +/*设置周期为50000000纳秒*/ +ret = PwmSetPeriod(handle, 50000000); if (ret != 0) { - HDF_LOGE("PwmEnable: failed, ret %d", ret); + /*错误处理*/ } ``` +### 设置PWM设备占空时间 -### 禁用PWM - -int32\_t PwmDisable\(DevHandle handle\); - -**表 7** PwmDisable参数和返回值描述 - - - - - - - - - - - - - - - - - - -

参数

-

参数描述

-

handle

-

PWM设备句柄

-

返回值

-

返回值描述

-

0

-

关闭PWM成功

-

负数

-

关闭PWM失败

-
+设置PWM设备占空时间。 +```c +int32_t PwmSetDuty(DevHandle handle, uint32_t duty); ``` + +**表8** PwmSetDuty参数描述 + + + +| 参数 | 参数描述 | +| ---------- | ---------------------------- | +| handle | PWM设备句柄 | +| duty | 要设置的占空时间,单位为纳秒 | +| **返回值** | **返回值描述** | +| 0 | 设置成功 | +| 负数 | 设置失败 | + +```c int32_t ret; -ret = PwmDisable(pwm); /* 禁用PWM */ + +/*设置占空时间为25000000纳秒*/ +ret = PwmSetDuty(handle, 25000000); if (ret != 0) { - HDF_LOGE("PwmDisable: failed, ret %d", ret); + /*错误处理*/ } ``` +### 设置PWM设备极性 -### 获取PWM设备配置信息 - -int32\_t PwmGetConfig\(DevHandle handle, struct PwmConfig \*config\); - -**表 8** PwmGetConfig参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - -

参数

-

参数描述

-

handle

-

PWM设备句柄

-

config

-

PWM设备配置信息

-

返回值

-

返回值描述

-

0

-

获取配置成功

-

负数

-

获取配置失败

-
+设置PWM设备极性。 +```c +int32_t PwmSetPolarity(DevHandle handle, uint8_t polarity); ``` + +**表9** PwmSetPolarity参数描述 + + + +| 参数 | 参数描述 | +| ---------- | ------------------- | +| handle | PWM设备句柄 | +| polarity | 要设置的极性,正/反 | +| **返回值** | **返回值描述** | +| 0 | 设置成功 | +| 负数 | 设置失败 | + +```c int32_t ret; -struct PwmConfig config= {0}; /* PWM配置信息 */ -ret = PwmGetConfig(pwm, &config); /* 获取PWM设备配置信息 */ + +/*设置极性为反*/ +ret = PwmSetPolarity(handle, PWM_INVERTED_POLARITY); if (ret != 0) { - HDF_LOGE("PwmGetConfig: failed, ret %d", ret); + /*错误处理*/ } ``` -### 设置PWM设备配置信息 - -int32\_t PwmSetConfig\(DevHandle handle, struct PwmConfig \*config\); - -**表 9** PwmSetConfig参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - -

参数

-

参数描述

-

handle

-

PWM设备句柄

-

config

-

PWM设备配置信息

-

返回值

-

返回值描述

-

0

-

设置配置成功

-

负数

-

设置配置失败

-
+### 设置PWM设备参数 + +设置PWM设备参数。 + +```c +int32_t PwmSetConfig(DevHandle handle, struct PwmConfig *config); ``` + +**表10** PwmSetConfig参数描述 + + + +| 参数 | 参数描述 | +| ---------- | -------------- | +| handle | PWM设备句柄 | +| *config | 参数指针 | +| **返回值** | **返回值描述** | +| 0 | 设置成功 | +| 负数 | 设置失败 | + +```c int32_t ret; -struct PwmConfig config= {0}; /* PWM配置信息 */ -config.duty = 500; /* 占空比500纳秒 */ -config.period = 1000; /* 周期1000纳秒 */ -config.number = 0; /* 一直输出方波 */ -config.polarity = PWM_NORMAL_POLARITY; /* 正常极性 */ -ret = PwmSetConfig(pwm, &config); /* 设置PWM设备配置信息 */ +struct PwmConfig pcfg; +pcfg.duty = 25000000; /*占空时间为25000000纳秒*/ +pcfg.period = 50000000; /*周期为50000000纳秒*/ +pcfg.number = 0; /*不断产生方波*/ +pcfg.polarity = PWM_INVERTED_POLARITY; /*极性为反*/ +pcfg.status = PWM_ENABLE_STATUS; /*运行状态为启用*/ + +/*设置PWM设备参数*/ +ret = PwmSetConfig(handle, &pcfg); if (ret != 0) { - HDF_LOGE("PwmSetConfig: failed, ret %d\n", ret); + /*错误处理*/ } ``` -### 释放PWM设备句柄 +### 获取PWM设备参数 -void PwmClose\(DevHandle handle\); +获取PWM设备参数。 -该函数会释放掉由PwmClose申请的资源。 +```c +int32_t PwmGetConfig(DevHandle handle, struct PwmConfig *config); +``` -**表 10** PwmClose参数描述 +**表11** PwmGetConfig参数描述 - - - - - - - - -

参数

-

参数描述

-

handle

-

PWM设备句柄

-
+ -``` -PwmClose(pwm); /* 释放PWM设备句柄 */ +| 参数 | 参数描述 | +| ---------- | -------------- | +| handle | PWM设备句柄 | +| *config | 参数指针 | +| **返回值** | **返回值描述** | +| 0 | 获取成功 | +| 负数 | 获取失败 | + +```c +int32_t ret; +struct PwmConfig pcfg; + +/*获取PWM设备参数*/ +ret = PwmGetConfig(handle, &pcfg); +if (ret != 0) { + /*错误处理*/ +} ``` -## 使用实例 +## 使用实例 -PWM设备完整的使用示例如下所示,首先获取PWM设备句柄,然后设置PWM设备配置信息,使能PWM,最后释放PWM设备句柄。 +PWM设备完整的使用示例如下所示,首先获取PWM设备句柄,然后设置设备周期、占空时间、极性,获取设备参数。使能,设置设备参数,禁用,最后销毁PWM设备句柄。 ``` -#include "hdf_log.h" -#include "osal_time.h" -#include "pwm_if.h" - void PwmTestSample(void) { int32_t ret; - struct PwmConfig config; /* PWM配置信息 */ - DevHandle pwm = NULL; /* PWM设备句柄 */ - - pwm = PwmOpen(0); /* 获取PWM设备句柄 */ - if (pwm == NULL) { - HDF_LOGE("PwmOpen: pwm0 failed"); + uint32_t num; + DevHandle handle = NULL; + + struct PwmConfig pcfg; + pcfg.duty = 20000000; /*占空时间为20000000纳秒*/ + pcfg.period = 40000000; /*周期为40000000纳秒*/ + pcfg.number = 100; /*生成100个方波*/ + pcfg.polarity = PWM_NORMAL_POLARITY; /*极性为正*/ + pcfg.status = PWM_ENABLE_STATUS; /*运行状态为启用*/ + + /* PWM设备编号,要填写实际平台上的编号 */ + num = 1; + + /* 获取PWM设备句柄 */ + handle = PwmOpen(num); + if (handle == NULL) { + HDF_LOGE("PwmOpen: failed!\n"); return; } - /* 获取PWM设备配置信息 */ - ret = PwmGetConfig(pwm, &config); + + /*设置周期为50000000纳秒*/ + ret = PwmSetPeriod(handle, 50000000); + if (ret != 0) { + HDF_LOGE("PwmSetPeriod: failed, ret %d\n", ret); + goto _ERR; + } + + /*设置占空时间为25000000纳秒*/ + ret = PwmSetDuty(handle, 25000000); + if (ret != 0) { + HDF_LOGE("PwmSetDuty: failed, ret %d\n", ret); + goto _ERR; + } + + /*设置极性为反*/ + ret = PwmSetPolarity(handle, PWM_INVERTED_POLARITY); + if (ret != 0) { + HDF_LOGE("PwmSetPolarity: failed, ret %d\n", ret); + goto _ERR; + } + + /*获取PWM设备参数*/ + ret = PwmGetConfig(handle, &pcfg); if (ret != 0) { HDF_LOGE("PwmGetConfig: failed, ret %d\n", ret); - goto err; + goto _ERR; } - config.duty = 500; /* 占空比500纳秒 */ - config.period = 1000; /* 周期1000纳秒 */ - /* 设置PWM设备配置信息 */ - ret = PwmSetConfig(pwm, &config); + + /*启用PWM设备*/ + ret = PwmEnable(handle); if (ret != 0) { - HDF_LOGE("PwmSetConfig: failed, ret %d\n", ret); - goto err; + HDF_LOGE("PwmEnable: failed, ret %d\n", ret); + goto _ERR; } - /* 使能PWM */ - ret = PwmEnable(pwm); + + /*设置PWM设备参数*/ + ret = PwmSetConfig(handle, &pcfg); if (ret != 0) { - HDF_LOGE("PwmEnable: failed, ret %d\n", ret); - goto err; + HDF_LOGE("PwmSetConfig: failed, ret %d\n", ret); + goto _ERR; } - /* 睡眠10秒 */ - OsalSleep(10); - /* 禁用PWM */ - ret = PwmDisable(pwm); + + /*禁用PWM设备*/ + ret = PwmDisable(handle); if (ret != 0) { HDF_LOGE("PwmDisable: failed, ret %d\n", ret); - goto err; + goto _ERR; } -err: - /* 释放PWM设备句柄 */ - PwmClose(pwm); + +_ERR: + /* 销毁PWM设备句柄 */ + PwmClose(handle); } ``` - diff --git "a/zh-cn/device-dev/driver/figures/CSI\345\217\221\351\200\201-\346\216\245\346\224\266\346\216\245\345\217\243.png" "b/zh-cn/device-dev/driver/figures/CSI\345\217\221\351\200\201-\346\216\245\346\224\266\346\216\245\345\217\243.png" new file mode 100755 index 0000000000000000000000000000000000000000..1407bc0ced6942501039f8fe041efc722882fbaa GIT binary patch literal 23263 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 UHK=vGDtKUSVtw+Zv3tZn0cfb;0RR91 literal 0 HcmV?d00001 diff --git "a/zh-cn/device-dev/driver/figures/CSI\346\227\240\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" "b/zh-cn/device-dev/driver/figures/CSI\346\227\240\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" new file mode 100755 index 0000000000000000000000000000000000000000..833ff6cc89e49ed4210dd68a502e4b304ac1c273 GIT binary patch literal 40274 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%0D)hUo|!Ldv`f6693s!R-FcDi4A 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 r!G?VP)I-okgO^PuigJ&E-w(y literal 0 HcmV?d00001 diff --git "a/zh-cn/device-dev/driver/figures/MIPI-CSI\344\275\277\347\224\250\346\265\201\347\250\213\345\233\276.png" "b/zh-cn/device-dev/driver/figures/MIPI-CSI\344\275\277\347\224\250\346\265\201\347\250\213\345\233\276.png" new file mode 100755 index 0000000000000000000000000000000000000000..1e5945dde90c375947137d8b5e9161018c0700f9 GIT binary patch literal 13078 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 E7j~CpkN^Mx literal 0 HcmV?d00001 diff --git "a/zh-cn/device-dev/driver/figures/PWM\350\256\276\345\244\207\344\275\277\347\224\250\346\265\201\347\250\213\345\233\276.png" "b/zh-cn/device-dev/driver/figures/PWM\350\256\276\345\244\207\344\275\277\347\224\250\346\265\201\347\250\213\345\233\276.png" new file mode 100755 index 0000000000000000000000000000000000000000..339d44368a15f4e58d7711c69f136bccdbc9d6db GIT binary patch literal 9334 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