diff --git a/zh-cn/device-dev/driver/driver-platform-adc-des.md b/zh-cn/device-dev/driver/driver-platform-adc-des.md index 4be6d40457169e8ca9380806d4ba16a5a4bdd10d..d478bd0a69d0a4dfd188541e8139799eb0d7caf2 100755 --- a/zh-cn/device-dev/driver/driver-platform-adc-des.md +++ b/zh-cn/device-dev/driver/driver-platform-adc-des.md @@ -4,65 +4,61 @@ ### 功能简介<a name="section2"></a> -ADC(Analog to Digital Converter),å³æ¨¡æ‹Ÿ-æ•°å—转æ¢å™¨ï¼Œæ˜¯ä¸€ç§å°†æ¨¡æ‹Ÿä¿¡å·è½¬æ¢æˆå¯¹åº”æ•°å—ä¿¡å·çš„设备。 +ADC(Analog to Digital Converter),å³æ¨¡æ‹Ÿ-æ•°å—转æ¢å™¨ï¼Œå¯å°†æ¨¡æ‹Ÿä¿¡å·è½¬æ¢æˆå¯¹åº”çš„æ•°å—ä¿¡å·ï¼Œä¾¿äºŽå˜å‚¨ä¸Žè®¡ç®—ç‰æ“作。除电æºçº¿å’Œåœ°çº¿ä¹‹å¤–,ADCåªéœ€è¦1æ ¹çº¿ä¸Žè¢«æµ‹é‡çš„设备进行连接,其物ç†è¿žçº¿å¦‚图1: + +**图 1** ADC物ç†è¿žçº¿ç¤ºæ„图<a name="fig1"></a> + + +ADC接å£å®šä¹‰äº†å®ŒæˆAD转æ¢çš„通用方法集åˆï¼ŒåŒ…括: -ADC接å£å®šä¹‰äº†å®ŒæˆADCä¼ è¾“çš„é€šç”¨æ–¹æ³•é›†åˆï¼ŒåŒ…括: - ADC设备管ç†ï¼šæ‰“开或关é—ADC设备。 - ADC读å–转æ¢ç»“果:读å–AD转æ¢ç»“果。 ### 基本概念<a name="section3"></a> -ADC主è¦ç”¨äºŽå°†æ¨¡æ‹Ÿé‡è½¬æ¢æˆæ•°å—é‡ï¼Œä»Žè€Œä¾¿äºŽå˜å‚¨ä¸Žè®¡ç®—ç‰ã€‚ - -ADC的主è¦æŠ€æœ¯å‚数有: - - 分辨率 + 分辨率指的是ADC模å—能够转æ¢çš„二进制ä½æ•°ï¼Œä½æ•°è¶Šå¤šåˆ†è¾¨çŽ‡è¶Šé«˜ã€‚ - 转æ¢è¯¯å·® + 转æ¢è¯¯å·®é€šå¸¸æ˜¯ä»¥è¾“出误差的最大值形å¼ç»™å‡ºã€‚它表示A/D转æ¢å™¨å®žé™…输出的数å—é‡å’Œç†è®ºä¸Šçš„输出数å—é‡ä¹‹é—´çš„差别。常用最低有效ä½çš„å€æ•°è¡¨ç¤ºã€‚ - 转æ¢æ—¶é—´ + 转æ¢æ—¶é—´æ˜¯æŒ‡A/D转æ¢å™¨ä»Žè½¬æ¢æŽ§åˆ¶ä¿¡å·åˆ°æ¥å¼€å§‹ï¼Œåˆ°è¾“出端得到稳定的数å—ä¿¡å·æ‰€ç»è¿‡çš„时间。 ### è¿ä½œæœºåˆ¶<a name="section4"></a> 在HDF框架ä¸ï¼ŒåŒç±»åž‹è®¾å¤‡å¯¹è±¡è¾ƒå¤šæ—¶ï¼ˆå¯èƒ½åŒæ—¶å˜åœ¨åå‡ ä¸ªåŒç±»åž‹é…置器),如果采用独立æœåŠ¡æ¨¡å¼åˆ™éœ€è¦é…置更多的设备节点,且相关æœåŠ¡ä¼šå æ®æ›´å¤šçš„内å˜èµ„æºã€‚相å,采用统一æœåŠ¡æ¨¡å¼å¯ä»¥ä½¿ç”¨ä¸€ä¸ªè®¾å¤‡æœåŠ¡ä½œä¸ºç®¡ç†å™¨ï¼Œç»Ÿä¸€å¤„ç†æ‰€æœ‰åŒç±»åž‹å¯¹è±¡çš„外部访问(这会在é…置文件ä¸æœ‰æ‰€ä½“现),实现便æ·ç®¡ç†å’ŒèŠ‚约资æºçš„目的。ADC模å—接å£é€‚é…模å¼é‡‡ç”¨ç»Ÿä¸€æœåŠ¡æ¨¡å¼ã€‚ -ADC模å—å„分层的作用为:接å£å±‚æ供打开设备,写入数æ®ï¼Œå…³é—设备的接å£ã€‚æ ¸å¿ƒå±‚ä¸»è¦æ供绑定设备ã€åˆå§‹åŒ–设备以åŠé‡Šæ”¾è®¾å¤‡çš„能力。适é…层实现其他具体的功能。 - -除电æºçº¿å’Œåœ°çº¿ä¹‹å¤–,ADCåªéœ€è¦1æ ¹çº¿ä¸Žè¢«æµ‹é‡çš„设备进行连接,其物ç†è¿žçº¿å¦‚[图1](#fig1)所示: - -**图 1** ADC物ç†è¿žçº¿ç¤ºæ„图<a name="fig1"></a> - - ### 约æŸä¸Žé™åˆ¶<a name="section5"></a> -ADC模å—当å‰ä»…支æŒè½»é‡å’Œå°åž‹ç³»ç»Ÿå†…æ ¸ï¼ˆLiteOS) 。 +ADC模å—仅支æŒè½®è¯¢æ–¹å¼è¯»å–æ•°æ®ã€‚ ## 使用指导<a name="section6"></a> ### 场景介ç»<a name="section7"></a> -ADC设备通常用于将模拟电压转æ¢ä¸ºæ•°å—é‡ï¼Œå¦‚与咪头æé…进行声音采集ã€ä¸ŽNTC电阻æé…进行温度测é‡ï¼Œæˆ–è€…å°†å…¶ä»–æ¨¡æ‹Ÿä¼ æ„Ÿå™¨çš„è¾“å‡ºé‡è½¬æ¢ä¸ºæ•°å—é‡çš„场景。 +ADC设备通常用于将模拟电压或电æµè½¬æ¢ä¸ºæ•°å—é‡ï¼Œä¾‹å¦‚与NTC电阻æé…进行温度测é‡ï¼Œæˆ–è€…å°†å…¶ä»–æ¨¡æ‹Ÿä¼ æ„Ÿå™¨çš„è¾“å‡ºé‡è½¬æ¢ä¸ºæ•°å—é‡çš„场景。 ### 接å£è¯´æ˜Ž<a name="section8"></a> -ADC模å—æ供的主è¦æŽ¥å£å¦‚[表1](#table1)所示,更多关于接å£çš„介ç»è¯·å‚考对应的API接å£æ–‡æ¡£ã€‚ +ADC模å—æ供的主è¦æŽ¥å£å¦‚表1所示,具体API详è§//drivers/hdf_core/framework/include/platform/adc_if.h。 **表 1** ADC驱动API接å£åŠŸèƒ½ä»‹ç» <a name="table1"></a> -| 接å£å | æè¿° | +| 接å£å | 接å£æè¿° | | -------- | ---------------- | -| AdcOpen | 打开ADC设备 | -| AdcClose | å…³é—ADC设备 | -| AdcRead | 读å–AD转æ¢ç»“果值 | +| DevHandle AdcOpen(uint32_t number) | 打开ADC设备 | +| void AdcClose(DevHandle handle) | å…³é—ADC设备 | +| int32_t AdcRead(DevHandle handle, uint32_t channel, uint32_t \*val) | 读å–AD转æ¢ç»“果值 | ### å¼€å‘æ¥éª¤<a name="section9"></a> -使用ADC设备的一般æµç¨‹å¦‚[图2](#fig2)所示。 +使用ADC设备的一般æµç¨‹å¦‚图2所示。 **图 2** ADC使用æµç¨‹å›¾<a name="fig2"></a>  @@ -156,13 +152,11 @@ AdcClose(adcHandle); /* å…³é—ADC设备 */ ### 使用实例<a name="section10"></a> -本例程以æ“作开å‘æ¿ä¸Šçš„ADC设备为例,详细展示ADC接å£çš„完整使用æµç¨‹ã€‚ - -本例拟对Hi3516DV300æŸå¼€å‘æ¿ä¸ŠADC设备进行简å•çš„读å–æ“作,基本硬件信æ¯å¦‚下: +本例拟对Hi3516DV300å¼€å‘æ¿ä¸ŠADC设备进行简å•çš„读å–æ“作,基本硬件信æ¯å¦‚下: - SOC:hi3516dv300。 -- 原ç†å›¾ä¿¡æ¯ï¼šç”µä½å™¨æŒ‚接在0å·ADC设备1通é“下。 +- 硬件连接:电ä½å™¨æŒ‚接在0å·ADC设备1通é“下。 本例程对测试ADC进行连ç»è¯»å–æ“作,测试ADC功能是å¦æ£å¸¸ã€‚ @@ -173,16 +167,17 @@ AdcClose(adcHandle); /* å…³é—ADC设备 */ #include "hdf_log.h" /* æ ‡å‡†æ—¥å¿—æ‰“å°å¤´æ–‡ä»¶ */ /* 设备å·0,通é“å·1 */ -#define ADC_DEVICE_NUM 0 +#define ADC_DEVICE_NUM 0 #define ADC_CHANNEL_NUM 1 +#define ADC_TEST_NUM 30 /* ADCä¾‹ç¨‹æ€»å…¥å£ */ static int32_t TestCaseAdc(void) { int32_t i; int32_t ret; - DevHandle adcHandle; - uint32_t readBuf[30] = {0}; + DevHandle adcHandle = NULL; + uint32_t readBuf[ADC_TEST_NUM] = {0}; /* 打开ADC设备 */ adcHandle = AdcOpen(ADC_DEVICE_NUM); @@ -192,7 +187,7 @@ static int32_t TestCaseAdc(void) } /* è¿žç»è¿›è¡Œ30次AD转æ¢å¹¶è¯»å–转æ¢ç»“æžœ */ - for (i = 0; i < 30; i++) { + for (i = 0; i < ADC_TEST_NUM; i++) { ret = AdcRead(adcHandle, ADC_CHANNEL_NUM, &readBuf[i]); if (ret != HDF_SUCCESS) { HDF_LOGE("%s: ADC read fail!:%d", __func__, ret); diff --git a/zh-cn/device-dev/driver/driver-platform-adc-develop.md b/zh-cn/device-dev/driver/driver-platform-adc-develop.md index 00f17c7790ef4eccb41a75f97d94b9da3d0dff1c..21843636451da3b08f8d2d0cfaf437ee2da1bf8f 100755 --- a/zh-cn/device-dev/driver/driver-platform-adc-develop.md +++ b/zh-cn/device-dev/driver/driver-platform-adc-develop.md @@ -1,40 +1,113 @@ # ADC - ## 概述 -ADC(Analog to Digital Converter),å³æ¨¡æ‹Ÿ-æ•°å—转æ¢å™¨ï¼Œæ˜¯ä¸€ç§å°†æ¨¡æ‹Ÿä¿¡å·è½¬æ¢æˆå¯¹åº”æ•°å—ä¿¡å·çš„设备。在HDF框架ä¸ï¼ŒADC模å—接å£é€‚é…模å¼é‡‡ç”¨ç»Ÿä¸€æœåŠ¡æ¨¡å¼ï¼Œè¿™éœ€è¦ä¸€ä¸ªè®¾å¤‡æœåŠ¡æ¥ä½œä¸ºADC模å—的管ç†å™¨ï¼Œç»Ÿä¸€å¤„ç†å¤–部访问,这会在é…置文件ä¸æœ‰æ‰€ä½“现。统一æœåŠ¡æ¨¡å¼é€‚åˆäºŽåŒç±»åž‹è®¾å¤‡å¯¹è±¡è¾ƒå¤šçš„情况,如ADCå¯èƒ½åŒæ—¶å…·å¤‡åå‡ ä¸ªæŽ§åˆ¶å™¨ï¼Œé‡‡ç”¨ç‹¬ç«‹æœåŠ¡æ¨¡å¼éœ€è¦é…置更多的设备节点,且æœåŠ¡ä¼šå æ®å†…å˜èµ„æºã€‚ +### 功能简介<a name="section2"></a> - **图1** ADC统一æœåŠ¡ +ADC(Analog to Digital Converter),å³æ¨¡æ‹Ÿ-æ•°å—转æ¢å™¨ï¼Œæ˜¯ä¸€ç§å°†æ¨¡æ‹Ÿä¿¡å·è½¬æ¢æˆå¯¹åº”æ•°å—ä¿¡å·çš„设备。 -  +### 基本概念<a name="section3"></a> +- 分辨率 -## 接å£è¯´æ˜Ž + 分辨率指的是ADC模å—能够转æ¢çš„二进制ä½æ•°ï¼Œä½æ•°è¶Šå¤šåˆ†è¾¨çŽ‡è¶Šé«˜ã€‚ -AdcMethod定义: +- 转æ¢è¯¯å·® + 转æ¢è¯¯å·®é€šå¸¸æ˜¯ä»¥è¾“出误差的最大值形å¼ç»™å‡ºã€‚它表示A/D转æ¢å™¨å®žé™…输出的数å—é‡å’Œç†è®ºä¸Šçš„输出数å—é‡ä¹‹é—´çš„差别。常用最低有效ä½çš„å€æ•°è¡¨ç¤ºã€‚ -``` +- 转æ¢æ—¶é—´ + + 转æ¢æ—¶é—´æ˜¯æŒ‡A/D转æ¢å™¨ä»Žè½¬æ¢æŽ§åˆ¶ä¿¡å·åˆ°æ¥å¼€å§‹ï¼Œåˆ°è¾“出端得到稳定的数å—ä¿¡å·æ‰€ç»è¿‡çš„时间。 + + +### è¿ä½œæœºåˆ¶ + +在HDF框架ä¸ï¼ŒåŒç±»åž‹è®¾å¤‡å¯¹è±¡è¾ƒå¤šæ—¶ï¼ˆå¯èƒ½åŒæ—¶å˜åœ¨åå‡ ä¸ªåŒç±»åž‹é…置器),若采用独立æœåŠ¡æ¨¡å¼ï¼Œåˆ™éœ€è¦é…置更多的设备节点,且相关æœåŠ¡ä¼šå æ®æ›´å¤šçš„内å˜èµ„æºã€‚相å,采用统一æœåŠ¡æ¨¡å¼å¯ä»¥ä½¿ç”¨ä¸€ä¸ªè®¾å¤‡æœåŠ¡ä½œä¸ºç®¡ç†å™¨ï¼Œç»Ÿä¸€å¤„ç†æ‰€æœ‰åŒç±»åž‹å¯¹è±¡çš„外部访问(这会在é…置文件ä¸æœ‰æ‰€ä½“现),实现便æ·ç®¡ç†å’ŒèŠ‚约资æºçš„目的。ADC模å—å³é‡‡ç”¨ç»Ÿä¸€æœåŠ¡æ¨¡å¼ï¼ˆå¦‚图1)。 + +ADC模å—å„分层的作用为: + +- 接å£å±‚:æ供打开设备,写入数æ®ï¼Œå…³é—设备的能力。 +- æ ¸å¿ƒå±‚ï¼šä¸»è¦è´Ÿè´£æœåŠ¡ç»‘定ã€åˆå§‹åŒ–以åŠé‡Šæ”¾ç®¡ç†å™¨ï¼Œå¹¶æä¾›æ·»åŠ ã€åˆ 除以åŠèŽ·å–控制器的能力。 +- 适é…层:由驱动适é…者实现与硬件相关的具体功能,如控制器的åˆå§‹åŒ–ç‰ã€‚ + +在统一模å¼ä¸‹ï¼Œæ‰€æœ‰çš„æŽ§åˆ¶å™¨éƒ½è¢«æ ¸å¿ƒå±‚ç»Ÿä¸€ç®¡ç†ï¼Œå¹¶ç”±æ ¸å¿ƒå±‚统一å‘布一个æœåŠ¡ä¾›æŽ¥å£å±‚ï¼Œå› æ¤è¿™ç§æ¨¡å¼ä¸‹é©±åŠ¨æ— 需å†ä¸ºæ¯ä¸ªæŽ§åˆ¶å™¨å‘布æœåŠ¡ã€‚ + +**图1** ADC统一æœåŠ¡æ¨¡å¼ç»“构图<a name="fig1"></a> + + +## 使用指导 + +### åœºæ™¯ä»‹ç» + +ADC设备通常用于将模拟电压转æ¢ä¸ºæ•°å—é‡ï¼Œä¾‹å¦‚与NTC电阻æé…进行温度测é‡ï¼Œæˆ–è€…å°†å…¶ä»–æ¨¡æ‹Ÿä¼ æ„Ÿå™¨çš„è¾“å‡ºé‡è½¬æ¢ä¸ºæ•°å—é‡çš„场景。当驱动开å‘者需è¦å°†ADC设备适é…到OpenHarmony时,需è¦è¿›è¡ŒADC驱动适é…,下文将介ç»å¦‚何进行ADC驱动适é…。 + +### 接å£è¯´æ˜Ž + +为了ä¿è¯ä¸Šå±‚在调用ADC接å£æ—¶èƒ½å¤Ÿæ£ç¡®çš„æ“ä½œç¡¬ä»¶ï¼Œæ ¸å¿ƒå±‚åœ¨//drivers/hdf_core/framework/support/platform/include/adc/adc_core.hä¸å®šä¹‰äº†ä»¥ä¸‹é’©å函数。驱动适é…者需è¦åœ¨é€‚é…层实现这些函数的具体功能,并与这些钩å函数挂接,从而完æˆæŽ¥å£å±‚ä¸Žæ ¸å¿ƒå±‚çš„äº¤äº’ã€‚ + +AdcMethodå’ŒAdcLockMethod定义: + +```c struct AdcMethod { - int32_t (*read)(struct AdcDevice *device, uint32_t channel, uint32_t *val); - int32_t (*start)(struct AdcDevice *device); - int32_t (*stop)(struct AdcDevice *device); + int32_t (*read)(struct AdcDevice *device, uint32_t channel, uint32_t *val); + int32_t (*start)(struct AdcDevice *device); + int32_t (*stop)(struct AdcDevice *device); }; + +struct AdcLockMethod { + int32_t (*lock)(struct AdcDevice *device); + void (*unlock)(struct AdcDevice *device); +}; + ``` - **表1** AdcMethod结构体æˆå‘˜çš„回调函数功能说明 +在适é…层ä¸ï¼ŒAdcMethod必须被实现,AdcLockMethodå¯æ ¹æ®å®žé™…情况考虑是å¦å®žçŽ°ã€‚æ ¸å¿ƒå±‚æ供了默认的AdcLockMethod,其ä¸ä½¿ç”¨Spinlock作为ä¿æŠ¤ä¸´ç•ŒåŒºçš„é”: + +```c +static int32_t AdcDeviceLockDefault(struct AdcDevice *device) +{ + if (device == NULL) { + return HDF_ERR_INVALID_OBJECT; + } + return OsalSpinLock(&device->spin); +} + +static void AdcDeviceUnlockDefault(struct AdcDevice *device) +{ + if (device == NULL) { + return; + } + (void)OsalSpinUnlock(&device->spin); +} + +static const struct AdcLockMethod g_adcLockOpsDefault = { + .lock = AdcDeviceLockDefault, + .unlock = AdcDeviceUnlockDefault, +}; + +``` + +若实际情况ä¸å…许使用Spinlock,驱动适é…者å¯ä»¥è€ƒè™‘使用其他类型的é”æ¥å®žçŽ°ä¸€ä¸ªè‡ªå®šä¹‰çš„AdcLockMethod。一旦实现了自定义的AdcLockMethod,默认的AdcLockMethod将被覆盖。 + + **表1** AdcMethod结构体æˆå‘˜çš„é’©å函数功能说明 | 函数æˆå‘˜ | å…¥å‚ | å‡ºå‚ | 返回值 | 功能 | | -------- | -------- | -------- | -------- | -------- | -| read | deviceï¼šç»“æž„ä½“æŒ‡é’ˆï¼Œæ ¸å¿ƒå±‚ADC控制器<br/>channel:uint32_tï¼Œä¼ å…¥çš„é€šé“å· | val:uint32_t指针,è¦ä¼ 出的信å·æ•°æ® | HDF_STATUSç›¸å…³çŠ¶æ€ | 读å–ADCé‡‡æ ·çš„ä¿¡å·æ•°æ® | -| stop | deviceï¼šç»“æž„ä½“æŒ‡é’ˆï¼Œæ ¸å¿ƒå±‚ADC控制器 | æ— | HDF_STATUSç›¸å…³çŠ¶æ€ | å…³é—ADC设备 | -| start | deviceï¼šç»“æž„ä½“æŒ‡é’ˆï¼Œæ ¸å¿ƒå±‚ADC控制器 | æ— | HDF_STATUSç›¸å…³çŠ¶æ€ | å¼€å¯ADC设备 | +| read | deviceï¼šç»“æž„ä½“æŒ‡é’ˆï¼Œæ ¸å¿ƒå±‚ADC控制器<br/>channel:uint32_tï¼Œä¼ å…¥çš„é€šé“å· | val:uint32_t指针,è¦ä¼ 出的信å·æ•°æ® | HDF_STATUSç›¸å…³çŠ¶æ€ | 读å–ADCé‡‡æ ·çš„ä¿¡å·æ•°æ® | +| stop | deviceï¼šç»“æž„ä½“æŒ‡é’ˆï¼Œæ ¸å¿ƒå±‚ADC控制器 | æ— | HDF_STATUSç›¸å…³çŠ¶æ€ | å…³é—ADC设备 | +| start | deviceï¼šç»“æž„ä½“æŒ‡é’ˆï¼Œæ ¸å¿ƒå±‚ADC控制器 | æ— | HDF_STATUSç›¸å…³çŠ¶æ€ | å¼€å¯ADC设备 | +**表2** AdcLockMethod结构体æˆå‘˜å‡½æ•°åŠŸèƒ½è¯´æ˜Ž + +| 函数æˆå‘˜ | å…¥å‚ | å‡ºå‚ | 返回值 | 功能 | +| -------- | -------- | -------- | -------- | -------- | +| lock | deviceï¼šç»“æž„ä½“æŒ‡é’ˆï¼Œæ ¸å¿ƒå±‚ADC设备对象。 | æ— | HDF_STATUSç›¸å…³çŠ¶æ€ | 获å–ä¸´ç•ŒåŒºé” | +| unlock | devicieï¼šç»“æž„ä½“æŒ‡é’ˆï¼Œæ ¸å¿ƒå±‚ADC设备对象。 | æ— | HDF_STATUSç›¸å…³çŠ¶æ€ | é‡Šæ”¾ä¸´ç•ŒåŒºé” | -## å¼€å‘æ¥éª¤ +### å¼€å‘æ¥éª¤ -ADC模å—适é…必选的三个环节是é…置属性文件,实例化驱动入å£ï¼Œä»¥åŠå®žä¾‹åŒ–æ ¸å¿ƒå±‚æŽ¥å£å‡½æ•°ã€‚ +ADC模å—适é…必选的三个环节是实例化驱动入å£ï¼Œé…置属性文件,以åŠå®žä¾‹åŒ–æ ¸å¿ƒå±‚æŽ¥å£å‡½æ•°ã€‚ 1. å®žä¾‹åŒ–é©±åŠ¨å…¥å£ - 实例化HdfDriverEntry结构体æˆå‘˜ã€‚ @@ -44,20 +117,15 @@ ADC模å—适é…必选的三个环节是é…置属性文件,实例化驱动入 - 在device_info.hcs文件ä¸æ·»åŠ deviceNodeæ述。 - ã€å¯é€‰ã€‘æ·»åŠ adc_config.hcs器件属性文件。 -3. 实例化ADC控制器对象 +3. å®žä¾‹åŒ–æ ¸å¿ƒå±‚æŽ¥å£å‡½æ•° - åˆå§‹åŒ–AdcDeviceæˆå‘˜ã€‚ - 实例化AdcDeviceæˆå‘˜AdcMethod。 >  **说明:**<br> > 实例化AdcDeviceæˆå‘˜AdcMethod,其定义和æˆå‘˜è¯´æ˜Žè§[接å£è¯´æ˜Ž](#接å£è¯´æ˜Ž)。 -4. 驱动调试 +### å¼€å‘实例 - ã€å¯é€‰ã€‘针对新增驱动程åºï¼Œå»ºè®®éªŒè¯é©±åŠ¨åŸºæœ¬åŠŸèƒ½ï¼Œä¾‹å¦‚挂载åŽçš„ä¿¡æ¯å馈,信å·é‡‡é›†çš„æˆåŠŸä¸Žå¦ç‰ã€‚ - - -## å¼€å‘实例 - - 接下æ¥ä»¥adc_hi35xx.c为示例, 展示需è¦åŽ‚商æ供哪些内容æ¥å®Œæ•´å®žçŽ°è®¾å¤‡åŠŸèƒ½ã€‚ + 接下æ¥ä»¥Hi3516DV300的驱动//device/soc/hisilicon/common/platform/adc/adc_hi35xx.c为例, 展示需è¦é©±åŠ¨é€‚é…者æ供哪些内容æ¥å®Œæ•´å®žçŽ°è®¾å¤‡åŠŸèƒ½ã€‚ 1. 驱动开å‘首先需è¦å®žä¾‹åŒ–驱动入å£ã€‚ @@ -69,128 +137,135 @@ ADC模å—适é…必选的三个环节是é…置属性文件,实例化驱动入 ADCæŽ§åˆ¶å™¨ä¼šå‡ºçŽ°å¤šä¸ªè®¾å¤‡æŒ‚æŽ¥çš„æƒ…å†µï¼Œå› è€Œåœ¨HDF框架ä¸é¦–先会为æ¤ç±»åž‹çš„设备创建一个管ç†å™¨å¯¹è±¡ã€‚è¿™æ ·ï¼Œéœ€è¦æ‰“å¼€æŸä¸ªè®¾å¤‡æ—¶ï¼Œç®¡ç†å™¨å¯¹è±¡ä¼šæ ¹æ®æŒ‡å®šå‚数查找到指定设备。 - ADC管ç†å™¨çš„é©±åŠ¨ç”±æ ¸å¿ƒå±‚å®žçŽ°ï¼ŒåŽ‚å•†ä¸éœ€è¦å…³æ³¨è¿™éƒ¨åˆ†å†…容的实现,但在实现Init函数的时候需è¦è°ƒç”¨æ ¸å¿ƒå±‚çš„AdcDeviceAdd函数,它会实现相应功能。 - - - ``` - static struct HdfDriverEntry g_hi35xxAdcDriverEntry = { - .moduleVersion = 1, - .Init = Hi35xxAdcInit, - .Release = Hi35xxAdcRelease, - .moduleName = "hi35xx_adc_driver", //ã€å¿…è¦ä¸”与HCS文件里é¢çš„åå—匹é…】 - }; - HDF_INIT(g_hi35xxAdcDriverEntry); // 调用HDF_INIT将驱动入å£æ³¨å†Œåˆ°HDFæ¡†æž¶ä¸ - - // æ ¸å¿ƒå±‚adc_core.c管ç†å™¨æœåŠ¡çš„é©±åŠ¨å…¥å£ - struct HdfDriverEntry g_adcManagerEntry = { - .moduleVersion = 1, - .Init = AdcManagerInit, - .Release = AdcManagerRelease, - .moduleName = "HDF_PLATFORM_ADC_MANAGER",// 这与device_info文件ä¸device0对应 - }; - HDF_INIT(g_adcManagerEntry); - ``` - -2. 完æˆé©±åŠ¨å…¥å£æ³¨å†Œä¹‹åŽï¼Œä¸‹ä¸€æ¥è¯·åœ¨device_info.hcs文件ä¸æ·»åŠ deviceNodeä¿¡æ¯ï¼Œå¹¶åœ¨adc_config.hcsä¸é…置器件属性。 - - deviceNodeä¿¡æ¯ä¸Žé©±åŠ¨å…¥å£æ³¨å†Œç›¸å…³ï¼Œå™¨ä»¶å±žæ€§å€¼å¯¹äºŽåŽ‚商驱动的实现以åŠæ ¸å¿ƒå±‚AdcDevice相关æˆå‘˜çš„默认值或é™åˆ¶èŒƒå›´æœ‰å¯†åˆ‡å…³ç³»ã€‚ - - 统一æœåŠ¡æ¨¡å¼çš„特点是device_info文件ä¸ç¬¬ä¸€ä¸ªè®¾å¤‡èŠ‚点必须为ADC管ç†å™¨ï¼Œå…¶å„项å‚数必须如下设置: - - - | æˆå‘˜å | 值 | - | -------- | -------- | - | moduleName | 固定为HDF_PLATFORM_ADC_MANAGER | - | serviceName | æ— | - | policy | 具体é…置为0,ä¸å‘布æœåŠ¡ | - | deviceMatchAttr | 没有使用,å¯å¿½ç•¥ | - - - 从第二个节点开始é…置具体ADC控制器信æ¯ï¼Œæ¤èŠ‚点并ä¸è¡¨ç¤ºæŸä¸€è·¯ADC控制器,而是代表一个资æºæ€§è´¨è®¾å¤‡ï¼Œç”¨äºŽæ述一类ADC控制器的信æ¯ã€‚本例åªæœ‰ä¸€ä¸ªADC设备,如有多个设备,则需è¦åœ¨device_infoæ–‡ä»¶å¢žåŠ deviceNodeä¿¡æ¯ï¼Œä»¥åŠåœ¨adc_config文件ä¸å¢žåŠ 对应的器件属性。 + ADC管ç†å™¨çš„é©±åŠ¨ç”±æ ¸å¿ƒå±‚å®žçŽ°ï¼Œé©±åŠ¨é€‚é…者ä¸éœ€è¦å…³æ³¨è¿™éƒ¨åˆ†å†…容的实现,但在实现Init函数的时候需è¦è°ƒç”¨æ ¸å¿ƒå±‚çš„AdcDeviceAdd函数,它会实现相应功能。 + + ```c + static struct HdfDriverEntry g_hi35xxAdcDriverEntry = { + .moduleVersion = 1, + .Init = Hi35xxAdcInit, + .Release = Hi35xxAdcRelease, + .moduleName = "hi35xx_adc_driver", //ã€å¿…è¦ä¸”与device_info.hcs文件内的模å—å匹é…】 + }; + HDF_INIT(g_hi35xxAdcDriverEntry); // 调用HDF_INIT将驱动入å£æ³¨å†Œåˆ°HDFæ¡†æž¶ä¸ + + /* æ ¸å¿ƒå±‚adc_core.c管ç†å™¨æœåŠ¡çš„é©±åŠ¨å…¥å£ */ + struct HdfDriverEntry g_adcManagerEntry = { + .moduleVersion = 1, + .Init = AdcManagerInit, + .Release = AdcManagerRelease, + .moduleName = "HDF_PLATFORM_ADC_MANAGER", // 这与device_info.hcs文件ä¸device0对应 + }; + HDF_INIT(g_adcManagerEntry); + ``` + +2. 完æˆé©±åŠ¨å…¥å£æ³¨å†Œä¹‹åŽï¼Œä¸‹ä¸€æ¥è¯·åœ¨//vendor/hisilicon/hispark_taurus/hdf_config/device_info/device_info.hcs文件ä¸æ·»åŠ deviceNodeä¿¡æ¯ï¼Œå¹¶åœ¨adc_config.hcsä¸é…置器件属性。 + + deviceNodeä¿¡æ¯ä¸Žé©±åŠ¨å…¥å£æ³¨å†Œç›¸å…³ï¼Œå™¨ä»¶å±žæ€§å€¼å¯¹äºŽé©±åŠ¨é€‚é…者的驱动实现以åŠæ ¸å¿ƒå±‚AdcDevice相关æˆå‘˜çš„默认值或é™åˆ¶èŒƒå›´æœ‰å¯†åˆ‡å…³ç³»ã€‚ + + 统一æœåŠ¡æ¨¡å¼çš„特点是device_info.hcs文件ä¸ç¬¬ä¸€ä¸ªè®¾å¤‡èŠ‚点必须为ADC管ç†å™¨ï¼Œå…¶å„项å‚数必须如下设置: + + | æˆå‘˜å | 值 | + | -------- | -------- | + | moduleName | 固定为HDF_PLATFORM_ADC_MANAGER | + | serviceName | æ— | + | policy | 具体é…置为0,ä¸å‘布æœåŠ¡ | + | deviceMatchAttr | 没有使用,å¯å¿½ç•¥ | + + 从第二个节点开始é…置具体ADC控制器信æ¯ï¼Œç¬¬ä¸€ä¸ªèŠ‚点并ä¸è¡¨ç¤ºæŸä¸€è·¯ADC控制器,而是代表一个资æºæ€§è´¨è®¾å¤‡ï¼Œç”¨äºŽæ述一类ADC控制器的信æ¯ã€‚本例åªæœ‰ä¸€ä¸ªADC设备,如有多个设备,则需è¦åœ¨device_info.hcsæ–‡ä»¶å¢žåŠ deviceNodeä¿¡æ¯ï¼Œä»¥åŠåœ¨adc_config文件ä¸å¢žåŠ 对应的器件属性。 - device_info.hcsé…ç½®å‚考 - - ``` + ```c root { device_info { - platform :: host { - device_adc :: device { - device0 :: deviceNode { - policy = 0; - priority = 50; - permission = 0644; - moduleName = "HDF_PLATFORM_ADC_MANAGER"; - serviceName = "HDF_PLATFORM_ADC_MANAGER"; - } - device1 :: deviceNode { - policy = 0; // ç‰äºŽ0,ä¸éœ€è¦å‘布æœåŠ¡ã€‚ - priority = 55; // 驱动å¯åŠ¨ä¼˜å…ˆçº§ã€‚ - permission = 0644; // 驱动创建设备节点æƒé™ã€‚ - moduleName = "hi35xx_adc_driver"; //ã€å¿…è¦ã€‘用于指定驱动å称,需è¦ä¸ŽæœŸæœ›çš„驱动Entryä¸çš„moduleName一致。 - serviceName = "HI35XX_ADC_DRIVER"; //ã€å¿…è¦ã€‘驱动对外å‘布æœåŠ¡çš„å称,必须唯一。 - deviceMatchAttr = "hisilicon_hi35xx_adc";//ã€å¿…è¦ã€‘用于é…置控制器ç§æœ‰æ•°æ®ï¼Œè¦ä¸Žadc_config.hcsä¸å¯¹åº”控制器ä¿æŒä¸€è‡´ï¼Œ - // 具体的控制器信æ¯åœ¨adc_config.hcsä¸ã€‚ - } - } + platform :: host { + device_adc :: device { + device0 :: deviceNode { + policy = 0; + priority = 50; + permission = 0644; + moduleName = "HDF_PLATFORM_ADC_MANAGER"; + serviceName = "HDF_PLATFORM_ADC_MANAGER"; + } + device1 :: deviceNode { + policy = 0; // ç‰äºŽ0,ä¸éœ€è¦å‘布æœåŠ¡ã€‚ + priority = 55; // 驱动å¯åŠ¨ä¼˜å…ˆçº§ã€‚ + permission = 0644; // 驱动创建设备节点æƒé™ã€‚ + moduleName = "hi35xx_adc_driver"; //ã€å¿…è¦ã€‘用于指定驱动å称,需è¦ä¸ŽæœŸæœ›çš„驱动Entryä¸çš„moduleName一致。 + serviceName = "HI35XX_ADC_DRIVER"; //ã€å¿…è¦ã€‘驱动对外å‘布æœåŠ¡çš„å称,必须唯一。 + deviceMatchAttr = "hisilicon_hi35xx_adc"; //ã€å¿…è¦ã€‘用于é…置控制器ç§æœ‰æ•°æ®ï¼Œè¦ä¸Žadc_config.hcsä¸å¯¹åº”控制器ä¿æŒä¸€è‡´ï¼Œ + // 具体的控制器信æ¯åœ¨adc_config.hcsä¸ã€‚ + } + } + } } - } } ``` + - adc_config.hcsé…ç½®å‚考 - - ``` + æ¤å¤„以Hi3516DV300为例,给出HCSé…ç½®å‚考。其ä¸éƒ¨åˆ†å—段为Hi3516DV300特有功能,驱动适é…者å¯æ ¹æ®éœ€è¦è¿›è¡Œåˆ é™¤æˆ–æ·»åŠ å—段。 + + ```c root { - platform { - adc_config_hi35xx { - match_attr = "hisilicon_hi35xx_adc"; - template adc_device { - regBasePhy = 0x120e0000;// 寄å˜å™¨ç‰©ç†åŸºåœ°å€ - regSize = 0x34; // 寄å˜å™¨ä½å®½ - deviceNum = 0; // è®¾å¤‡å· - validChannel = 0x1; // æœ‰æ•ˆé€šé“ - dataWidth = 10; // ä¿¡å·æŽ¥æ”¶çš„æ•°æ®ä½å®½ - scanMode = 1; // 扫ææ¨¡å¼ - delta = 0; // deltaå‚æ•° - deglitch = 0; - glitchSample = 5000; - rate = 20000; - } - device_0 :: adc_device { - deviceNum = 0; - validChannel = 0x2; - } + platform { + adc_config_hi35xx { + match_attr = "hisilicon_hi35xx_adc"; + template adc_device { + regBasePhy = 0x120e0000; // 寄å˜å™¨ç‰©ç†åŸºåœ°å€ + regSize = 0x34; // 寄å˜å™¨ä½å®½ + deviceNum = 0; // è®¾å¤‡å· + validChannel = 0x1; // æœ‰æ•ˆé€šé“ + dataWidth = 10; // AD转æ¢åŽçš„æ•°æ®ä½å®½ï¼Œå³åˆ†è¾¨çŽ‡ + scanMode = 1; // 扫ææ¨¡å¼ + delta = 0; // 转æ¢ç»“果误差范围 + deglitch = 0; // 滤毛刺开关 + glitchSample = 5000; // æ»¤æ¯›åˆºæ—¶é—´çª—å£ + rate = 20000; // 转æ¢é€ŸçŽ‡ + } + device_0 :: adc_device { + deviceNum = 0; + validChannel = 0x2; + } + } } } - } ``` -3. 完æˆé©±åŠ¨å…¥å£æ³¨å†Œä¹‹åŽï¼Œä¸‹ä¸€æ¥å°±æ˜¯ä»¥æ ¸å¿ƒå±‚AdcDevice对象的åˆå§‹åŒ–ä¸ºæ ¸å¿ƒï¼ŒåŒ…æ‹¬åˆå§‹åŒ–åŽ‚å•†è‡ªå®šä¹‰ç»“æž„ä½“ï¼ˆä¼ é€’å‚数和数æ®ï¼‰ï¼Œå®žä¾‹åŒ–AdcDeviceæˆå‘˜AdcMethod(让用户å¯ä»¥é€šè¿‡æŽ¥å£æ¥è°ƒç”¨é©±åŠ¨åº•å±‚函数),实现HdfDriverEntryæˆå‘˜å‡½æ•°ï¼ˆBind,Init,Release)。 + 需è¦æ³¨æ„的是,新增adc_config.hcsé…置文件åŽï¼Œå¿…须在hdf.hcs文件ä¸å°†å…¶åŒ…å«ï¼Œå¦åˆ™é…ç½®æ–‡ä»¶æ— æ³•ç”Ÿæ•ˆã€‚ + + 例如:本例ä¸adc_config.hcs所在路径为//device/soc/hisilicon/hi3516dv300/sdk_liteos/hdf_config/adc/adc_config.hcs,则必须在产å“对应的hdf.hcsä¸æ·»åŠ 如下è¯å¥ï¼š + + ```c + #include "../../../../device/soc/hisilicon/hi3516dv300/sdk_liteos/hdf_config/adc/adc_config.hcs" // é…置文件相对路径 + ``` + + 本例基于Hi3516DV300å¼€å‘æ¿çš„å°åž‹ç³»ç»ŸLiteOSå†…æ ¸è¿è¡Œï¼Œå¯¹åº”çš„hdf.hcs文件路径为vendor/hisilicon/hispark_taurus/hdf_config/hdf.hcs以åŠ//device/hisilicon/hispark_taurus/sdk_liteos/hdf_config/hdf.hcs。驱动适é…è€…éœ€æ ¹æ®å®žé™…情况选择对应路径下的文件进行修改。 + +3. 完æˆé©±åŠ¨å…¥å£æ³¨å†Œä¹‹åŽï¼Œä¸‹ä¸€æ¥å°±æ˜¯ä»¥æ ¸å¿ƒå±‚AdcDevice对象的åˆå§‹åŒ–ä¸ºæ ¸å¿ƒï¼ŒåŒ…æ‹¬åˆå§‹åŒ–驱动适é…è€…è‡ªå®šä¹‰ç»“æž„ä½“ï¼ˆä¼ é€’å‚数和数æ®ï¼‰ï¼Œå®žä¾‹åŒ–AdcDeviceæˆå‘˜AdcMethod(让用户å¯ä»¥é€šè¿‡æŽ¥å£æ¥è°ƒç”¨é©±åŠ¨åº•å±‚函数),实现HdfDriverEntryæˆå‘˜å‡½æ•°ï¼ˆBind,Init,Release)。 - 自定义结构体å‚考。 - 从驱动的角度看,自定义结构体是å‚数和数æ®çš„载体,而且adc_config.hcs文件ä¸çš„数值会被HDF读入并通过DeviceResourceIfaceæ¥åˆå§‹åŒ–结构体æˆå‘˜ï¼Œå…¶ä¸ä¸€äº›é‡è¦æ•°å€¼ä¹Ÿä¼šä¼ é€’ç»™æ ¸å¿ƒå±‚AdcDevice对象,例如设备å·ã€æ€»çº¿å·ç‰ã€‚ + 从驱动的角度看,自定义结构体是å‚数和数æ®çš„载体,而且adc_config.hcs文件ä¸çš„数值会被HDF读入并通过DeviceResourceIfaceæ¥åˆå§‹åŒ–结构体æˆå‘˜ï¼Œå…¶ä¸ä¸€äº›é‡è¦æ•°å€¼ï¼ˆä¾‹å¦‚设备å·ã€æ€»çº¿å·ç‰ï¼‰ä¹Ÿä¼šä¼ é€’ç»™æ ¸å¿ƒå±‚AdcDevice对象。 - - ``` + ```c struct Hi35xxAdcDevice { - struct AdcDevice device; //ã€å¿…è¦ã€‘æ˜¯æ ¸å¿ƒå±‚æŽ§åˆ¶å¯¹è±¡ï¼Œå…·ä½“æè¿°è§ä¸‹é¢ã€‚ - volatile unsigned char *regBase;//ã€å¿…è¦ã€‘寄å˜å™¨åŸºåœ°å€ + struct AdcDevice device; //ã€å¿…è¦ã€‘æ˜¯æ ¸å¿ƒå±‚æŽ§åˆ¶å¯¹è±¡ï¼Œå¿…é¡»ä½œä¸ºè‡ªå®šä¹‰ç»“æž„ä½“çš„é¦–ä¸ªæˆå‘˜ï¼Œå…¶å…·ä½“æè¿°è§ä¸‹æ–¹ã€‚ + volatile unsigned char *regBase; //ã€å¿…è¦ã€‘寄å˜å™¨åŸºåœ°å€ volatile unsigned char *pinCtrlBase; - uint32_t regBasePhy; //ã€å¿…è¦ã€‘寄å˜å™¨ç‰©ç†åŸºåœ°å€ - uint32_t regSize; //ã€å¿…è¦ã€‘寄å˜å™¨ä½å®½ - uint32_t deviceNum; //ã€å¿…è¦ã€‘è®¾å¤‡å· - uint32_t dataWidth; //ã€å¿…è¦ã€‘ä¿¡å·æŽ¥æ”¶çš„æ•°æ®ä½å®½ - uint32_t validChannel; //ã€å¿…è¦ã€‘æœ‰æ•ˆé€šé“ - uint32_t scanMode; //ã€å¿…è¦ã€‘扫ææ¨¡å¼ + uint32_t regBasePhy; //ã€å¿…è¦ã€‘寄å˜å™¨ç‰©ç†åŸºåœ°å€ + uint32_t regSize; //ã€å¿…è¦ã€‘寄å˜å™¨ä½å®½ + uint32_t deviceNum; //ã€å¿…è¦ã€‘è®¾å¤‡å· + uint32_t dataWidth; //ã€å¿…è¦ã€‘ä¿¡å·æŽ¥æ”¶çš„æ•°æ®ä½å®½ + uint32_t validChannel; //ã€å¿…è¦ã€‘æœ‰æ•ˆé€šé“ + uint32_t scanMode; //ã€å¿…è¦ã€‘扫ææ¨¡å¼ uint32_t delta; uint32_t deglitch; uint32_t glitchSample; - uint32_t rate; //ã€å¿…è¦ã€‘é‡‡æ ·çŽ‡ + uint32_t rate; //ã€å¿…è¦ã€‘é‡‡æ ·çŽ‡ }; - // AdcDeviceæ˜¯æ ¸å¿ƒå±‚æŽ§åˆ¶å™¨ç»“æž„ä½“ï¼Œå…¶ä¸çš„æˆå‘˜åœ¨Init函数ä¸ä¼šè¢«èµ‹å€¼ã€‚ + /* AdcDeviceæ˜¯æ ¸å¿ƒå±‚æŽ§åˆ¶å™¨ç»“æž„ä½“ï¼Œå…¶ä¸çš„æˆå‘˜åœ¨Init函数ä¸ä¼šè¢«èµ‹å€¼ã€‚*/ struct AdcDevice { const struct AdcMethod *ops; OsalSpinlock spin; @@ -201,50 +276,50 @@ ADC模å—适é…必选的三个环节是é…置属性文件,实例化驱动入 }; ``` - - AdcDeviceæˆå‘˜å›žè°ƒå‡½æ•°ç»“构体AdcMethod的实例化。 + - AdcDeviceæˆå‘˜é’©å函数结构体AdcMethod的实例化。 - AdcLockMethod回调函数结构体本例未实现,若è¦å®žä¾‹åŒ–,å¯å‚考I2C驱动开å‘,其他æˆå‘˜åœ¨Init函数ä¸åˆå§‹åŒ–。 + AdcLockMethodé’©å函数结构体本例未实现,若è¦å®žä¾‹åŒ–,å¯å‚考I2C驱动开å‘,其他æˆå‘˜åœ¨Init函数ä¸åˆå§‹åŒ–。 - - ``` + ```c static const struct AdcMethod g_method = { .read = Hi35xxAdcRead, .stop = Hi35xxAdcStop, .start = Hi35xxAdcStart, }; ``` - - Init函数å‚考 + + - Init函数开å‘å‚考 å…¥å‚: - HdfDeviceObject是整个驱动对外暴露的接å£å‚数,具备HCSé…置文件的信æ¯ã€‚ + HdfDeviceObject是整个驱动对外æ供的接å£å‚数,具备HCSé…置文件的信æ¯ã€‚ 返回值: - HDF_STATUS相关状æ€ï¼ˆä¸‹è¡¨ä¸ºéƒ¨åˆ†å±•ç¤ºï¼Œå¦‚需使用其他状æ€ï¼Œå¯è§//drivers/framework/include/utils/hdf_base.hä¸HDF_STATUS定义)。 + HDF_STATUS相关状æ€ï¼ˆä¸‹è¡¨ä¸ºéƒ¨åˆ†å±•ç¤ºï¼Œå¦‚需使用其他状æ€ï¼Œå¯è§//drivers/hdf_core/framework/include/utils/hdf_base.hä¸HDF_STATUS定义)。 - | 状æ€(值) | 问题æè¿° | + | 状æ€(值) | 问题æè¿° | | -------- | -------- | - | HDF_ERR_INVALID_OBJECT | 控制器对象éžæ³• | - | HDF_ERR_INVALID_PARAM | å‚æ•°éžæ³• | - | HDF_ERR_MALLOC_FAIL | 内å˜åˆ†é…失败 | - | HDF_ERR_IO | I/O错误 | - | HDF_SUCCESS | ä¼ è¾“æˆåŠŸ | - | HDF_FAILURE | ä¼ è¾“å¤±è´¥ | + | HDF_ERR_INVALID_OBJECT | 控制器对象éžæ³• | + | HDF_ERR_INVALID_PARAM | å‚æ•°éžæ³• | + | HDF_ERR_MALLOC_FAIL | 内å˜åˆ†é…失败 | + | HDF_ERR_IO | I/O错误 | + | HDF_SUCCESS | ä¼ è¾“æˆåŠŸ | + | HDF_FAILURE | ä¼ è¾“å¤±è´¥ | 函数说明: - åˆå§‹åŒ–自定义结构体对象,åˆå§‹åŒ–AdcDeviceæˆå‘˜ï¼Œå¹¶è°ƒç”¨æ ¸å¿ƒå±‚AdcDeviceAdd函数。 + åˆå§‹åŒ–自定义结构体对象,åˆå§‹åŒ–AdcDeviceæˆå‘˜ï¼Œå¹¶è°ƒç”¨æ ¸å¿ƒå±‚AdcDeviceAdd函数。 - ``` + ```c static int32_t Hi35xxAdcInit(struct HdfDeviceObject *device) { int32_t ret; struct DeviceResourceNode *childNode = NULL; ... - // é历ã€è§£æžadc_config.hcsä¸çš„所有é…置节点,并分别调用Hi35xxAdcParseInit函数æ¥åˆå§‹åŒ–device。 + /* é历ã€è§£æžadc_config.hcsä¸çš„所有é…置节点,并分别调用Hi35xxAdcParseInit函数æ¥åˆå§‹åŒ–device。*/ DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) { - ret = Hi35xxAdcParseInit(device, childNode);// 函数定义è§ä¸‹ + ret = Hi35xxAdcParseInit(device, childNode); // 函数定义è§ä¸‹æ–¹ ... } return ret; @@ -252,43 +327,70 @@ ADC模å—适é…必选的三个环节是é…置属性文件,实例化驱动入 static int32_t Hi35xxAdcParseInit(struct HdfDeviceObject *device, struct DeviceResourceNode *node) { - int32_t ret; - struct Hi35xxAdcDevice *hi35xx = NULL; //ã€å¿…è¦ã€‘自定义结构体对象 - (void)device; - - hi35xx = (struct Hi35xxAdcDevice *)OsalMemCalloc(sizeof(*hi35xx)); //ã€å¿…è¦ã€‘内å˜åˆ†é… - ... - ret = Hi35xxAdcReadDrs(hi35xx, node); //ã€å¿…è¦ã€‘å°†adc_configæ–‡ä»¶çš„é»˜è®¤å€¼å¡«å……åˆ°ç»“æž„ä½“ä¸ - ... - hi35xx->regBase = OsalIoRemap(hi35xx->regBasePhy, hi35xx->regSize);//ã€å¿…è¦ã€‘地å€æ˜ å°„ - ... - hi35xx->pinCtrlBase = OsalIoRemap(HI35XX_ADC_IO_CONFIG_BASE, HI35XX_ADC_IO_CONFIG_SIZE); - ... - Hi35xxAdcDeviceInit(hi35xx); //ã€å¿…è¦ã€‘ADC设备的åˆå§‹åŒ– - hi35xx->device.priv = (void *)node; //ã€å¿…è¦ã€‘å˜å‚¨è®¾å¤‡å±žæ€§ - hi35xx->device.devNum = hi35xx->deviceNum;//ã€å¿…è¦ã€‘åˆå§‹åŒ–AdcDeviceæˆå‘˜ - hi35xx->device.ops = &g_method; //ã€å¿…è¦ã€‘AdcMethod的实例化对象的挂载 - ret = AdcDeviceAdd(&hi35xx->device); //ã€å¿…è¦ä¸”é‡è¦ã€‘调用æ¤å‡½æ•°å¡«å……æ ¸å¿ƒå±‚ç»“æž„ä½“ï¼Œè¿”å›žæˆåŠŸä¿¡å·åŽé©±åŠ¨æ‰å®Œå…¨æŽ¥å…¥å¹³å°æ ¸å¿ƒå±‚。 - ... - return HDF_SUCCESS; + int32_t ret; + struct Hi35xxAdcDevice *hi35xx = NULL; //ã€å¿…è¦ã€‘自定义结构体对象 + (void)device; + + hi35xx = (struct Hi35xxAdcDevice *)OsalMemCalloc(sizeof(*hi35xx)); //ã€å¿…è¦ã€‘内å˜åˆ†é… + ... + ret = Hi35xxAdcReadDrs(hi35xx, node); //ã€å¿…è¦ã€‘å°†adc_config文件的默认值填充到结构体ä¸ï¼Œå‡½æ•°å®šä¹‰è§ä¸‹æ–¹ + ... + hi35xx->regBase = OsalIoRemap(hi35xx->regBasePhy, hi35xx->regSize); //ã€å¿…è¦ã€‘地å€æ˜ å°„ + ... + hi35xx->pinCtrlBase = OsalIoRemap(HI35XX_ADC_IO_CONFIG_BASE, HI35XX_ADC_IO_CONFIG_SIZE); + ... + Hi35xxAdcDeviceInit(hi35xx); //ã€å¿…è¦ã€‘ADC设备的åˆå§‹åŒ– + hi35xx->device.priv = (void *)node; //ã€å¿…è¦ã€‘å˜å‚¨è®¾å¤‡å±žæ€§ + hi35xx->device.devNum = hi35xx->deviceNum; //ã€å¿…è¦ã€‘åˆå§‹åŒ–AdcDeviceæˆå‘˜ + hi35xx->device.ops = &g_method; //ã€å¿…è¦ã€‘AdcMethod的实例化对象的挂载 + ret = AdcDeviceAdd(&hi35xx->device); //ã€å¿…è¦ä¸”é‡è¦ã€‘调用æ¤å‡½æ•°å¡«å……æ ¸å¿ƒå±‚ç»“æž„ä½“ï¼Œè¿”å›žæˆåŠŸä¿¡å·åŽé©±åŠ¨æ‰å®Œå…¨æŽ¥å…¥å¹³å°æ ¸å¿ƒå±‚。 + ... + return HDF_SUCCESS; __ERR__: - if (hi35xx != NULL) { // ä¸æˆåŠŸçš„è¯ï¼Œéœ€è¦åå‘执行åˆå§‹åŒ–相关函数。 - if (hi35xx->regBase != NULL) { - OsalIoUnmap((void *)hi35xx->regBase); - hi35xx->regBase = NULL; + if (hi35xx != NULL) { // è‹¥ä¸æˆåŠŸï¼Œéœ€è¦æ‰§è¡ŒåŽ»åˆå§‹åŒ–相关函数。 + if (hi35xx->regBase != NULL) { + OsalIoUnmap((void *)hi35xx->regBase); + hi35xx->regBase = NULL; + } + AdcDeviceRemove(&hi35xx->device); + OsalMemFree(hi35xx); } - AdcDeviceRemove(&hi35xx->device); - OsalMemFree(hi35xx); + return ret; } - return ret; + + static int32_t Hi35xxAdcReadDrs(struct Hi35xxAdcDevice *hi35xx, const struct DeviceResourceNode *node) + { + int32_t ret; + struct DeviceResourceIface *drsOps = NULL; + + /* 获å–drsOps方法 */ + drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE); + if (drsOps == NULL || drsOps->GetUint32 == NULL) { + HDF_LOGE("%s: invalid drs ops", __func__); + return HDF_ERR_NOT_SUPPORT; + } + /* å°†é…ç½®å‚æ•°ä¾æ¬¡è¯»å‡ºï¼Œå¹¶å¡«å……è‡³ç»“æž„ä½“ä¸ */ + ret = drsOps->GetUint32(node, "regBasePhy", &hi35xx->regBasePhy, 0); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: read regBasePhy failed", __func__); + return ret; + } + ret = drsOps->GetUint32(node, "regSize", &hi35xx->regSize, 0); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: read regSize failed", __func__); + return ret; + } + ··· + return HDF_SUCCESS; } ``` - - Release函数å‚考 + + - Release函数开å‘å‚考 å…¥å‚: - HdfDeviceObject是整个驱动对外暴露的接å£å‚数,具备HCSé…置文件的信æ¯ã€‚ + HdfDeviceObject是整个驱动对外æ供的接å£å‚数,具备HCSé…置文件的信æ¯ã€‚ 返回值: @@ -298,41 +400,38 @@ ADC模å—适é…必选的三个环节是é…置属性文件,实例化驱动入 释放内å˜å’Œåˆ 除控制器,该函数需è¦åœ¨é©±åŠ¨å…¥å£ç»“构体ä¸èµ‹å€¼ç»™Release接å£ï¼Œå½“HDF框架调用Init函数åˆå§‹åŒ–驱动失败时,å¯ä»¥è°ƒç”¨Release释放驱动资æºã€‚ - >  **说明:**<br> - > 所有强制转æ¢èŽ·å–相应对象的æ“作的å‰æ是在Init函数ä¸å…·å¤‡å¯¹åº”赋值的æ“作。 - - - ``` + ```c static void Hi35xxAdcRelease(struct HdfDeviceObject *device) { - const struct DeviceResourceNode *childNode = NULL; - ... - // é历ã€è§£æžadc_config.hcsä¸çš„所有é…置节点,并分别进行Releaseæ“作。 - DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) { - Hi35xxAdcRemoveByNode(childNode);// 函数定义è§ä¸‹ - } + const struct DeviceResourceNode *childNode = NULL; + ... + /* é历ã€è§£æžadc_config.hcsä¸çš„所有é…置节点,并分别进行Releaseæ“作。*/ + DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) { + Hi35xxAdcRemoveByNode(childNode);// 函数定义è§ä¸‹ + } } static void Hi35xxAdcRemoveByNode(const struct DeviceResourceNode *node) { - int32_t ret; - int32_t deviceNum; - struct AdcDevice *device = NULL; - struct Hi35xxAdcDevice *hi35xx = NULL; - struct DeviceResourceIface *drsOps = NULL; - - drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE); - ... - ret = drsOps->GetUint32(node, "deviceNum", (uint32_t *)&deviceNum, 0); - ... - // å¯ä»¥è°ƒç”¨AdcDeviceGet函数通过设备的deviceNum获å–AdcDevice对象,以åŠè°ƒç”¨AdcDeviceRemove函数æ¥é‡Šæ”¾AdcDevice对象的内容。 - device = AdcDeviceGet(deviceNum); - if (device != NULL && device->priv == node) { - AdcDevicePut(device); - AdcDeviceRemove(device); //ã€å¿…è¦ã€‘主è¦æ˜¯ä»Žç®¡ç†å™¨é©±åŠ¨é‚£è¾¹ç§»é™¤AdcDevice对象 - hi35xx = (struct Hi35xxAdcDevice *)device;//ã€å¿…è¦ã€‘通过强制转æ¢èŽ·å–自定义的对象并进行Releaseæ“作 - OsalIoUnmap((void *)hi35xx->regBase); - OsalMemFree(hi35xx); + int32_t ret; + int32_t deviceNum; + struct AdcDevice *device = NULL; + struct Hi35xxAdcDevice *hi35xx = NULL; + struct DeviceResourceIface *drsOps = NULL; + + drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE); + ... + ret = drsOps->GetUint32(node, "deviceNum", (uint32_t *)&deviceNum, 0); + ... + /* å¯ä»¥è°ƒç”¨AdcDeviceGet函数通过设备的deviceNum获å–AdcDevice对象,以åŠè°ƒç”¨AdcDeviceRemove函数æ¥é‡Šæ”¾AdcDevice对象的内容。*/ + device = AdcDeviceGet(deviceNum); + if (device != NULL && device->priv == node) { + AdcDevicePut(device); + AdcDeviceRemove(device); //ã€å¿…è¦ã€‘主è¦æ˜¯ä»Žç®¡ç†å™¨é©±åŠ¨é‚£è¾¹ç§»é™¤AdcDevice对象。 + hi35xx = (struct Hi35xxAdcDevice *)device; //ã€å¿…è¦ã€‘通过强制转æ¢èŽ·å–自定义的对象并进行Releaseæ“作。这一æ¥çš„å‰æ是device必须作为自定义结构体的首个æˆå‘˜ã€‚ + OsalIoUnmap((void *)hi35xx->regBase); + OsalMemFree(hi35xx); + } + return; } - return ``` diff --git a/zh-cn/device-dev/driver/driver-platform-dac-des.md b/zh-cn/device-dev/driver/driver-platform-dac-des.md index 7238d1453b8db78e43bd1227841de29a62d0c582..4f4e4b47f12e04e5559af1794dc0ac2dde1e2b4b 100644 --- a/zh-cn/device-dev/driver/driver-platform-dac-des.md +++ b/zh-cn/device-dev/driver/driver-platform-dac-des.md @@ -4,7 +4,10 @@ ### 功能简介 -DAC(Digital to Analog Converter)是一ç§é€šè¿‡ç”µæµã€ç”µåŽ‹æˆ–电è·çš„å½¢å¼å°†æ•°å—ä¿¡å·è½¬æ¢ä¸ºæ¨¡æ‹Ÿä¿¡å·çš„设备。 +DAC(Digital to Analog Converter)是一ç§é€šè¿‡ç”µæµã€ç”µåŽ‹æˆ–电è·çš„å½¢å¼å°†æ•°å—ä¿¡å·è½¬æ¢ä¸ºæ¨¡æ‹Ÿä¿¡å·çš„设备,主è¦ç”¨äºŽï¼š + +- 作为过程控制计算机系统的输出通é“,与执行器相连,实现对生产过程的自动控制。 +- 在利用å馈技术的模数转æ¢å™¨è®¾è®¡ä¸ï¼Œä½œä¸ºé‡è¦çš„功能模å—呈现。 DAC接å£å®šä¹‰äº†å®ŒæˆDACä¼ è¾“çš„é€šç”¨æ–¹æ³•é›†åˆï¼ŒåŒ…括: - DAC设备管ç†ï¼šæ‰“开或关é—DAC设备。 @@ -12,11 +15,6 @@ DAC接å£å®šä¹‰äº†å®ŒæˆDACä¼ è¾“çš„é€šç”¨æ–¹æ³•é›†åˆï¼ŒåŒ…括: ### 基本概念 -DAC模å—支æŒæ•°æ¨¡è½¬æ¢çš„å¼€å‘,它主è¦ç”¨äºŽï¼š - -1. 作为过程控制计算机系统的输出通é“,与执行器相连,实现对生产过程的自动控制。 -2. 在利用å馈技术的模数转æ¢å™¨è®¾è®¡ä¸ï¼Œä½œä¸ºé‡è¦çš„功能模å—呈现。 - - 分辨率 分辨率指的是DAC模å—能够转æ¢çš„二进制ä½æ•°ï¼Œä½æ•°è¶Šå¤šåˆ†è¾¨çŽ‡è¶Šé«˜ã€‚ @@ -35,7 +33,7 @@ DAC模å—支æŒæ•°æ¨¡è½¬æ¢çš„å¼€å‘,它主è¦ç”¨äºŽï¼š ### è¿ä½œæœºåˆ¶ -在HDF框架ä¸ï¼ŒåŒç±»åž‹è®¾å¤‡å¯¹è±¡è¾ƒå¤šæ—¶ï¼ˆå¯èƒ½åŒæ—¶å˜åœ¨åå‡ ä¸ªåŒç±»åž‹é…置器),如果采用独立æœåŠ¡æ¨¡å¼ï¼Œåˆ™éœ€è¦é…置更多的设备节点,且相关æœåŠ¡ä¼šå æ®æ›´å¤šçš„内å˜èµ„æºã€‚相å,采用统一æœåŠ¡æ¨¡å¼å¯ä»¥ä½¿ç”¨ä¸€ä¸ªè®¾å¤‡æœåŠ¡ä½œä¸ºç®¡ç†å™¨ï¼Œç»Ÿä¸€å¤„ç†æ‰€æœ‰åŒç±»åž‹å¯¹è±¡çš„外部访问(这会在é…置文件ä¸æœ‰æ‰€ä½“现),实现便æ·ç®¡ç†å’ŒèŠ‚约资æºçš„目的。DAC模å—接å£é€‚é…模å¼é‡‡ç”¨ç»Ÿä¸€æœåŠ¡æ¨¡å¼ï¼Œå¦‚图1所示。 +在HDF框架ä¸ï¼ŒåŒç±»åž‹è®¾å¤‡å¯¹è±¡è¾ƒå¤šæ—¶ï¼ˆå¯èƒ½åŒæ—¶å˜åœ¨åå‡ ä¸ªåŒç±»åž‹é…置器),如果采用独立æœåŠ¡æ¨¡å¼ï¼Œåˆ™éœ€è¦é…置更多的设备节点,且相关æœåŠ¡ä¼šå æ®æ›´å¤šçš„内å˜èµ„æºã€‚相å,采用统一æœåŠ¡æ¨¡å¼å¯ä»¥ä½¿ç”¨ä¸€ä¸ªè®¾å¤‡æœåŠ¡ä½œä¸ºç®¡ç†å™¨ï¼Œç»Ÿä¸€å¤„ç†æ‰€æœ‰åŒç±»åž‹å¯¹è±¡çš„外部访问(这会在é…置文件ä¸æœ‰æ‰€ä½“现),实现便æ·ç®¡ç†å’ŒèŠ‚约资æºçš„目的。DAC模å—接å£é€‚é…模å¼é‡‡ç”¨ç»Ÿä¸€æœåŠ¡æ¨¡å¼ï¼ˆå¦‚图1)。 DAC模å—å„分层的作用为:接å£å±‚æ供打开设备ã€å†™å…¥æ•°æ®å’Œå…³é—设备的接å£ã€‚æ ¸å¿ƒå±‚ä¸»è¦æ供绑定设备ã€åˆå§‹åŒ–设备以åŠé‡Šæ”¾è®¾å¤‡çš„能力。适é…层实现其它具体的功能。 @@ -47,7 +45,7 @@ DAC模å—å„分层的作用为:接å£å±‚æ供打开设备ã€å†™å…¥æ•°æ®å’Œ ### 约æŸä¸Žé™åˆ¶ -DAC模å—当å‰ä»…支æŒè½»é‡å’Œå°åž‹ç³»ç»Ÿå†…æ ¸ï¼ˆLiteOS)。 +DAC模å—当å‰ä»…支æŒè½»é‡å’Œå°åž‹ç³»ç»Ÿå†…æ ¸ï¼ˆLiteOS-A)。 ## 使用指导 @@ -57,11 +55,11 @@ DAC模å—的主è¦å·¥ä½œæ˜¯ä»¥ç”µæµã€ç”µåŽ‹æˆ–电è·çš„å½¢å¼å°†æ•°å—ä¿¡å· ### 接å£è¯´æ˜Ž -DAC模å—æ供的主è¦æŽ¥å£å¦‚下所示,更多关于接å£çš„介ç»è¯·å‚考对应的API接å£æ–‡æ¡£ã€‚ +DAC模å—æ供的主è¦æŽ¥å£å¦‚下所示,具体API详è§//drivers/hdf_core/framework/include/platform/dac_if.h。 **表 1** DAC驱动API接å£åŠŸèƒ½ä»‹ç» -| 接å£å | æè¿° | +| 接å£å | 接å£æè¿° | | ------------------------------------------------------------------ | ------------ | | DevHandle DacOpen(uint32_t number) | 打开DAC设备。 | | void DacClose(DevHandle handle) | å…³é—DAC设备。 | @@ -94,7 +92,7 @@ DevHandle DacOpen(uint32_t number); å‡è®¾ç³»ç»Ÿä¸å˜åœ¨2个DAC设备,编å·ä»Ž0到1,现在打开1å·è®¾å¤‡ã€‚ ```c++ -DevHandle dacHandle = NULL; /* DAC设备å¥æŸ„ / +DevHandle dacHandle = NULL; // DAC设备å¥æŸ„ /* 打开DAC设备 */ dacHandle = DacOpen(1); @@ -123,12 +121,12 @@ int32_t DacWrite(DevHandle handle, uint32_t channel, uint32_t val); ```c++ /* 通过DAC_CHANNEL_NUM设备通é“å†™å…¥ç›®æ ‡val值 */ - ret = DacWrite(dacHandle, DAC_CHANNEL_NUM, val); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: tp DAC write reg fail!:%d", __func__, ret); - DacClose(dacHandle); - return -1; - } +ret = DacWrite(dacHandle, DAC_CHANNEL_NUM, val); +if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: tp DAC write reg fail!:%d", __func__, ret); + DacClose(dacHandle); + return -1; +} ``` #### å…³é—DAC设备 diff --git a/zh-cn/device-dev/driver/driver-platform-dac-develop.md b/zh-cn/device-dev/driver/driver-platform-dac-develop.md index 54b624b17ef8eb16385e4b2ecea4ce4e7c39b910..b2d5bfb0cb57d7910bbdc5dc26a616b24c569f26 100644 --- a/zh-cn/device-dev/driver/driver-platform-dac-develop.md +++ b/zh-cn/device-dev/driver/driver-platform-dac-develop.md @@ -9,7 +9,7 @@ DAC(Digital to Analog Converter)是一ç§é€šè¿‡ç”µæµã€ç”µåŽ‹æˆ–电è·çš„ DAC模å—支æŒæ•°æ¨¡è½¬æ¢çš„å¼€å‘。它主è¦ç”¨äºŽï¼š - 作为过程控制计算机系统的输出通é“,与执行器相连,实现对生产过程的自动控制。 -- 在利用å馈技术的é”术转æ¢å™¨è®¾è®¡ä¸ï¼Œä½œä¸ºé‡è¦çš„功能模å—呈现。 +- 在利用å馈技术的模数转æ¢å™¨è®¾è®¡ä¸ï¼Œä½œä¸ºé‡è¦çš„功能模å—呈现。 ### 基本概念 @@ -31,44 +31,82 @@ DAC模å—支æŒæ•°æ¨¡è½¬æ¢çš„å¼€å‘。它主è¦ç”¨äºŽï¼š ### è¿ä½œæœºåˆ¶ -在HDF框架ä¸ï¼ŒåŒç±»åž‹è®¾å¤‡å¯¹è±¡è¾ƒå¤šæ—¶ï¼ˆå¯èƒ½åŒæ—¶å˜åœ¨åå‡ ä¸ªåŒç±»åž‹é…置器),若采用独立æœåŠ¡æ¨¡å¼ï¼Œåˆ™éœ€è¦é…置更多的设备节点,且相关æœåŠ¡ä¼šå æ®æ›´å¤šçš„内å˜èµ„æºã€‚相å,采用统一æœåŠ¡æ¨¡å¼å¯ä»¥ä½¿ç”¨ä¸€ä¸ªè®¾å¤‡æœåŠ¡ä½œä¸ºç®¡ç†å™¨ï¼Œç»Ÿä¸€å¤„ç†æ‰€æœ‰åŒç±»åž‹å¯¹è±¡çš„外部访问(这会在é…置文件ä¸æœ‰æ‰€ä½“现),实现便æ·ç®¡ç†å’ŒèŠ‚约资æºçš„目的。DAC模å—接å£é€‚é…模å¼é‡‡ç”¨ç»Ÿä¸€æœåŠ¡æ¨¡å¼ï¼ˆå¦‚图1所示)。 +在HDF框架ä¸ï¼ŒåŒç±»åž‹è®¾å¤‡å¯¹è±¡è¾ƒå¤šæ—¶ï¼ˆå¯èƒ½åŒæ—¶å˜åœ¨åå‡ ä¸ªåŒç±»åž‹é…置器),若采用独立æœåŠ¡æ¨¡å¼ï¼Œåˆ™éœ€è¦é…置更多的设备节点,且相关æœåŠ¡ä¼šå æ®æ›´å¤šçš„内å˜èµ„æºã€‚相å,采用统一æœåŠ¡æ¨¡å¼å¯ä»¥ä½¿ç”¨ä¸€ä¸ªè®¾å¤‡æœåŠ¡ä½œä¸ºç®¡ç†å™¨ï¼Œç»Ÿä¸€å¤„ç†æ‰€æœ‰åŒç±»åž‹å¯¹è±¡çš„外部访问(这会在é…置文件ä¸æœ‰æ‰€ä½“现),实现便æ·ç®¡ç†å’ŒèŠ‚约资æºçš„目的。DAC模å—å³é‡‡ç”¨ç»Ÿä¸€æœåŠ¡æ¨¡å¼ï¼ˆå¦‚图1)。 -DAC模å—å„分层的作用为:接å£å±‚æ供打开设备ã€å†™å…¥æ•°æ®å’Œå…³é—设备接å£çš„èƒ½åŠ›ã€‚æ ¸å¿ƒå±‚ä¸»è¦æ供绑定设备ã€åˆå§‹åŒ–设备以åŠé‡Šæ”¾è®¾å¤‡çš„能力。适é…层实现其他具体的功能。 +DAC模å—å„分层的作用为: +- 接å£å±‚:æ供打开设备ã€å†™å…¥æ•°æ®å’Œå…³é—设备接å£çš„能力。 +- æ ¸å¿ƒå±‚ï¼šä¸»è¦æ供绑定设备ã€åˆå§‹åŒ–设备以åŠé‡Šæ”¾è®¾å¤‡çš„能力。 +- 适é…层:由驱动适é…者实现与硬件相关的具体功能,如控制器的åˆå§‹åŒ–ç‰ã€‚ + +在统一模å¼ä¸‹ï¼Œæ‰€æœ‰çš„æŽ§åˆ¶å™¨éƒ½è¢«æ ¸å¿ƒå±‚ç»Ÿä¸€ç®¡ç†ï¼Œå¹¶ç”±æ ¸å¿ƒå±‚统一å‘布一个æœåŠ¡ä¾›æŽ¥å£å±‚ï¼Œå› æ¤è¿™ç§æ¨¡å¼ä¸‹é©±åŠ¨æ— 需å†ä¸ºæ¯ä¸ªæŽ§åˆ¶å™¨å‘布æœåŠ¡ã€‚  说明:<br>æ ¸å¿ƒå±‚å¯ä»¥è°ƒç”¨æŽ¥å£å±‚的函数,也å¯ä»¥é€šè¿‡é’©å函数调用适é…层函数,从而使得适é…层间接的å¯ä»¥è°ƒç”¨æŽ¥å£å±‚函数,但是ä¸å¯é€†è½¬æŽ¥å£å±‚调用适é…层函数。 -**图 1** 统一æœåŠ¡æ¨¡å¼ +**图 1** 统一æœåŠ¡æ¨¡å¼ç»“构图<a name="fig1"></a>  ### 约æŸä¸Žé™åˆ¶ -DAC模å—当å‰ä»…支æŒè½»é‡å’Œå°åž‹ç³»ç»Ÿå†…æ ¸ï¼ˆLiteOS)。 +DAC模å—当å‰ä»…支æŒè½»é‡å’Œå°åž‹ç³»ç»Ÿå†…æ ¸ï¼ˆLiteOS-A)。 ## å¼€å‘指导 ### åœºæ™¯ä»‹ç» -DAC模å—主è¦åœ¨è®¾å¤‡ä¸æ•°æ¨¡è½¬æ¢ã€éŸ³é¢‘输出和电机控制ç‰è®¾å¤‡ä½¿ç”¨ï¼Œè®¾ç½®å°†DAC模å—ä¼ å…¥çš„æ•°å—ä¿¡å·è½¬æ¢ä¸ºè¾“出模拟信å·æ—¶éœ€è¦ç”¨åˆ°DAC数模转æ¢é©±åŠ¨ã€‚ +DAC模å—主è¦åœ¨è®¾å¤‡ä¸æ•°æ¨¡è½¬æ¢ã€éŸ³é¢‘输出和电机控制ç‰è®¾å¤‡ä½¿ç”¨ï¼Œè®¾ç½®å°†DAC模å—ä¼ å…¥çš„æ•°å—ä¿¡å·è½¬æ¢ä¸ºè¾“出模拟信å·æ—¶éœ€è¦ç”¨åˆ°DAC数模转æ¢é©±åŠ¨ã€‚当驱动开å‘者需è¦å°†DAC设备适é…到OpenHarmony时,需è¦è¿›è¡ŒDAC驱动适é…,下文将介ç»å¦‚何进行DAC驱动适é…。 ### 接å£è¯´æ˜Ž -通过以下DacMethodä¸çš„函数调用DAC驱动对应的函数。 +为了ä¿è¯ä¸Šå±‚在调用DAC接å£æ—¶èƒ½å¤Ÿæ£ç¡®çš„æ“ä½œç¡¬ä»¶ï¼Œæ ¸å¿ƒå±‚åœ¨//drivers/hdf_core/framework/support/platform/include/dac/dac_core.hä¸å®šä¹‰äº†ä»¥ä¸‹é’©å函数。驱动适é…者需è¦åœ¨é€‚é…层实现这些函数的具体功能,并与这些钩å函数挂接,从而完æˆæŽ¥å£å±‚ä¸Žæ ¸å¿ƒå±‚çš„äº¤äº’ã€‚ -DacMethod定义: +DacMethodå’ŒDacLockMethod定义: ```c++ struct DacMethod { - // 写入数æ®çš„é’©å函数 + /* 写入数æ®çš„é’©å函数 */ int32_t (*write)(struct DacDevice *device, uint32_t channel, uint32_t val); - // å¯åŠ¨DAC设备的钩å函数 + /* å¯åŠ¨DAC设备的钩å函数 */ int32_t (*start)(struct DacDevice *device); - // åœæ¢DAC设备的钩å函数 + /* åœæ¢DAC设备的钩å函数 */ int32_t (*stop)(struct DacDevice *device); }; + +struct DacLockMethod { + int32_t (*lock)(struct DacDevice *device); + void (*unlock)(struct DacDevice *device); +}; ``` +在适é…层ä¸ï¼ŒDacMethod必须被实现,DacLockMethodå¯æ ¹æ®å®žé™…情况考虑是å¦å®žçŽ°ã€‚æ ¸å¿ƒå±‚æ供了默认的DacLockMethod,其ä¸ä½¿ç”¨Spinlock作为ä¿æŠ¤ä¸´ç•ŒåŒºçš„é”: + +```c +static int32_t DacDeviceLockDefault(struct DacDevice *device) +{ + if (device == NULL) { + HDF_LOGE("%s: device is null", __func__); + return HDF_ERR_INVALID_OBJECT; + } + return OsalSpinLock(&device->spin); +} + +static void DacDeviceUnlockDefault(struct DacDevice *device) +{ + if (device == NULL) { + HDF_LOGE("%s: device is null", __func__); + return; + } + (void)OsalSpinUnlock(&device->spin); +} + +static const struct DacLockMethod g_dacLockOpsDefault = { + .lock = DacDeviceLockDefault, + .unlock = DacDeviceUnlockDefault, +}; +``` + +若实际情况ä¸å…许使用Spinlock,驱动适é…者å¯ä»¥è€ƒè™‘使用其他类型的é”æ¥å®žçŽ°ä¸€ä¸ªè‡ªå®šä¹‰çš„DacLockMethod。一旦实现了自定义的DacLockMethod,默认的DacLockMethod将被覆盖。 -**表 1** DacMethod结构体æˆå‘˜çš„回调函数功能说明 +**表 1** DacMethod结构体æˆå‘˜çš„é’©å函数功能说明 | 函数æˆå‘˜ | å…¥å‚ | å‡ºå‚ | 返回值 | 功能 | | -------- | ------------------------------------------------------------ | ---- | ------------------ | -------------- | @@ -76,6 +114,14 @@ struct DacMethod { | start | deviceï¼šç»“æž„ä½“æŒ‡é’ˆï¼Œæ ¸å¿ƒå±‚DAC控制器 | æ— | HDF_STATUSç›¸å…³çŠ¶æ€ | å¼€å¯DAC设备 | | stop | deviceï¼šç»“æž„ä½“æŒ‡é’ˆï¼Œæ ¸å¿ƒå±‚DAC控制器 | æ— | HDF_STATUSç›¸å…³çŠ¶æ€ | å…³é—DAC设备 | +**表2** DacLockMethod结构体æˆå‘˜å‡½æ•°åŠŸèƒ½è¯´æ˜Ž + +| 函数æˆå‘˜ | å…¥å‚ | å‡ºå‚ | 返回值 | 功能 | +| -------- | -------- | -------- | -------- | -------- | +| lock | deviceï¼šç»“æž„ä½“æŒ‡é’ˆï¼Œæ ¸å¿ƒå±‚DAC设备对象。 | æ— | HDF_STATUSç›¸å…³çŠ¶æ€ | 获å–ä¸´ç•ŒåŒºé” | +| unlock | devicieï¼šç»“æž„ä½“æŒ‡é’ˆï¼Œæ ¸å¿ƒå±‚DAC设备对象。 | æ— | HDF_STATUSç›¸å…³çŠ¶æ€ | é‡Šæ”¾ä¸´ç•ŒåŒºé” | + + ### å¼€å‘æ¥éª¤ DAC模å—适é…包å«ä»¥ä¸‹å››ä¸ªæ¥éª¤ï¼š @@ -87,11 +133,11 @@ DAC模å—适é…包å«ä»¥ä¸‹å››ä¸ªæ¥éª¤ï¼š ### å¼€å‘实例 -下方将展示厂商需è¦æ供哪些内容æ¥å®Œæ•´å®žçŽ°è®¾å¤‡åŠŸèƒ½ã€‚ +下方将Hi3516DV300的驱动//device/soc/hisilicon/common/platform/dac/dac_hi35xx.c为例,展示驱动适é…者需è¦æ供哪些内容æ¥å®Œæ•´å®žçŽ°è®¾å¤‡åŠŸèƒ½ã€‚ 1. 实例化驱动入å£ï¼š - 驱动开å‘首先需è¦å®žä¾‹åŒ–驱动入å£ï¼Œé©±åŠ¨å…¥å£å¿…须为HdfDriverEntry(在hdf_device_desc.hä¸å®šä¹‰ï¼‰ç±»åž‹çš„全局å˜é‡ï¼Œä¸”moduleNameè¦å’Œdevice_info.hcsä¸ä¿æŒä¸€è‡´ã€‚HDFæ¡†æž¶ä¼šæ±‡æ€»æ‰€æœ‰åŠ è½½çš„é©±åŠ¨çš„HdfDriverEntry对象入å£ï¼Œå½¢æˆä¸€ä¸ªç±»ä¼¼æ•°ç»„的段地å€ç©ºé—´ï¼Œæ–¹ä¾¿ä¸Šå±‚调用。 + 驱动开å‘首先需è¦å®žä¾‹åŒ–驱动入å£ï¼Œé©±åŠ¨å…¥å£å¿…须为HdfDriverEntry(在hdf_device_desc.hä¸å®šä¹‰ï¼‰ç±»åž‹çš„全局å˜é‡ï¼Œä¸”moduleNameè¦å’Œ//vendor/hisilicon/hispark_taurus/hdf_config/device_info/device_info.hcsä¸ä¿æŒä¸€è‡´ã€‚HDFæ¡†æž¶ä¼šæ±‡æ€»æ‰€æœ‰åŠ è½½çš„é©±åŠ¨çš„HdfDriverEntry对象入å£ï¼Œå½¢æˆä¸€ä¸ªç±»ä¼¼æ•°ç»„的段地å€ç©ºé—´ï¼Œæ–¹ä¾¿ä¸Šå±‚调用。 ä¸€èˆ¬åœ¨åŠ è½½é©±åŠ¨æ—¶HDF会先调用Initå‡½æ•°åŠ è½½è¯¥é©±åŠ¨ã€‚å½“Init调用异常时,HDF框架会调用Release释放驱动资æºå¹¶é€€å‡ºã€‚ @@ -101,15 +147,15 @@ DAC模å—适é…包å«ä»¥ä¸‹å››ä¸ªæ¥éª¤ï¼š .Init = VirtualDacInit, .Release = VirtualDacRelease, .moduleName = "virtual_dac_driver", //ã€å¿…è¦ä¸”与HCS里é¢çš„åå—匹é…】 - }; - HDF_INIT(g_dacDriverEntry); // 调用HDF_INIT将驱动入å£æ³¨å†Œåˆ°HDFæ¡†æž¶ä¸ + }; + HDF_INIT(g_dacDriverEntry); // 调用HDF_INIT将驱动入å£æ³¨å†Œåˆ°HDFæ¡†æž¶ä¸ ``` 2. é…置属性文件: - - 在vendor/hisilicon/hispark_taurus/hdf_config/device_info/device_info.hcs文件ä¸æ·»åŠ deviceNodeæ述。 + - æ·»åŠ //vendor/hisilicon/hispark_taurus/hdf_config/device_info/device_info.hcs器件属性文件。 - 器件属性值对于厂商驱动的实现以åŠæ ¸å¿ƒå±‚DacDevice相关æˆå‘˜çš„默认值或é™åˆ¶èŒƒå›´æœ‰å¯†åˆ‡å…³ç³»ï¼Œæ¯”如设备通é“的个数以åŠä¼ 输速率的最大值,会影å“DacDevice相关æˆå‘˜çš„默认值。 + 器件属性值对于驱动适é…者的驱动实现以åŠæ ¸å¿ƒå±‚DacDevice相关æˆå‘˜çš„默认值或é™åˆ¶èŒƒå›´æœ‰å¯†åˆ‡å…³ç³»ï¼Œæ¯”如设备通é“的个数以åŠä¼ 输速率的最大值,会影å“DacDevice相关æˆå‘˜çš„默认值。 由于采用了统一æœåŠ¡æ¨¡å¼ï¼Œdevice_info.hcs文件ä¸ç¬¬ä¸€ä¸ªè®¾å¤‡èŠ‚点必须为DAC管ç†å™¨ï¼Œå…¶å„项å‚数必须如下设置: @@ -122,14 +168,14 @@ DAC模å—适é…包å«ä»¥ä¸‹å››ä¸ªæ¥éª¤ï¼š | serviceName | 固定为HDF_PLATFORM_DAC_MANAGER | | deviceMatchAttr | 没有使用,å¯å¿½ç•¥ | - 从第二个节点开始é…置具体DAC控制器信æ¯ï¼Œæ¤èŠ‚点并ä¸è¡¨ç¤ºæŸä¸€è·¯DAC控制器,而是代表一个资æºæ€§è´¨è®¾å¤‡ï¼Œç”¨äºŽæ述一类DAC控制器的信æ¯ã€‚本例åªæœ‰ä¸€ä¸ªDAC设备,如有多个设备,则需è¦åœ¨device_infoæ–‡ä»¶å¢žåŠ deviceNodeä¿¡æ¯ï¼Œä»¥åŠåœ¨dac_config文件ä¸å¢žåŠ 对应的器件属性。 + 从第二个节点开始é…置具体DAC控制器信æ¯ï¼Œæ¤èŠ‚点并ä¸è¡¨ç¤ºæŸä¸€è·¯DAC控制器,而是代表一个资æºæ€§è´¨è®¾å¤‡ï¼Œç”¨äºŽæ述一类DAC控制器的信æ¯ã€‚本例åªæœ‰ä¸€ä¸ªDAC设备,如有多个设备,则需è¦åœ¨device_info.hcsæ–‡ä»¶å¢žåŠ deviceNodeä¿¡æ¯ï¼Œä»¥åŠåœ¨dac_config.hcs文件ä¸å¢žåŠ 对应的器件属性。 device_info.hcsé…ç½®å‚考: ```hcs root { device_dac :: device { - // device0是DAC管ç†å™¨ + /* device0是DAC管ç†å™¨ */ device0 :: deviceNode { policy = 0; priority = 52; @@ -138,7 +184,7 @@ DAC模å—适é…包å«ä»¥ä¸‹å››ä¸ªæ¥éª¤ï¼š moduleName = "HDF_PLATFORM_DAC_MANAGER"; } } - // dac_virtual是DAC控制器 + /* dac_virtual是DAC控制器 */ dac_virtual :: deviceNode { policy = 0; priority = 56; @@ -152,7 +198,7 @@ DAC模å—适é…包å«ä»¥ä¸‹å››ä¸ªæ¥éª¤ï¼š - æ·»åŠ dac_test_config.hcs器件属性文件。 - 在vendor/vendor_hisilicon/hispark_taurus/hdf_config/hdf_test/xxx_test_config.hcs目录下新增文件用于驱动é…ç½®å‚数,(例如:vendor/vendor_hisilicon/hispark_taurus/hdf_config/hdf_test/dac_test_config.hcs)其ä¸é…ç½®å‚数如下: + 在具体产å“对应目录下新增文件用于驱动é…ç½®å‚数(例如hispark_tauruså¼€å‘æ¿ï¼švendor/hisilicon/hispark_taurus/hdf_config/hdf_test/dac_test_config.hcs),其ä¸é…ç½®å‚数如下: ```hcs root { @@ -173,6 +219,14 @@ DAC模å—适é…包å«ä»¥ä¸‹å››ä¸ªæ¥éª¤ï¼š } ``` + 需è¦æ³¨æ„的是,新增dac_config.hcsé…置文件åŽï¼Œå¿…须在hdf.hcs文件ä¸å°†å…¶åŒ…å«ï¼Œå¦åˆ™é…ç½®æ–‡ä»¶æ— æ³•ç”Ÿæ•ˆã€‚ + + 例如:本例ä¸dac_config.hcs所在路径为device/soc/hisilicon/hi3516dv300/sdk_liteos/hdf_config/dac/dac_config.hcs,则必须在产å“对应的hdf.hcsä¸æ·»åŠ 如下è¯å¥ï¼š + + ```c + #include "../../../../device/soc/hisilicon/hi3516dv300/sdk_liteos/hdf_config/dac/dac_config.hcs" // é…置文件相对路径 + ``` + 3. å®žä¾‹åŒ–æ ¸å¿ƒå±‚æŽ¥å£å‡½æ•°ï¼š - åˆå§‹åŒ–DacDeviceæˆå‘˜ã€‚ @@ -180,59 +234,59 @@ DAC模å—适é…包å«ä»¥ä¸‹å››ä¸ªæ¥éª¤ï¼š 在VirtualDacParseAndInit函数ä¸å¯¹DacDeviceæˆå‘˜è¿›è¡Œåˆå§‹åŒ–æ“作。 ```c++ - // 虚拟驱动自定义结构体 + /* 虚拟驱动自定义结构体 */ struct VirtualDacDevice { - // DAC设备结构体 + /*DAC设备结构体 */ struct DacDevice device; - // DACè®¾å¤‡å· + /* DACè®¾å¤‡å· */ uint32_t deviceNum; - // æœ‰æ•ˆé€šé“ + /* æœ‰æ•ˆé€šé“ */ uint32_t validChannel; - // DAC速率 + /* DAC速率 */ uint32_t rate; }; - // 解æžå¹¶ä¸”åˆå§‹åŒ–æ ¸å¿ƒå±‚DacDevice对象 + /* 解æžå¹¶ä¸”åˆå§‹åŒ–æ ¸å¿ƒå±‚DacDevice对象 */ static int32_t VirtualDacParseAndInit(struct HdfDeviceObject *device, const struct DeviceResourceNode *node) { - // 定义返回值 + /* 定义返回值 */ int32_t ret; - // DAC设备虚拟指针 + /* DAC设备虚拟指针 */ struct VirtualDacDevice *virtual = NULL; (void)device; - // ç»™virtual指针开辟空间 + /* ç»™virtual指针开辟空间 */ virtual = (struct VirtualDacDevice *)OsalMemCalloc(sizeof(*virtual)); if (virtual == NULL) { - // 为空则返回错误å‚æ•° + /*为空则返回错误å‚æ•° */ HDF_LOGE("%s: Malloc virtual fail!", __func__); return HDF_ERR_MALLOC_FAIL; } - // 读å–属性文件é…ç½®å‚æ•° + /* 读å–属性文件é…ç½®å‚æ•° */ ret = VirtualDacReadDrs(virtual, node); if (ret != HDF_SUCCESS) { - // 读å–失败 + /* 读å–失败 */ HDF_LOGE("%s: Read drs fail! ret:%d", __func__, ret); - // 释放virtual空间 + /* 释放virtual空间 */ OsalMemFree(virtual); - // 指针置为0 + /* 指针置为0 */ virtual = NULL; return ret; } - // åˆå§‹åŒ–虚拟指针 + /* åˆå§‹åŒ–虚拟指针 */ VirtualDacDeviceInit(virtual); - // 对DacDeviceä¸priv对象åˆå§‹åŒ– + /* 对DacDeviceä¸priv对象åˆå§‹åŒ– */ virtual->device.priv = (void *)node; - // 对DacDeviceä¸devNum对象åˆå§‹åŒ– + /* 对DacDeviceä¸devNum对象åˆå§‹åŒ– */ virtual->device.devNum = virtual->deviceNum; - // 对DacDeviceä¸ops对象åˆå§‹åŒ– + /* 对DacDeviceä¸ops对象åˆå§‹åŒ– */ virtual->device.ops = &g_method; - // æ·»åŠ DAC设备 + /* æ·»åŠ DAC设备 */ ret = DacDeviceAdd(&virtual->device); if (ret != HDF_SUCCESS) { - // æ·»åŠ è®¾å¤‡å¤±è´¥ + /* æ·»åŠ è®¾å¤‡å¤±è´¥ */ HDF_LOGE("%s: add Dac controller failed! ret = %d", __func__, ret); - // 释放virtual空间 + /* 释放virtual空间 */ OsalMemFree(virtual); - // 虚拟指针置空 + /* 虚拟指针置空 */ virtual = NULL; return ret; } @@ -253,7 +307,7 @@ DAC模å—适é…包å«ä»¥ä¸‹å››ä¸ªæ¥éª¤ï¼š uint32_t rate; //ã€å¿…è¦ã€‘é‡‡æ ·çŽ‡ }; - // DacDeviceæ˜¯æ ¸å¿ƒå±‚æŽ§åˆ¶å™¨ç»“æž„ä½“ï¼Œå…¶ä¸çš„æˆå‘˜åœ¨Init函数ä¸ä¼šè¢«èµ‹å€¼ã€‚ + /* DacDeviceæ˜¯æ ¸å¿ƒå±‚æŽ§åˆ¶å™¨ç»“æž„ä½“ï¼Œå…¶ä¸çš„æˆå‘˜åœ¨Init函数ä¸ä¼šè¢«èµ‹å€¼ã€‚ */ struct DacDevice { const struct DacMethod *ops; OsalSpinlock spin; // è‡ªæ—‹é” @@ -279,15 +333,15 @@ DAC模å—适é…包å«ä»¥ä¸‹å››ä¸ªæ¥éª¤ï¼š  **说明:**<br> DacDeviceæˆå‘˜DacMethod的定义和æˆå‘˜è¯´æ˜Žè§[接å£è¯´æ˜Ž](#接å£è¯´æ˜Ž)。 - - Init函数å‚考 + - Init函数开å‘å‚考 å…¥å‚: - HdfDeviceObject这个是整个驱动对外暴露的接å£å‚数,具备HCSé…置文件的信æ¯ã€‚ + HdfDeviceObject这个是整个驱动对外æ供的接å£å‚数,具备HCSé…置文件的信æ¯ã€‚ 返回值: - HDF_STATUS相关状æ€ï¼ˆä¸‹è¡¨ä¸ºéƒ¨åˆ†å±•ç¤ºï¼Œå¦‚需使用其他状æ€ï¼Œå¯è§//drivers/framework/include/utils/hdf_base.hä¸HDF_STATUS定义)。 + HDF_STATUS相关状æ€ï¼ˆä¸‹è¡¨ä¸ºéƒ¨åˆ†å±•ç¤ºï¼Œå¦‚需使用其他状æ€ï¼Œå¯è§//drivers/hdf_core/framework/include/utils/hdf_base.hä¸HDF_STATUS定义)。 | 状æ€(值) | 问题æè¿° | | ---------------------- | ------------- | @@ -305,48 +359,48 @@ DAC模å—适é…包å«ä»¥ä¸‹å››ä¸ªæ¥éª¤ï¼š ```c++ static int32_t VirtualDacParseAndInit(struct HdfDeviceObject *device, const struct DeviceResourceNode *node) { - // 定义返回值å‚æ•° + /* 定义返回值å‚æ•° */ int32_t ret; - // DAC设备的结构体指针 + /* DAC设备的结构体指针 */ struct VirtualDacDevice *virtual = NULL; (void)device; - // 分é…指定大å°çš„å†…å˜ + /* 分é…指定大å°çš„å†…å˜ */ virtual = (struct VirtualDacDevice *)OsalMemCalloc(sizeof(*virtual)); if (virtual == NULL) { - // 分é…内å˜å¤±è´¥ + /* 分é…内å˜å¤±è´¥ */ HDF_LOGE("%s: Malloc virtual fail!", __func__); return HDF_ERR_MALLOC_FAIL; } - // 读å–hcsä¸çš„node节点å‚æ•° + /* 读å–hcsä¸çš„node节点å‚数,函数定义è§ä¸‹æ–¹ */ ret = VirtualDacReadDrs(virtual, node); if (ret != HDF_SUCCESS) { - // 读å–节点失败 + /* 读å–节点失败 */ HDF_LOGE("%s: Read drs fail! ret:%d", __func__, ret); goto __ERR__; } - // åˆå§‹åŒ–DAC设备指针 + /* åˆå§‹åŒ–DAC设备指针 */ VirtualDacDeviceInit(virtual); - // 节点数æ®ä¼ å…¥ç§æœ‰æ•°æ® + /* 节点数æ®ä¼ å…¥ç§æœ‰æ•°æ® */ virtual->device.priv = (void *)node; - // ä¼ å…¥è®¾å¤‡å· + /* ä¼ å…¥è®¾å¤‡å· */ virtual->device.devNum = virtual->deviceNum; - // ä¼ å…¥æ–¹æ³• + /* ä¼ å…¥æ–¹æ³• */ virtual->device.ops = &g_method; - // æ·»åŠ DAC设备 + /* æ·»åŠ DAC设备 */ ret = DacDeviceAdd(&virtual->device); if (ret != HDF_SUCCESS) { - // æ·»åŠ DAC设备失败 + /* æ·»åŠ DAC设备失败 */ HDF_LOGE("%s: add Dac controller failed! ret = %d", __func__, ret); goto __ERR__; } - // æˆåŠŸæ·»åŠ DAC设备 + /* æˆåŠŸæ·»åŠ DAC设备 */ return HDF_SUCCESS; __ERR__: - // 如果指针为空 + /* 如果指针为空 */ if (virtual != NULL) { - // é‡Šæ”¾å†…å˜ + /* é‡Šæ”¾å†…å˜ */ OsalMemFree(virtual); - // 指针置空 + /* 指针置空 */ virtual = NULL; } @@ -355,36 +409,62 @@ DAC模å—适é…包å«ä»¥ä¸‹å››ä¸ªæ¥éª¤ï¼š static int32_t VirtualDacInit(struct HdfDeviceObject *device) { - // 定义返回值å‚æ•° + /* 定义返回值å‚æ•° */ int32_t ret; - // 设备结构体å节点 + /* 设备结构体å节点 */ const struct DeviceResourceNode *childNode = NULL; - // å…¥å‚æŒ‡é’ˆè¿›è¡Œåˆ¤æ– + /* å…¥å‚æŒ‡é’ˆè¿›è¡Œåˆ¤æ– */ if (device == NULL || device->property == NULL) { - // å…¥å‚指针为空 + /* å…¥å‚指针为空 */ HDF_LOGE("%s: device or property is NULL", __func__); return HDF_ERR_INVALID_OBJECT; } - // å…¥å‚指针ä¸ä¸ºç©º + /* å…¥å‚指针ä¸ä¸ºç©º */ ret = HDF_SUCCESS; DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) { - // 解æžå节点 + /* 解æžå节点 */ ret = VirtualDacParseAndInit(device, childNode); if (ret != HDF_SUCCESS) { - // 解æžå¤±è´¥ + /* 解æžå¤±è´¥ */ break; } } - // 解æžæˆåŠŸ + /* 解æžæˆåŠŸ */ return ret; } + + static int32_t VirtualDacReadDrs(struct VirtualDacDevice *virtual, const struct DeviceResourceNode *node) + { + struct DeviceResourceIface *drsOps = NULL; + + /* 获å–drsOps方法 */ + drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE); + if (drsOps == NULL || drsOps->GetUint32 == NULL || drsOps->GetUint16 == NULL) { + HDF_LOGE("%s: Invalid drs ops fail!", __func__); + return HDF_FAILURE; + } + /* å°†é…ç½®å‚æ•°ä¾æ¬¡è¯»å‡ºï¼Œå¹¶å¡«å……è‡³ç»“æž„ä½“ä¸ */ + if (drsOps->GetUint32(node, "deviceNum", &virtual->deviceNum, 0) != HDF_SUCCESS) { + HDF_LOGE("%s: Read deviceNum fail!", __func__); + return HDF_ERR_IO; + } + if (drsOps->GetUint32(node, "validChannel", &virtual->validChannel, 0) != HDF_SUCCESS) { + HDF_LOGE("%s: Read validChannel fail!", __func__); + return HDF_ERR_IO; + } + if (drsOps->GetUint32(node, "rate", &virtual->rate, 0) != HDF_SUCCESS) { + HDF_LOGE("%s: Read rate fail!", __func__); + return HDF_ERR_IO; + } + return HDF_SUCCESS; + } ``` - - Release函数å‚考 + - Release函数开å‘å‚考 å…¥å‚: - HdfDeviceObject是整个驱动对外暴露的接å£å‚数,具备HCSé…置文件的信æ¯ã€‚ + HdfDeviceObject是整个驱动对外æ供的接å£å‚数,具备HCSé…置文件的信æ¯ã€‚ 返回值: @@ -400,41 +480,41 @@ DAC模å—适é…包å«ä»¥ä¸‹å››ä¸ªæ¥éª¤ï¼š ```c++ static void VirtualDacRemoveByNode(const struct DeviceResourceNode *node) { - // 定义返回值å‚æ•° + /* 定义返回值å‚æ•° */ int32_t ret; - // 定义DACè®¾å¤‡å· + /* 定义DACè®¾å¤‡å· */ int16_t devNum; - // DAC设备结构体指针 + /* DAC设备结构体指针 */ struct DacDevice *device = NULL; - // DAC虚拟结构体指针 + /* DAC虚拟结构体指针 */ struct VirtualDacDevice *virtual = NULL; - // 设备资æºæŽ¥å£ç»“构体指针 + /* 设备资æºæŽ¥å£ç»“构体指针 */ struct DeviceResourceIface *drsOps = NULL; - // 通过实例入å£èŽ·å–è®¾å¤‡èµ„æº + /* 通过实例入å£èŽ·å–è®¾å¤‡èµ„æº */ drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE); - // å…¥å‚指判空 + /* å…¥å‚指判空 */ if (drsOps == NULL || drsOps->GetUint32 == NULL) { - // 指针为空 + /* 指针为空 */ HDF_LOGE("%s: invalid drs ops fail!", __func__); return; } - // 获å–devNumèŠ‚ç‚¹çš„æ•°æ® + /* 获å–devNumèŠ‚ç‚¹çš„æ•°æ® */ ret = drsOps->GetUint16(node, "devNum", (uint16_t *)&devNum, 0); if (ret != HDF_SUCCESS) { - //获å–失败 + /* 获å–失败 */ HDF_LOGE("%s: read devNum fail!", __func__); return; } - // 获å–DACè®¾å¤‡å· + /* 获å–DACè®¾å¤‡å· */ device = DacDeviceGet(devNum); - // 判æ–DAC设备å·ä»¥åŠæ•°æ®æ˜¯å¦ä¸ºç©º + /* 判æ–DAC设备å·ä»¥åŠæ•°æ®æ˜¯å¦ä¸ºç©º */ if (device != NULL && device->priv == node) { - // 为空释放DACè®¾å¤‡å· + /* 为空释放DACè®¾å¤‡å· */ DacDevicePut(device); - // 移除DACè®¾å¤‡å· + /* 移除DACè®¾å¤‡å· */ DacDeviceRemove(device); virtual = (struct VirtualDacDevice *)device; - // 释放虚拟指针 + /* 释放虚拟指针 */ OsalMemFree(virtual); } return; @@ -442,17 +522,17 @@ DAC模å—适é…包å«ä»¥ä¸‹å››ä¸ªæ¥éª¤ï¼š static void VirtualDacRelease(struct HdfDeviceObject *device) { - // 定义设备资æºå节点结构体指针 + /* 定义设备资æºå节点结构体指针 */ const struct DeviceResourceNode *childNode = NULL; - // å…¥å‚指针判空 + /* å…¥å‚指针判空 */ if (device == NULL || device->property == NULL) { - // å…¥å‚指针为空 + /* å…¥å‚指针为空 */ HDF_LOGE("%s: device or property is NULL", __func__); return; } DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) { - // 通过节点移除DAC + /* 通过节点移除DAC */ VirtualDacRemoveByNode(childNode); } } diff --git a/zh-cn/device-dev/driver/driver-platform-i2c-des.md b/zh-cn/device-dev/driver/driver-platform-i2c-des.md index c1bfaae6a2a00f42f61b313b03ca440f07039461..c4324343a044891d354a1f2cf1938034be16ebc1 100644 --- a/zh-cn/device-dev/driver/driver-platform-i2c-des.md +++ b/zh-cn/device-dev/driver/driver-platform-i2c-des.md @@ -3,9 +3,13 @@ ## 概述 -I2C(Inter Integrated Circuit)总线是由Philipså…¬å¸å¼€å‘的一ç§ç®€å•ã€åŒå‘二线制åŒæ¥ä¸²è¡Œæ€»çº¿ã€‚ +### 功能简介 -I2C以主从方å¼å·¥ä½œï¼Œé€šå¸¸æœ‰ä¸€ä¸ªä¸»è®¾å¤‡å’Œä¸€ä¸ªæˆ–者多个从设备,主从设备通过SDA(SerialData)串行数æ®çº¿ä»¥åŠSCL(SerialClockï¼‰ä¸²è¡Œæ—¶é’Ÿçº¿ä¸¤æ ¹çº¿ç›¸è¿žï¼Œå¦‚å›¾1所示。 +I2C(Inter Integrated Circuit)总线是由Philipså…¬å¸å¼€å‘的一ç§ç®€å•ã€åŒå‘二线制åŒæ¥ä¸²è¡Œæ€»çº¿ã€‚由于其硬件连接简å•ã€æˆæœ¬ä½Žå»‰ï¼Œå› æ¤è¢«å¹¿æ³›åº”用于å„ç§çŸè·ç¦»é€šä¿¡çš„场景。 + +### è¿ä½œæœºåˆ¶ + +I2C以主从方å¼å·¥ä½œï¼Œé€šå¸¸æœ‰ä¸€ä¸ªä¸»è®¾å¤‡å’Œä¸€ä¸ªæˆ–者多个从设备,主从设备通过SDA(SerialData)串行数æ®çº¿ä»¥åŠSCL(SerialClockï¼‰ä¸²è¡Œæ—¶é’Ÿçº¿ä¸¤æ ¹çº¿ç›¸è¿žï¼ˆå¦‚å›¾1)。 I2Cæ•°æ®çš„ä¼ è¾“å¿…é¡»ä»¥ä¸€ä¸ªèµ·å§‹ä¿¡å·ä½œä¸ºå¼€å§‹æ¡ä»¶ï¼Œä»¥ä¸€ä¸ªç»“æŸä¿¡å·ä½œä¸ºä¼ 输的åœæ¢æ¡ä»¶ã€‚æ•°æ®ä¼ 输以å—节为å•ä½ï¼Œé«˜ä½åœ¨å‰ï¼Œé€ä¸ªbitè¿›è¡Œä¼ è¾“ã€‚ @@ -19,37 +23,40 @@ I2C接å£å®šä¹‰äº†å®ŒæˆI2Cä¼ è¾“çš„é€šç”¨æ–¹æ³•é›†åˆï¼ŒåŒ…括:  +## 使用指导 -## 接å£è¯´æ˜Ž +### åœºæ™¯ä»‹ç» - **表1** I2C驱动API接å£åŠŸèƒ½ä»‹ç» +I2C通常用于与å„类支æŒI2Cåè®®çš„ä¼ æ„Ÿå™¨ã€æ‰§è¡Œå™¨æˆ–输入输出设备进行通信。 -| 功能分类 | 接å£æè¿° | -| -------- | -------- | -| I2C控制器管ç†æŽ¥å£ | - I2cOpen:打开I2C控制器<br/>- I2cClose:关é—I2C控制器 | -| I2C消æ¯ä¼ è¾“æŽ¥å£ | I2cTransferï¼šè‡ªå®šä¹‰ä¼ è¾“ | +### 接å£è¯´æ˜Ž ->  **说明:**<br> -> 本文涉åŠçš„所有接å£ï¼Œä»…é™å†…æ ¸æ€ä½¿ç”¨ï¼Œä¸æ”¯æŒåœ¨ç”¨æˆ·æ€ä½¿ç”¨ã€‚ +I2C模å—æ供的主è¦æŽ¥å£å¦‚表1所示,具体API详è§//drivers/hdf_core/framework/include/platform/i2c_if.h。 +**表1** I2C驱动API接å£åŠŸèƒ½ä»‹ç» -## 使用指导 - +| 接å£å | 接å£æè¿° | +| -------- | -------- | +| DevHandle I2cOpen(int16_t number) | 打开I2C控制器 | +| void I2cClose(DevHandle handle) | å…³é—I2C控制器 | +| int32_t I2cTransfer(DevHandle handle, struct I2cMsg \*msgs, int16_t count) | è‡ªå®šä¹‰ä¼ è¾“ | ### 使用æµç¨‹ 使用I2C设备的一般æµç¨‹å¦‚下图所示。 - **图2** I2C设备使用æµç¨‹å›¾ +**图2** I2C设备使用æµç¨‹å›¾ -  + -### 打开I2C控制器 +#### 打开I2C控制器 在进行I2C通信å‰ï¼Œé¦–å…ˆè¦è°ƒç”¨I2cOpen打开I2C控制器。 +```c DevHandle I2cOpen(int16_t number); +``` **表2** I2cOpenå‚数和返回值æè¿° @@ -62,8 +69,7 @@ DevHandle I2cOpen(int16_t number); å‡è®¾ç³»ç»Ÿä¸å˜åœ¨8个I2C控制器,编å·ä»Ž0到7,以下代ç 示例为获å–3å·æŽ§åˆ¶å™¨ï¼š - -``` +```c DevHandle i2cHandle = NULL; /* I2C控制器å¥æŸ„ / /* 打开I2C控制器 */ @@ -75,11 +81,13 @@ if (i2cHandle == NULL) { ``` -### 进行I2C通信 +#### 进行I2C通信 消æ¯ä¼ 输 +```c int32_t I2cTransfer(DevHandle handle, struct I2cMsg \*msgs, int16_t count); +``` **表3** I2cTransferå‚数和返回值æè¿° @@ -92,10 +100,10 @@ int32_t I2cTransfer(DevHandle handle, struct I2cMsg \*msgs, int16_t count); | æ£æ•´æ•° | æˆåŠŸä¼ 输的消æ¯ç»“构体数目 | | è´Ÿæ•° | 执行失败 | -I2Cä¼ è¾“æ¶ˆæ¯ç±»åž‹ä¸ºI2cMsg,æ¯ä¸ªä¼ 输消æ¯ç»“构体表示一次读或写,通过一个消æ¯æ•°ç»„,å¯ä»¥æ‰§è¡Œè‹¥å¹²æ¬¡çš„读写组åˆæ“作。 +I2Cä¼ è¾“æ¶ˆæ¯ç±»åž‹ä¸ºI2cMsg,æ¯ä¸ªä¼ 输消æ¯ç»“构体表示一次读或写,通过一个消æ¯æ•°ç»„,å¯ä»¥æ‰§è¡Œè‹¥å¹²æ¬¡çš„读写组åˆæ“作。组åˆè¯»å†™ç¤ºä¾‹ï¼š -``` +```c int32_t ret; uint8_t wbuff[2] = { 0x12, 0x13 }; uint8_t rbuff[2] = { 0 }; @@ -126,11 +134,13 @@ if (ret != 2) { > - 本函数å¯èƒ½ä¼šå¼•èµ·ç³»ç»Ÿä¼‘çœ ï¼Œä¸å…许在ä¸æ–上下文调用 -### å…³é—I2C控制器 +#### å…³é—I2C控制器 I2C通信完æˆä¹‹åŽï¼Œéœ€è¦å…³é—I2C控制器,关é—函数如下所述: +```c void I2cClose(DevHandle handle); +``` **表4** I2cCloseå‚数和返回值æè¿° @@ -138,23 +148,24 @@ void I2cClose(DevHandle handle); | -------- | -------- | | handle | I2C控制器设备å¥æŸ„ | +å…³é—I2C控制器示例: -``` +```c I2cClose(i2cHandle); /* å…³é—I2C控制器 */ ``` -## 使用示例 +### 使用示例 本例程以æ“作开å‘æ¿ä¸Šçš„I2C设备为例,详细展示I2C接å£çš„完整使用æµç¨‹ã€‚ -本例拟对Hi3516DV300æŸå¼€å‘æ¿ä¸ŠTouchPad设备进行简å•çš„寄å˜å™¨è¯»å†™è®¿é—®ï¼ŒåŸºæœ¬ç¡¬ä»¶ä¿¡æ¯å¦‚下: +本例拟对Hi3516DV300å¼€å‘æ¿ä¸ŠTouchPad设备进行简å•çš„寄å˜å™¨è¯»å†™è®¿é—®ï¼ŒåŸºæœ¬ç¡¬ä»¶ä¿¡æ¯å¦‚下: - SOC:hi3516dv300。 -- Touch IC:I2C地å€ä¸º0x38, IC内部寄å˜å™¨ä½å®½ä¸º1å—节。 +- Touch IC:I2C地å€ä¸º0x38,IC内部寄å˜å™¨ä½å®½ä¸º1å—节。 -- 原ç†å›¾ä¿¡æ¯ï¼šTouchPad设备挂接在3å·I2C控制器下;ICçš„å¤ä½ç®¡è„šä¸º3å·GPIO。 +- 硬件连接:TouchPad设备挂接在3å·I2C控制器下;ICçš„å¤ä½ç®¡è„šä¸º3å·GPIO。 本例程首先对Touch IC进行å¤ä½æ“作(开å‘æ¿ä¸Šç”µé»˜è®¤ä¼šç»™TouchIC供电,本例程ä¸è€ƒè™‘供电),然åŽå¯¹å…¶å†…部寄å˜å™¨è¿›è¡Œéšæœºè¯»å†™ï¼Œæµ‹è¯•I2C通路是å¦æ£å¸¸ã€‚ @@ -163,8 +174,7 @@ I2cClose(i2cHandle); /* å…³é—I2C控制器 */ 示例如下: - -``` +```c #include "i2c_if.h" /* I2Cæ ‡å‡†æŽ¥å£å¤´æ–‡ä»¶ */ #include "gpio_if.h" /* GPIOæ ‡å‡†æŽ¥å£å¤´æ–‡ä»¶ */ #include "hdf_log.h" /* æ ‡å‡†æ—¥å¿—æ‰“å°å¤´æ–‡ä»¶ */ diff --git a/zh-cn/device-dev/driver/driver-platform-i2c-develop.md b/zh-cn/device-dev/driver/driver-platform-i2c-develop.md index fd0a6269e01b6d32f273a2628c6c793d0d6219b4..cf8fdfa72c847a500739343cf7fb49bc4aefbc76 100755 --- a/zh-cn/device-dev/driver/driver-platform-i2c-develop.md +++ b/zh-cn/device-dev/driver/driver-platform-i2c-develop.md @@ -1,38 +1,90 @@ # I2C - ## 概述 -I2C(Inter Integrated Circuit)总线是由Philipså…¬å¸å¼€å‘的一ç§ç®€å•ã€åŒå‘二线制åŒæ¥ä¸²è¡Œæ€»çº¿ã€‚在HDF框架ä¸ï¼ŒI2C模å—接å£é€‚é…模å¼é‡‡ç”¨ç»Ÿä¸€æœåŠ¡æ¨¡å¼ï¼Œè¿™éœ€è¦ä¸€ä¸ªè®¾å¤‡æœåŠ¡æ¥ä½œä¸ºI2C模å—的管ç†å™¨ï¼Œç»Ÿä¸€å¤„ç†å¤–部访问,这会在é…置文件ä¸æœ‰æ‰€ä½“现。统一æœåŠ¡æ¨¡å¼é€‚åˆäºŽåŒç±»åž‹è®¾å¤‡å¯¹è±¡è¾ƒå¤šçš„情况,如I2Cå¯èƒ½åŒæ—¶å…·å¤‡åå‡ ä¸ªæŽ§åˆ¶å™¨ï¼Œé‡‡ç”¨ç‹¬ç«‹æœåŠ¡æ¨¡å¼éœ€è¦é…置更多的设备节点,且æœåŠ¡ä¼šå æ®å†…å˜èµ„æºã€‚ +### 功能简介<a name="section2"></a> + +I2C(Inter Integrated Circuit)总线是由Philipså…¬å¸å¼€å‘的一ç§ç®€å•ã€åŒå‘二线制åŒæ¥ä¸²è¡Œæ€»çº¿ã€‚由于其硬件连接简å•ã€æˆæœ¬ä½Žå»‰ï¼Œå› æ¤è¢«å¹¿æ³›åº”用于å„ç§çŸè·ç¦»é€šä¿¡çš„场景。 + +### è¿ä½œæœºåˆ¶ + +在HDF框架ä¸ï¼ŒåŒç±»åž‹è®¾å¤‡å¯¹è±¡è¾ƒå¤šæ—¶ï¼ˆå¯èƒ½åŒæ—¶å˜åœ¨åå‡ ä¸ªåŒç±»åž‹æŽ§åˆ¶å™¨ï¼‰ï¼Œè‹¥é‡‡ç”¨ç‹¬ç«‹æœåŠ¡æ¨¡å¼ï¼Œåˆ™éœ€è¦é…置更多的设备节点,且相关æœåŠ¡ä¼šå æ®æ›´å¤šçš„内å˜èµ„æºã€‚相å,采用统一æœåŠ¡æ¨¡å¼å¯ä»¥ä½¿ç”¨ä¸€ä¸ªè®¾å¤‡æœåŠ¡ä½œä¸ºç®¡ç†å™¨ï¼Œç»Ÿä¸€å¤„ç†æ‰€æœ‰åŒç±»åž‹å¯¹è±¡çš„外部访问(这会在é…置文件ä¸æœ‰æ‰€ä½“现),实现便æ·ç®¡ç†å’ŒèŠ‚约资æºçš„目的。I2C模å—å³é‡‡ç”¨ç»Ÿä¸€æœåŠ¡æ¨¡å¼ï¼ˆå¦‚图1)。 + +在统一模å¼ä¸‹ï¼Œæ‰€æœ‰çš„æŽ§åˆ¶å™¨éƒ½è¢«æ ¸å¿ƒå±‚ç»Ÿä¸€ç®¡ç†ï¼Œå¹¶ç”±æ ¸å¿ƒå±‚统一å‘布一个æœåŠ¡ä¾›æŽ¥å£å±‚ï¼Œå› æ¤è¿™ç§æ¨¡å¼ä¸‹é©±åŠ¨æ— 需å†ä¸ºæ¯ä¸ªæŽ§åˆ¶å™¨å‘布æœåŠ¡ã€‚ + +I2C模å—å„分层的作用为: - **图1** I2C统一æœåŠ¡æ¨¡å¼ç»“构图 +- 接å£å±‚:æ供打开设备,数æ®ä¼ 输以åŠå…³é—设备的能力。 +- æ ¸å¿ƒå±‚ï¼šä¸»è¦è´Ÿè´£æœåŠ¡ç»‘定ã€åˆå§‹åŒ–以åŠé‡Šæ”¾ç®¡ç†å™¨ï¼Œå¹¶æä¾›æ·»åŠ ã€åˆ 除以åŠèŽ·å–控制器的能力。 +- 适é…层:由驱动适é…者实现与硬件相关的具体功能,如控制器的åˆå§‹åŒ–ç‰ã€‚ -  +**图1** I2C统一æœåŠ¡æ¨¡å¼ç»“构图<a name="fig1"></a> + +## 使用指导 -## 接å£è¯´æ˜Ž +### åœºæ™¯ä»‹ç» + +I2C通常用于与å„类支æŒI2Cåè®®çš„ä¼ æ„Ÿå™¨ã€æ‰§è¡Œå™¨æˆ–输入输出设备进行通信。当驱动开å‘者需è¦å°†I2C设备适é…到OpenHarmony时,需è¦è¿›è¡ŒI2C驱动适é…,下文将介ç»å¦‚何进行I2C驱动适é…。 + +### 接å£è¯´æ˜Ž + +为了ä¿è¯ä¸Šå±‚在调用I2C接å£æ—¶èƒ½å¤Ÿæ£ç¡®çš„æ“ä½œç¡¬ä»¶ï¼Œæ ¸å¿ƒå±‚åœ¨//drivers/hdf_core/framework/support/platform/include/i2c/i2c_core.hä¸å®šä¹‰äº†ä»¥ä¸‹é’©å函数。驱动适é…者需è¦åœ¨é€‚é…层实现这些函数的具体功能,并与这些钩å函数挂接,从而完æˆæŽ¥å£å±‚ä¸Žæ ¸å¿ƒå±‚çš„äº¤äº’ã€‚ I2cMethodå’ŒI2cLockMethod定义: - -``` +```c struct I2cMethod { -int32_t (*transfer)(struct I2cCntlr *cntlr, struct I2cMsg *msgs, int16_t count); + int32_t (*transfer)(struct I2cCntlr *cntlr, struct I2cMsg *msgs, int16_t count); +}; + +struct I2cLockMethod { // é”机制æ“作结构体 + int32_t (*lock)(struct I2cCntlr *cntlr); + void (*unlock)(struct I2cCntlr *cntlr); }; -struct I2cLockMethod {// é”机制æ“作结构体 - int32_t (*lock)(struct I2cCntlr *cntlr);// åŠ é” - void (*unlock)(struct I2cCntlr *cntlr); // è§£é” +``` + +在适é…层ä¸ï¼ŒI2cMethod必须被实现,I2cLockMethodå¯æ ¹æ®å®žé™…情况考虑是å¦å®žçŽ°ã€‚æ ¸å¿ƒå±‚æ供了默认的I2cLockMethod,其ä¸ä½¿ç”¨mutex作为ä¿æŠ¤ä¸´ç•ŒåŒºçš„é”: + +```c +static int32_t I2cCntlrLockDefault(struct I2cCntlr *cntlr) +{ + if (cntlr == NULL) { + return HDF_ERR_INVALID_OBJECT; + } + return OsalMutexLock(&cntlr->lock); +} + +static void I2cCntlrUnlockDefault(struct I2cCntlr *cntlr) +{ + if (cntlr == NULL) { + return; + } + (void)OsalMutexUnlock(&cntlr->lock); +} + +static const struct I2cLockMethod g_i2cLockOpsDefault = { + .lock = I2cCntlrLockDefault, + .unlock = I2cCntlrUnlockDefault, }; ``` - **表1** I2cMethod结构体æˆå‘˜çš„回调函数功能说明 +若实际情况ä¸å…许使用mutex(例如使用者å¯èƒ½åœ¨ä¸æ–上下文调用I2C接å£ï¼Œmutexå¯èƒ½å¯¼è‡´ä¼‘çœ ï¼Œè€Œä¸æ–上下文ä¸å…è®¸ä¼‘çœ ï¼‰æ—¶ï¼Œé©±åŠ¨é€‚é…者å¯ä»¥è€ƒè™‘使用其他类型的é”æ¥å®žçŽ°ä¸€ä¸ªè‡ªå®šä¹‰çš„I2cLockMethod。一旦实现了自定义的I2cLockMethod,默认的I2cLockMethod将被覆盖。 + + **表1** I2cMethod结构体æˆå‘˜å‡½æ•°åŠŸèƒ½è¯´æ˜Ž | 函数æˆå‘˜ | å…¥å‚ | å‡ºå‚ | 返回值 | 功能 | | -------- | -------- | -------- | -------- | -------- | | transfer | cntlrï¼šç»“æž„ä½“æŒ‡é’ˆï¼Œæ ¸å¿ƒå±‚I2C控制器。<br>msgs:结构体指针,用户消æ¯ã€‚<br>count:uint16_t,消æ¯æ•°é‡ã€‚ | æ— | HDF_STATUSç›¸å…³çŠ¶æ€ | ä¼ é€’ç”¨æˆ·æ¶ˆæ¯ | + **表2** I2cLockMethod结构体æˆå‘˜å‡½æ•°åŠŸèƒ½è¯´æ˜Ž + +| 函数æˆå‘˜ | å…¥å‚ | å‡ºå‚ | 返回值 | 功能 | +| -------- | -------- | -------- | -------- | -------- | +| lock | cntlrï¼šç»“æž„ä½“æŒ‡é’ˆï¼Œæ ¸å¿ƒå±‚I2C控制器。 | æ— | HDF_STATUSç›¸å…³çŠ¶æ€ | 获å–ä¸´ç•ŒåŒºé” | +| unlock | cntlrï¼šç»“æž„ä½“æŒ‡é’ˆï¼Œæ ¸å¿ƒå±‚I2C控制器。 | æ— | HDF_STATUSç›¸å…³çŠ¶æ€ | é‡Šæ”¾ä¸´ç•ŒåŒºé” | -## å¼€å‘æ¥éª¤ +### å¼€å‘æ¥éª¤ I2C模å—适é…的三个必选环节是实例化驱动入å£ï¼Œé…置属性文件,以åŠå®žä¾‹åŒ–æ ¸å¿ƒå±‚æŽ¥å£å‡½æ•°ã€‚ @@ -57,10 +109,9 @@ I2C模å—适é…的三个必选环节是实例化驱动入å£ï¼Œé…置属性文 ã€å¯é€‰ã€‘针对新增驱动程åºï¼Œå»ºè®®éªŒè¯é©±åŠ¨åŸºæœ¬åŠŸèƒ½ï¼Œä¾‹å¦‚挂载åŽçš„ä¿¡æ¯å馈,消æ¯ä¼ 输的æˆåŠŸä¸Žå¦ç‰ã€‚ +### å¼€å‘实例 -## å¼€å‘实例 - -下方将以i2c_hi35xx.c为示例,展示需è¦åŽ‚商æ供哪些内容æ¥å®Œæ•´å®žçŽ°è®¾å¤‡åŠŸèƒ½ã€‚ +下方将以Hi3516DV300的驱动//device/soc/hisilicon/common/platform/i2c/i2c_hi35xx.c为示例,展示需è¦é©±åŠ¨é€‚é…者æ供哪些内容æ¥å®Œæ•´å®žçŽ°è®¾å¤‡åŠŸèƒ½ã€‚ 1. 驱动开å‘首先需è¦å®žä¾‹åŒ–驱动入å£ã€‚ @@ -68,131 +119,135 @@ I2C模å—适é…的三个必选环节是实例化驱动入å£ï¼Œé…置属性文 ä¸€èˆ¬åœ¨åŠ è½½é©±åŠ¨æ—¶HDF会先调用Bind函数,å†è°ƒç”¨Initå‡½æ•°åŠ è½½è¯¥é©±åŠ¨ã€‚å½“Init调用异常时,HDF框架会调用Release释放驱动资æºå¹¶é€€å‡ºã€‚ - I2C驱动入å£å‚考: + I2C驱动入å£å¼€å‘å‚考: I2CæŽ§åˆ¶å™¨ä¼šå‡ºçŽ°å¾ˆå¤šä¸ªè®¾å¤‡æŒ‚æŽ¥çš„æƒ…å†µï¼Œå› è€Œåœ¨HDF框架ä¸é¦–先会为æ¤ç±»åž‹çš„设备创建一个管ç†å™¨å¯¹è±¡ï¼Œå¹¶åŒæ—¶å¯¹å¤–å‘布一个管ç†å™¨æœåŠ¡æ¥ç»Ÿä¸€å¤„ç†å¤–éƒ¨è®¿é—®ã€‚è¿™æ ·ï¼Œç”¨æˆ·éœ€è¦æ‰“å¼€æŸä¸ªè®¾å¤‡æ—¶ï¼Œä¼šå…ˆèŽ·å–到管ç†å™¨æœåŠ¡ï¼Œç„¶åŽç®¡ç†å™¨æœåŠ¡æ ¹æ®ç”¨æˆ·æŒ‡å®šå‚数查找到指定设备。 - I2C管ç†å™¨æœåŠ¡çš„é©±åŠ¨ç”±æ ¸å¿ƒå±‚å®žçŽ°ï¼ŒåŽ‚å•†ä¸éœ€è¦å…³æ³¨è¿™éƒ¨åˆ†å†…容的实现,但在实现Init函数的时候需è¦è°ƒç”¨æ ¸å¿ƒå±‚çš„I2cCntlrAdd函数,它会实现相应功能。 + I2C管ç†å™¨æœåŠ¡çš„é©±åŠ¨ç”±æ ¸å¿ƒå±‚å®žçŽ°ï¼Œé©±åŠ¨é€‚é…者ä¸éœ€è¦å…³æ³¨è¿™éƒ¨åˆ†å†…容的实现,但在实现Init函数的时候需è¦è°ƒç”¨æ ¸å¿ƒå±‚çš„I2cCntlrAdd函数,它会实现相应功能。 - - ``` - struct HdfDriverEntry g_i2cDriverEntry = { + ```c + struct HdfDriverEntry g_i2cDriverEntry = { .moduleVersion = 1, .Init = Hi35xxI2cInit, .Release = Hi35xxI2cRelease, - .moduleName = "hi35xx_i2c_driver", // ã€å¿…è¦ä¸”与config.hcs文件里é¢åŒ¹é…】 - }; - HDF_INIT(g_i2cDriverEntry); // 调用HDF_INIT将驱动入å£æ³¨å†Œåˆ°HDFæ¡†æž¶ä¸ - - // æ ¸å¿ƒå±‚i2c_core.c管ç†å™¨æœåŠ¡çš„é©±åŠ¨å…¥å£ - struct HdfDriverEntry g_i2cManagerEntry = { + .moduleName = "hi35xx_i2c_driver", // ã€å¿…è¦ä¸”与config.hcs文件里é¢åŒ¹é…】 + }; + HDF_INIT(g_i2cDriverEntry); // 调用HDF_INIT将驱动入å£æ³¨å†Œåˆ°HDFæ¡†æž¶ä¸ + + /* æ ¸å¿ƒå±‚i2c_core.c管ç†å™¨æœåŠ¡çš„é©±åŠ¨å…¥å£ */ + struct HdfDriverEntry g_i2cManagerEntry = { .moduleVersion = 1, .Bind = I2cManagerBind, .Init = I2cManagerInit, .Release = I2cManagerRelease, - .moduleName = "HDF_PLATFORM_I2C_MANAGER", // 这与device_info文件ä¸device0对应 - }; - HDF_INIT(g_i2cManagerEntry); - ``` + .moduleName = "HDF_PLATFORM_I2C_MANAGER", // 这与device_info.hcs文件ä¸device0对应 + }; + HDF_INIT(g_i2cManagerEntry); + ``` -2. 完æˆé©±åŠ¨å…¥å£æ³¨å†Œä¹‹åŽï¼Œä¸‹ä¸€æ¥è¯·åœ¨device_info.hcs文件ä¸æ·»åŠ deviceNodeä¿¡æ¯ï¼Œå¹¶åœ¨i2c_config.hcsä¸é…置器件属性。 +2. 完æˆé©±åŠ¨å…¥å£æ³¨å†Œä¹‹åŽï¼Œä¸‹ä¸€æ¥è¯·åœ¨//vendor/hisilicon/hispark_taurus/hdf_config/device_info/device_info.hcs文件ä¸æ·»åŠ deviceNodeä¿¡æ¯ï¼Œå¹¶åœ¨i2c_config.hcsä¸é…置器件属性。 - deviceNodeä¿¡æ¯ä¸Žé©±åŠ¨å…¥å£æ³¨å†Œç›¸å…³ï¼Œå™¨ä»¶å±žæ€§å€¼å¯¹äºŽåŽ‚商驱动的实现以åŠæ ¸å¿ƒå±‚I2cCntlr相关æˆå‘˜çš„默认值或é™åˆ¶èŒƒå›´æœ‰å¯†åˆ‡å…³ç³»ã€‚ + deviceNodeä¿¡æ¯ä¸Žé©±åŠ¨å…¥å£æ³¨å†Œç›¸å…³ï¼Œå™¨ä»¶å±žæ€§å€¼å¯¹äºŽé©±åŠ¨é€‚é…者的驱动实现以åŠæ ¸å¿ƒå±‚I2cCntlr相关æˆå‘˜çš„默认值或é™åˆ¶èŒƒå›´æœ‰å¯†åˆ‡å…³ç³»ã€‚ - 统一æœåŠ¡æ¨¡å¼çš„特点是device_info文件ä¸ç¬¬ä¸€ä¸ªè®¾å¤‡èŠ‚点必须为I2C管ç†å™¨ï¼Œå…¶å„项å‚数必须如表2设置: + 统一æœåŠ¡æ¨¡å¼çš„特点是device_info.hcs文件ä¸ç¬¬ä¸€ä¸ªè®¾å¤‡èŠ‚点必须为I2C管ç†å™¨ï¼Œå…¶å„项å‚数必须如表2设置: - **表2** 统一æœåŠ¡æ¨¡å¼çš„特点 + **表3** 统一æœåŠ¡æ¨¡å¼çš„特点 - | æˆå‘˜å | 值 | - | -------- | -------- | - | moduleName | 固定为HDF_PLATFORM_I2C_MANAGER | - | serviceName | 固定为HDF_PLATFORM_I2C_MANAGER | - | policy | 具体é…置为1或2å–决于是å¦å¯¹ç”¨æˆ·æ€å¯è§ | - | deviceMatchAttr | 没有使用,å¯å¿½ç•¥ | + | æˆå‘˜å | 值 | + | -------- | -------- | + | moduleName | 固定为HDF_PLATFORM_I2C_MANAGER | + | serviceName | 固定为HDF_PLATFORM_I2C_MANAGER | + | policy | 具体é…置为1或2å–决于是å¦å¯¹ç”¨æˆ·æ€å¯è§ | + | deviceMatchAttr | 没有使用,å¯å¿½ç•¥ | - 从第二个节点开始é…置具体I2C控制器信æ¯ï¼Œæ¤èŠ‚点并ä¸è¡¨ç¤ºæŸä¸€è·¯I2C控制器,而是代表一个资æºæ€§è´¨è®¾å¤‡ï¼Œç”¨äºŽæ述一类I2C控制器的信æ¯ã€‚多个控制器之间相互区分的å‚数是busIDå’Œreg_pbase,这在i2c_config文件ä¸æœ‰æ‰€ä½“现。 + 从第二个节点开始é…置具体I2C控制器信æ¯ï¼Œæ¤èŠ‚点并ä¸è¡¨ç¤ºæŸä¸€è·¯I2C控制器,而是代表一个资æºæ€§è´¨è®¾å¤‡ï¼Œç”¨äºŽæ述一类I2C控制器的信æ¯ã€‚多个控制器之间相互区分的å‚数是busIdå’Œreg_pbase,这在i2c_config.hcs文件ä¸æœ‰æ‰€ä½“现。 - device_info.hcsé…ç½®å‚考 - - - ``` - root { - device_info { - match_attr = "hdf_manager"; - device_i2c :: device { - device0 :: deviceNode { - policy = 2; - priority = 50; - permission = 0644; - moduleName = "HDF_PLATFORM_I2C_MANAGER"; - serviceName = "HDF_PLATFORM_I2C_MANAGER"; - deviceMatchAttr = "hdf_platform_i2c_manager"; - } - device1 :: deviceNode { - policy = 0; // ç‰äºŽ0,ä¸éœ€è¦å‘布æœåŠ¡ã€‚ - priority = 55; // 驱动å¯åŠ¨ä¼˜å…ˆçº§ã€‚ - permission = 0644; // 驱动创建设备节点æƒé™ã€‚ - moduleName = "hi35xx_i2c_driver"; //ã€å¿…è¦ã€‘用于指定驱动å称,需è¦ä¸ŽæœŸæœ›çš„驱动Entryä¸çš„moduleName一致。 - serviceName = "HI35XX_I2C_DRIVER"; //ã€å¿…è¦ã€‘驱动对外å‘布æœåŠ¡çš„å称,必须唯一。 - deviceMatchAttr = "hisilicon_hi35xx_i2c"; //ã€å¿…è¦ã€‘用于é…置控制器ç§æœ‰æ•°æ®ï¼Œè¦ä¸Ži2c_config.hcsä¸å¯¹åº”控制器ä¿æŒä¸€è‡´ï¼Œ - // 具体的控制器信æ¯åœ¨ i2c_config.hcsä¸ã€‚ - } - } - } - } - ``` - - - i2c_config.hcs é…ç½®å‚考 - - - ``` - root { - platform { - i2c_config { - match_attr = "hisilicon_hi35xx_i2c"; //ã€å¿…è¦ã€‘需è¦å’Œdevice_info.hcsä¸çš„deviceMatchAttr值一致 - template i2c_controller { // 模æ¿å…¬å…±å‚数,继承该模æ¿çš„节点如果使用模æ¿ä¸çš„默认值,则节点å—段å¯ä»¥ç¼ºçœã€‚ - bus = 0; //ã€å¿…è¦ã€‘i2cè¯†åˆ«å· - reg_pbase = 0x120b0000; //ã€å¿…è¦ã€‘物ç†åŸºåœ°å€ - reg_size = 0xd1; //ã€å¿…è¦ã€‘寄å˜å™¨ä½å®½ - irq = 0; //ã€å¯é€‰ã€‘æ ¹æ®åŽ‚商需è¦æ¥ä½¿ç”¨ - freq = 400000; //ã€å¯é€‰ã€‘æ ¹æ®åŽ‚商需è¦æ¥ä½¿ç”¨ - clk = 50000000; //ã€å¯é€‰ã€‘æ ¹æ®åŽ‚商需è¦æ¥ä½¿ç”¨ - } - controller_0x120b0000 :: i2c_controller { - bus = 0; - } - controller_0x120b1000 :: i2c_controller { - bus = 1; - reg_pbase = 0x120b1000; - } - ... - } - } - } - ``` - -3. 完æˆé©±åŠ¨å…¥å£æ³¨å†Œä¹‹åŽï¼Œä¸‹ä¸€æ¥å°±æ˜¯ä»¥æ ¸å¿ƒå±‚I2cCntlr对象的åˆå§‹åŒ–ä¸ºæ ¸å¿ƒï¼ŒåŒ…æ‹¬åŽ‚å•†è‡ªå®šä¹‰ç»“æž„ä½“ï¼ˆä¼ é€’å‚数和数æ®ï¼‰ï¼Œå®žä¾‹åŒ–I2cCntlræˆå‘˜I2cMethod(让用户å¯ä»¥é€šè¿‡æŽ¥å£æ¥è°ƒç”¨é©±åŠ¨åº•å±‚函数),实现HdfDriverEntryæˆå‘˜å‡½æ•°ï¼ˆBind,Init,Release)。 + + ```c + root { + device_info { + match_attr = "hdf_manager"; + device_i2c :: device { + device0 :: deviceNode { + policy = 2; + priority = 50; + permission = 0644; + moduleName = "HDF_PLATFORM_I2C_MANAGER"; + serviceName = "HDF_PLATFORM_I2C_MANAGER"; + deviceMatchAttr = "hdf_platform_i2c_manager"; + } + device1 :: deviceNode { + policy = 0; // ç‰äºŽ0,ä¸éœ€è¦å‘布æœåŠ¡ã€‚ + priority = 55; // 驱动å¯åŠ¨ä¼˜å…ˆçº§ã€‚ + permission = 0644; // 驱动创建设备节点æƒé™ã€‚ + moduleName = "hi35xx_i2c_driver"; //ã€å¿…è¦ã€‘用于指定驱动å称,需è¦ä¸ŽæœŸæœ›çš„驱动Entryä¸çš„moduleName一致。 + serviceName = "HI35XX_I2C_DRIVER"; //ã€å¿…è¦ã€‘驱动对外å‘布æœåŠ¡çš„å称,必须唯一。 + deviceMatchAttr = "hisilicon_hi35xx_i2c"; //ã€å¿…è¦ã€‘用于é…置控制器ç§æœ‰æ•°æ®ï¼Œè¦ä¸Ži2c_config.hcsä¸å¯¹åº”控制器ä¿æŒä¸€è‡´ï¼Œ + // 具体的控制器信æ¯åœ¨ i2c_config.hcsä¸ã€‚ + } + } + } + } + ``` + + - i2c_config.hcsé…ç½®å‚考 + + ```c + root { + platform { + i2c_config { + match_attr = "hisilicon_hi35xx_i2c"; //ã€å¿…è¦ã€‘需è¦å’Œdevice_info.hcsä¸çš„deviceMatchAttr值一致 + template i2c_controller { // 模æ¿å…¬å…±å‚数,继承该模æ¿çš„节点如果使用模æ¿ä¸çš„默认值,则节点å—段å¯ä»¥ç¼ºçœã€‚ + bus = 0; //ã€å¿…è¦ã€‘i2cè¯†åˆ«å· + reg_pbase = 0x120b0000; //ã€å¿…è¦ã€‘物ç†åŸºåœ°å€ + reg_size = 0xd1; //ã€å¿…è¦ã€‘寄å˜å™¨ä½å®½ + irq = 0; //ã€å¯é€‰ã€‘ä¸æ–å·ï¼Œç”±æŽ§åˆ¶å™¨çš„ä¸æ–特性决定是å¦éœ€è¦ + freq = 400000; //ã€å¯é€‰ã€‘频率,åˆå§‹åŒ–硬件控制器的å¯é€‰å‚æ•° + clk = 50000000; //ã€å¯é€‰ã€‘控制器时钟,由控制器时钟的åˆå§‹åŒ–æµç¨‹å†³å®šæ˜¯å¦éœ€è¦ + } + controller_0x120b0000 :: i2c_controller { + bus = 0; + } + controller_0x120b1000 :: i2c_controller { + bus = 1; + reg_pbase = 0x120b1000; + } + ... + } + } + } + ``` + + 需è¦æ³¨æ„的是,新增i2c_config.hcsé…置文件åŽï¼Œå¿…须在hdf.hcs文件ä¸å°†å…¶åŒ…å«ï¼Œå¦åˆ™é…ç½®æ–‡ä»¶æ— æ³•ç”Ÿæ•ˆã€‚ + + 例如:本例ä¸i2c_config.hcs所在路径为device/soc/hisilicon/hi3516dv300/sdk_liteos/hdf_config/i2c/i2c_config.hcs,则必须在产å“对应的hdf.hcsä¸æ·»åŠ 如下è¯å¥ï¼š + + ```c + #include "../../../../device/soc/hisilicon/hi3516dv300/sdk_liteos/hdf_config/i2c/i2c_config.hcs" // é…置文件相对路径 + ``` + +3. 完æˆé©±åŠ¨å…¥å£æ³¨å†Œä¹‹åŽï¼Œä¸‹ä¸€æ¥å°±æ˜¯ä»¥æ ¸å¿ƒå±‚I2cCntlr对象的åˆå§‹åŒ–ä¸ºæ ¸å¿ƒï¼ŒåŒ…æ‹¬é©±åŠ¨é€‚é…è€…è‡ªå®šä¹‰ç»“æž„ä½“ï¼ˆä¼ é€’å‚数和数æ®ï¼‰ï¼Œå®žä¾‹åŒ–I2cCntlræˆå‘˜I2cMethod(让用户å¯ä»¥é€šè¿‡æŽ¥å£æ¥è°ƒç”¨é©±åŠ¨åº•å±‚函数),实现HdfDriverEntryæˆå‘˜å‡½æ•°ï¼ˆBind,Init,Release)。 - 自定义结构体å‚考 从驱动的角度看,自定义结构体是å‚数和数æ®çš„载体,而且i2c_config.hcs文件ä¸çš„数值会被HDF读入通过DeviceResourceIfaceæ¥åˆå§‹åŒ–结构体æˆå‘˜ï¼Œå…¶ä¸ä¸€äº›é‡è¦æ•°å€¼ä¹Ÿä¼šä¼ é€’ç»™æ ¸å¿ƒå±‚I2cCntlr对象,例如设备å·ã€æ€»çº¿å·ç‰ã€‚ - - ``` - // 厂商自定义功能结构体 + ```c + /* 驱动适é…者自定义结构体 */ struct Hi35xxI2cCntlr { struct I2cCntlr cntlr; // ã€å¿…è¦ã€‘æ˜¯æ ¸å¿ƒå±‚æŽ§åˆ¶å¯¹è±¡ï¼Œå…·ä½“æè¿°è§ä¸‹é¢ã€‚ - OsalSpinlock spin; // ã€å¿…è¦ã€‘厂商需è¦åŸºäºŽæ¤é”å˜é‡å¯¹å„个i2cæ“ä½œå‡½æ•°å®žçŽ°å¯¹åº”çš„åŠ é”解é”。 + OsalSpinlock spin; // ã€å¿…è¦ã€‘驱动适é…者需è¦åŸºäºŽæ¤é”å˜é‡å¯¹å„个i2cæ“ä½œå‡½æ•°å®žçŽ°å¯¹åº”çš„åŠ é”解é”。 volatile unsigned char *regBase; // ã€å¿…è¦ã€‘寄å˜å™¨åŸºåœ°å€ uint16_t regSize; // ã€å¿…è¦ã€‘寄å˜å™¨ä½å®½ int16_t bus; // ã€å¿…è¦ã€‘i2c_config.hcs文件ä¸å¯è¯»å–具体值 - uint32_t clk; // ã€å¯é€‰ã€‘厂商自定义 - uint32_t freq; // ã€å¯é€‰ã€‘厂商自定义 - uint32_t irq; // ã€å¯é€‰ã€‘厂商自定义 + uint32_t clk; // ã€å¯é€‰ã€‘驱动适é…者自定义 + uint32_t freq; // ã€å¯é€‰ã€‘驱动适é…者自定义 + uint32_t irq; // ã€å¯é€‰ã€‘驱动适é…者自定义 uint32_t regBasePhy; // ã€å¿…è¦ã€‘寄å˜å™¨ç‰©ç†åŸºåœ°å€ }; - // I2cCntlræ˜¯æ ¸å¿ƒå±‚æŽ§åˆ¶å™¨ç»“æž„ä½“ï¼Œå…¶ä¸çš„æˆå‘˜åœ¨Init函数ä¸ä¼šè¢«èµ‹å€¼ã€‚ + /* I2cCntlræ˜¯æ ¸å¿ƒå±‚æŽ§åˆ¶å™¨ç»“æž„ä½“ï¼Œå…¶ä¸çš„æˆå‘˜åœ¨Init函数ä¸ä¼šè¢«èµ‹å€¼ã€‚*/ struct I2cCntlr { struct OsalMutex lock; void *owner; @@ -202,31 +257,32 @@ I2C模å—适é…的三个必选环节是实例化驱动入å£ï¼Œé…置属性文 const struct I2cLockMethod *lockOps; }; ``` - - I2cCntlræˆå‘˜å›žè°ƒå‡½æ•°ç»“构体I2cMethod的实例化,和é”机制回调函数结构体I2cLockMethod实例化,其他æˆå‘˜åœ¨Init函数ä¸åˆå§‹åŒ–。 - - ``` - // i2c_hi35xx.cä¸çš„示例 + - I2cCntlræˆå‘˜é’©å函数结构体I2cMethod的实例化,和é”机制钩å函数结构体I2cLockMethod实例化,其他æˆå‘˜åœ¨Init函数ä¸åˆå§‹åŒ–。 + + ```c + /* i2c_hi35xx.cä¸çš„示例 */ static const struct I2cMethod g_method = { .transfer = Hi35xxI2cTransfer, }; static const struct I2cLockMethod g_lockOps = { - .lock = Hi35xxI2cLock, // åŠ é”函数 - .unlock = Hi35xxI2cUnlock,// 解é”函数 + .lock = Hi35xxI2cLock, // åŠ é”函数 + .unlock = Hi35xxI2cUnlock, // 解é”函数 }; ``` - - Init函数å‚考 + + - Init函数开å‘å‚考 å…¥å‚: - HdfDeviceObject是整个驱动对外暴露的接å£å‚数,具备HCSé…置文件的信æ¯ã€‚ + HdfDeviceObject是整个驱动对外æ供的接å£å‚数,具备HCSé…置文件的信æ¯ã€‚ 返回值: - HDF_STATUS相关状æ€ï¼ˆä¸‹è¡¨ä¸ºéƒ¨åˆ†å±•ç¤ºï¼Œå¦‚需使用其他状æ€ï¼Œå¯è§//drivers/framework/include/utils/hdf_base.hä¸HDF_STATUS定义)。 + HDF_STATUS相关状æ€ï¼ˆä¸‹è¡¨ä¸ºéƒ¨åˆ†å±•ç¤ºï¼Œå¦‚需使用其他状æ€ï¼Œå¯è§//drivers/hdf_core/framework/include/utils/hdf_base.hä¸HDF_STATUS定义)。 - **表3** Init函数入å‚åŠè¿”回值å‚考 + **表4** Init函数入å‚åŠè¿”回值å‚考 | 状æ€(值) | 问题æè¿° | | -------- | -------- | @@ -241,12 +297,11 @@ I2C模å—适é…的三个必选环节是实例化驱动入å£ï¼Œé…置属性文 åˆå§‹åŒ–自定义结构体对象,åˆå§‹åŒ–I2cCntlræˆå‘˜ï¼Œè°ƒç”¨æ ¸å¿ƒå±‚I2cCntlrAdd函数,接入VFS(å¯é€‰ï¼‰ã€‚ - - ``` + ```c static int32_t Hi35xxI2cInit(struct HdfDeviceObject *device) { ... - // é历ã€è§£æži2c_config.hcsä¸çš„所有é…置节点,并分别进行åˆå§‹åŒ–,需è¦è°ƒç”¨Hi35xxI2cParseAndInit函数。 + /* é历ã€è§£æži2c_config.hcsä¸çš„所有é…置节点,并分别进行åˆå§‹åŒ–,需è¦è°ƒç”¨Hi35xxI2cParseAndInit函数。*/ DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) { ret = Hi35xxI2cParseAndInit(device, childNode);//函数定义è§ä¸‹ ... @@ -257,11 +312,11 @@ I2C模å—适é…的三个必选环节是实例化驱动入å£ï¼Œé…置属性文 static int32_t Hi35xxI2cParseAndInit(struct HdfDeviceObject *device, const struct DeviceResourceNode *node) { struct Hi35xxI2cCntlr *hi35xx = NULL; - ... + ... // å…¥å‚判空 hi35xx = (struct Hi35xxI2cCntlr *)OsalMemCalloc(sizeof(*hi35xx)); // 内å˜åˆ†é… - ... + ... // è¿”å›žå€¼æ ¡éªŒ hi35xx->regBase = OsalIoRemap(hi35xx->regBasePhy, hi35xx->regSize); // 地å€æ˜ å°„ - ... + ... // è¿”å›žå€¼æ ¡éªŒ Hi35xxI2cCntlrInit(hi35xx); // ã€å¿…è¦ã€‘i2c设备的åˆå§‹åŒ– hi35xx->cntlr.priv = (void *)node; // ã€å¿…è¦ã€‘å˜å‚¨è®¾å¤‡å±žæ€§ @@ -269,13 +324,13 @@ I2C模å—适é…的三个必选环节是实例化驱动入å£ï¼Œé…置属性文 hi35xx->cntlr.ops = &g_method; // ã€å¿…è¦ã€‘I2cMethod的实例化对象的挂载 hi35xx->cntlr.lockOps = &g_lockOps; // ã€å¿…è¦ã€‘I2cLockMethod的实例化对象的挂载 (void)OsalSpinInit(&hi35xx->spin); // ã€å¿…è¦ã€‘é”çš„åˆå§‹åŒ– - ret = I2cCntlrAdd(&hi35xx->cntlr); // ã€å¿…è¦ã€‘调用æ¤å‡½æ•°å¡«å……æ ¸å¿ƒå±‚ç»“æž„ä½“ï¼Œè¿”å›žæˆåŠŸä¿¡å·åŽé©±åŠ¨æ‰å®Œå…¨æŽ¥å…¥å¹³å°æ ¸å¿ƒå±‚。 + ret = I2cCntlrAdd(&hi35xx->cntlr); // ã€å¿…è¦ã€‘调用æ¤å‡½æ•°å°†æŽ§åˆ¶å™¨å¯¹è±¡æ·»åŠ 至平å°æ ¸å¿ƒå±‚,返回æˆåŠŸä¿¡å·åŽé©±åŠ¨æ‰å®Œå…¨æŽ¥å…¥å¹³å°æ ¸å¿ƒå±‚。 ... #ifdef USER_VFS_SUPPORT - (void)I2cAddVfsById(hi35xx->cntlr.busId);// ã€å¯é€‰ã€‘若支æŒç”¨æˆ·çº§çš„虚拟文件系统,则接入。 + (void)I2cAddVfsById(hi35xx->cntlr.busId); // ã€å¯é€‰ã€‘若支æŒç”¨æˆ·çº§çš„虚拟文件系统,则接入。 #endif return HDF_SUCCESS; - __ERR__: // ä¸æˆåŠŸçš„è¯ï¼Œéœ€è¦åå‘执行åˆå§‹åŒ–相关函数。 + __ERR__: // è‹¥ä¸æˆåŠŸï¼Œéœ€è¦å›žæ»šå‡½æ•°å†…已执行的æ“作(如å–消IOæ˜ å°„ã€é‡Šæ”¾å†…å˜ç‰ï¼‰ï¼Œå¹¶è¿”回错误ç if (hi35xx != NULL) { if (hi35xx->regBase != NULL) { OsalIoUnmap((void *)hi35xx->regBase); @@ -287,11 +342,12 @@ I2C模å—适é…的三个必选环节是实例化驱动入å£ï¼Œé…置属性文 return ret; } ``` - - Release函数å‚考 + + - Release函数开å‘å‚考 å…¥å‚: - HdfDeviceObject是整个驱动对外暴露的接å£å‚数,具备HCSé…置文件的信æ¯ã€‚ + HdfDeviceObject是整个驱动对外æ供的接å£å‚数,具备HCSé…置文件的信æ¯ã€‚ 返回值: @@ -301,26 +357,25 @@ I2C模å—适é…的三个必选环节是实例化驱动入å£ï¼Œé…置属性文 释放内å˜å’Œåˆ 除控制器,该函数需è¦åœ¨é©±åŠ¨å…¥å£ç»“构体ä¸èµ‹å€¼ç»™Release接å£ï¼Œå½“HDF框架调用Init函数åˆå§‹åŒ–驱动失败时,å¯ä»¥è°ƒç”¨Release释放驱动资æºã€‚ - - ``` + ```c static void Hi35xxI2cRelease(struct HdfDeviceObject *device) { ... - // 与Hi35xxI2cInitä¸€æ ·ï¼Œéœ€è¦å°†å¯¹æ¯ä¸ªèŠ‚点分别进行释放。 + /* 与Hi35xxI2cInitä¸€æ ·ï¼Œéœ€è¦å°†æ¯ä¸ªèŠ‚点分别进行释放。*/ DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) { - Hi35xxI2cRemoveByNode(childNode);// 函数定义è§ä¸‹ + Hi35xxI2cRemoveByNode(childNode); // 函数定义如下 } } static void Hi35xxI2cRemoveByNode(const struct DeviceResourceNode *node) { ... - // ã€å¿…è¦ã€‘å¯ä»¥è°ƒç”¨I2cCntlrGet函数通过设备的busid获å–I2cCntlr对象,以åŠè°ƒç”¨I2cCntlrRemove函数æ¥é‡Šæ”¾I2cCntlr对象的内容。 + /* ã€å¿…è¦ã€‘å¯ä»¥è°ƒç”¨I2cCntlrGet函数通过设备的buså·èŽ·å–I2cCntlr对象的指针,以åŠè°ƒç”¨I2cCntlrRemove函数将I2cCntlr对象从平å°æ ¸å¿ƒå±‚移除。*/ cntlr = I2cCntlrGet(bus); if (cntlr != NULL && cntlr->priv == node) { ... I2cCntlrRemove(cntlr); - // ã€å¿…è¦ã€‘解除地å€æ˜ 射,é”和内å˜çš„释放。 + /* ã€å¿…è¦ã€‘解除地å€æ˜ 射,释放é”和内å˜ã€‚*/ hi35xx = (struct Hi35xxI2cCntlr *)cntlr; OsalIoUnmap((void *)hi35xx->regBase); (void)OsalSpinDestroy(&hi35xx->spin); diff --git a/zh-cn/device-dev/driver/driver-platform-i3c-des.md b/zh-cn/device-dev/driver/driver-platform-i3c-des.md index 24d7f0bd02a15e1942680cd80a19556bbdc2d0f3..0926a9a2be4976b86ab3c107cf356480d5b3a88c 100755 --- a/zh-cn/device-dev/driver/driver-platform-i3c-des.md +++ b/zh-cn/device-dev/driver/driver-platform-i3c-des.md @@ -35,7 +35,7 @@ I3C接å£å®šä¹‰äº†å®ŒæˆI3Cä¼ è¾“çš„é€šç”¨æ–¹æ³•é›†åˆï¼ŒåŒ…括: ### è¿ä½œæœºåˆ¶<a name="section4"></a> -在HDF框架ä¸ï¼ŒI3C模å—接å£é€‚é…模å¼é‡‡ç”¨ç»Ÿä¸€æœåŠ¡æ¨¡å¼ï¼Œè¿™éœ€è¦ä¸€ä¸ªè®¾å¤‡æœåŠ¡æ¥ä½œä¸ºI3C模å—的管ç†å™¨ï¼Œç»Ÿä¸€å¤„ç†å¤–部访问,这会在é…置文件ä¸æœ‰æ‰€ä½“现。统一æœåŠ¡æ¨¡å¼é€‚åˆäºŽåŒç±»åž‹è®¾å¤‡å¯¹è±¡è¾ƒå¤šçš„情况,如I3Cå¯èƒ½åŒæ—¶å…·å¤‡åå‡ ä¸ªæŽ§åˆ¶å™¨ï¼Œé‡‡ç”¨ç‹¬ç«‹æœåŠ¡æ¨¡å¼éœ€è¦é…置更多的设备节点,且æœåŠ¡ä¼šå æ®å†…å˜èµ„æºã€‚ +在HDF框架ä¸ï¼ŒI3C模å—接å£é€‚é…模å¼é‡‡ç”¨ç»Ÿä¸€æœåŠ¡æ¨¡å¼ï¼Œè¿™éœ€è¦ä¸€ä¸ªè®¾å¤‡æœåŠ¡æ¥ä½œä¸ºI3C模å—的管ç†å™¨ï¼Œç»Ÿä¸€å¤„ç†å¤–部访问,这会在é…置文件ä¸æœ‰æ‰€ä½“现。统一æœåŠ¡æ¨¡å¼é€‚åˆäºŽåŒç±»åž‹è®¾å¤‡å¯¹è±¡è¾ƒå¤šçš„情况,如I3Cå¯èƒ½åŒæ—¶å…·å¤‡åå‡ ä¸ªæŽ§åˆ¶å™¨ï¼Œé‡‡ç”¨ç‹¬ç«‹æœåŠ¡æ¨¡å¼éœ€è¦é…置更多的设备节点,且æœåŠ¡ä¼šå æ®å†…å˜èµ„æºã€‚相å,采用统一æœåŠ¡æ¨¡å¼å¯ä»¥ä½¿ç”¨ä¸€ä¸ªè®¾å¤‡æœåŠ¡ä½œä¸ºç®¡ç†å™¨ï¼Œç»Ÿä¸€å¤„ç†æ‰€æœ‰åŒç±»åž‹å¯¹è±¡çš„外部访问(这会在é…置文件ä¸æœ‰æ‰€ä½“现),实现便æ·ç®¡ç†å’ŒèŠ‚约资æºçš„目的。 相比于I2C,I3C总线拥有更高的速度ã€æ›´ä½Žçš„功耗,支æŒå¸¦å†…ä¸æ–ã€ä»Žè®¾å¤‡çƒæŽ¥å…¥ä»¥åŠåˆ‡æ¢å½“å‰ä¸»è®¾å¤‡ï¼ŒåŒæ—¶å‘åŽå…¼å®¹I2C从设备。一路I3C总线上,å¯ä»¥è¿žæŽ¥å¤šä¸ªè®¾å¤‡ï¼Œè¿™äº›è®¾å¤‡å¯ä»¥æ˜¯I2C从设备ã€I3C从设备和I3C次级主设备,但åªèƒ½åŒæ—¶å˜åœ¨ä¸€ä¸ªä¸»è®¾å¤‡ï¼Œä¸€èˆ¬ä¸ºæŽ§åˆ¶å™¨æœ¬èº«ã€‚ @@ -44,38 +44,41 @@ I3C接å£å®šä¹‰äº†å®ŒæˆI3Cä¼ è¾“çš„é€šç”¨æ–¹æ³•é›†åˆï¼ŒåŒ…括: ### 约æŸä¸Žé™åˆ¶<a name="section5"></a> -I3C模å—当å‰ä»…支æŒè½»é‡å’Œå°åž‹ç³»ç»Ÿå†…æ ¸ï¼ˆLiteOS)。 +I3C模å—当å‰ä»…支æŒè½»é‡å’Œå°åž‹ç³»ç»Ÿå†…æ ¸ï¼ˆLiteOS-A),ä¸æ”¯æŒåœ¨ç”¨æˆ·æ€ä½¿ç”¨ã€‚ ## 使用指导<a name="section6"></a> ### 场景介ç»<a name="section7"></a> I3Cå¯è¿žæŽ¥å•ä¸ªæˆ–多个I3Cã€I2C从器件,它主è¦ç”¨äºŽï¼š -1. ä¸Žä¼ æ„Ÿå™¨é€šä¿¡ï¼Œå¦‚é™€èžºä»ªã€æ°”压计或支æŒI3Cå议的图åƒä¼ 感器ç‰ï¼› -2. 通过软件或硬件å议转æ¢ï¼Œä¸Žå…¶ä»–接å£ï¼ˆå¦‚ UART 串å£ç‰ï¼‰çš„设备进行通信。 + +- ä¸Žä¼ æ„Ÿå™¨é€šä¿¡ï¼Œå¦‚é™€èžºä»ªã€æ°”压计或支æŒI3Cå议的图åƒä¼ 感器ç‰ï¼› +- 通过软件或硬件å议转æ¢ï¼Œä¸Žå…¶ä»–接å£ï¼ˆå¦‚ UART 串å£ç‰ï¼‰çš„设备进行通信。 ### 接å£è¯´æ˜Ž<a name="section8"></a> +I3C模å—æ供的主è¦æŽ¥å£å¦‚表1所示,具体API详è§//drivers/hdf_core/framework/include/platform/i3c_if.h。 + **表 1** I3C驱动API接å£åŠŸèƒ½ä»‹ç» <a name="table1"></a> -| 接å£å | æè¿° | +| 接å£å | 接å£æè¿° | | ------------- | ----------------- | -| I3cOpen | 打开I3C控制器 | -| I3cClose | å…³é—I3C控制器 | -| I3cTransfer | è‡ªå®šä¹‰ä¼ è¾“ | -| I3cSetConfig | é…ç½®I3C控制器 | -| I3cGetConfig | 获å–I3C控制器é…ç½® | -| I3cRequestIbi | 请求带内ä¸æ– | -| I3cFreeIbi | 释放带内ä¸æ– | +| DevHandle I3cOpen(int16_t number) | 打开I3C控制器 | +| void I3cClose(DevHandle handle) | å…³é—I3C控制器 | +| int32_t I3cTransfer(DevHandle handle, struct I3cMsg \*msg, int16_t count, enum TransMode mode) | è‡ªå®šä¹‰ä¼ è¾“ | +| int32_t I3cSetConfig(DevHandle handle, struct I3cConfig \*config) | é…ç½®I3C控制器 | +| int32_t I3cGetConfig(DevHandle handle, struct I3cConfig \*config) | 获å–I3C控制器é…ç½® | +| int32_t I3cRequestIbi(DevHandle handle, uint16_t addr, I3cIbiFunc func, uint32_t payload) | 请求带内ä¸æ– | +| int32_t I3cFreeIbi(DevHandle handle, uint16_t addr) | 释放带内ä¸æ– | > **说明:**<br> >本文涉åŠçš„所有接å£ï¼Œä»…é™å†…æ ¸æ€ä½¿ç”¨ï¼Œä¸æ”¯æŒåœ¨ç”¨æˆ·æ€ä½¿ç”¨ã€‚ ### å¼€å‘æ¥éª¤<a name="section9"></a> -I3C的使用æµç¨‹å¦‚[图2](#fig2)所示。 +I3C的使用æµç¨‹å¦‚图2所示。 **图 2** I3C使用æµç¨‹å›¾<a name="fig2"></a>  @@ -111,65 +114,15 @@ if (i3cHandle == NULL) { } ``` -#### 进行I3C通信<a name="section6"></a> - -消æ¯ä¼ 输 -```c -int32_t I3cTransfer(DevHandle handle, struct I3cMsg *msgs, int16_t count, enum TransMode mode); -``` - -**表 3** I3cTransferå‚数和返回值æè¿° - -<a name="table3"></a> - -| å‚æ•° | å‚æ•°æè¿° | -| ---------- | -------------------------------------------- | -| handle | I3C控制器å¥æŸ„ | -| msgs | å¾…ä¼ è¾“æ•°æ®çš„消æ¯ç»“构体数组 | -| count | 消æ¯æ•°ç»„长度 | -| mode | ä¼ è¾“æ¨¡å¼ï¼Œ0:I2C模å¼ï¼›1:I3C模å¼ï¼›2:å‘é€CCC | -| **返回值** | **返回值æè¿°** | -| æ£æ•´æ•° | æˆåŠŸä¼ 输的消æ¯ç»“构体数目 | -| è´Ÿæ•° | 执行失败 | - -I3Cä¼ è¾“æ¶ˆæ¯ç±»åž‹ä¸ºI3cMsg,æ¯ä¸ªä¼ 输消æ¯ç»“构体表示一次读或写,通过一个消æ¯æ•°ç»„,å¯ä»¥æ‰§è¡Œè‹¥å¹²æ¬¡çš„读写组åˆæ“作。 - -```c -int32_t ret; -uint8_t wbuff[2] = { 0x12, 0x13 }; -uint8_t rbuff[2] = { 0 }; -struct I3cMsg msgs[2]; /* è‡ªå®šä¹‰ä¼ è¾“çš„æ¶ˆæ¯ç»“构体数组 */ -msgs[0].buf = wbuff; /* å†™å…¥çš„æ•°æ® */ -msgs[0].len = 2; /* 写入数æ®é•¿åº¦ä¸º2 */ -msgs[0].addr = 0x3F; /* 写入设备地å€ä¸º0x3F */ -msgs[0].flags = 0; /* ä¼ è¾“æ ‡è®°ä¸º0,默认为写 */ -msgs[1].buf = rbuff; /* è¦è¯»å–çš„æ•°æ® */ -msgs[1].len = 2; /* 读å–æ•°æ®é•¿åº¦ä¸º2 */ -msgs[1].addr = 0x3F; /* 读å–设备地å€ä¸º0x3F */ -msgs[1].flags = I3C_FLAG_READ /* I3C_FLAG_READç½®ä½ */ -/* 进行一次I2C模å¼è‡ªå®šä¹‰ä¼ è¾“ï¼Œä¼ è¾“çš„æ¶ˆæ¯ä¸ªæ•°ä¸º2 */ -ret = I3cTransfer(i3cHandle, msgs, 2, I2C_MODE); -if (ret != 2) { - HDF_LOGE("I3cTransfer: failed, ret %d\n", ret); - return; -} -``` - -> **注æ„:** ->- I3cMsg结构体ä¸çš„设备地å€ä¸åŒ…å«è¯»å†™æ ‡å¿—ä½ï¼Œè¯»å†™ä¿¡æ¯ç”±flagsæˆå‘˜å˜é‡çš„读写控制ä½ä¼ 递。 ->- 本函数ä¸å¯¹æ¶ˆæ¯ç»“构体个数åšé™åˆ¶ï¼Œå…¶æœ€å¤§ä¸ªæ•°åº¦ç”±å…·ä½“I3C控制器决定。 ->- 本函数ä¸å¯¹æ¯ä¸ªæ¶ˆæ¯ç»“构体ä¸çš„æ•°æ®é•¿åº¦åšé™åˆ¶ï¼ŒåŒæ ·ç”±å…·ä½“I3C控制器决定。 ->- 本函数å¯èƒ½ä¼šå¼•èµ·ç³»ç»Ÿä¼‘çœ ï¼Œç¦æ¢åœ¨ä¸æ–上下文调用。 - #### 获å–I3C控制器é…ç½®<a name="section7"></a> ```c int32_t I3cGetConfig(DevHandle handle, struct I3cConfig *config); ``` -**表 4** I3cGetConfigå‚数和返回值æè¿° +**表 3** I3cGetConfigå‚数和返回值æè¿° -<a name="table4"></a> +<a name="table3"></a> | å‚æ•° | å‚æ•°æè¿° | | ---------- | -------------- | @@ -197,9 +150,9 @@ if (ret != HDF_SUCCESS) { int32_t I3cSetConfig(DevHandle handle, struct I3cConfig *config); ``` -**表 5** I3cSetConfigå‚数和返回值æè¿° +**表 4** I3cSetConfigå‚数和返回值æè¿° -<a name="table5"></a> +<a name="table4"></a> | å‚æ•° | å‚æ•°æè¿° | | ---------- | -------------- | @@ -223,6 +176,56 @@ if (ret != HDF_SUCCESS) { } ``` +#### 进行I3C通信<a name="section6"></a> + +消æ¯ä¼ 输 +```c +int32_t I3cTransfer(DevHandle handle, struct I3cMsg *msgs, int16_t count, enum TransMode mode); +``` + +**表 5** I3cTransferå‚数和返回值æè¿° + +<a name="table5"></a> + +| å‚æ•° | å‚æ•°æè¿° | +| ---------- | -------------------------------------------- | +| handle | I3C控制器å¥æŸ„ | +| msgs | å¾…ä¼ è¾“æ•°æ®çš„消æ¯ç»“构体数组 | +| count | 消æ¯æ•°ç»„长度 | +| mode | ä¼ è¾“æ¨¡å¼ï¼Œ0:I2C模å¼ï¼›1:I3C模å¼ï¼›2:å‘é€CCC | +| **返回值** | **返回值æè¿°** | +| æ£æ•´æ•° | æˆåŠŸä¼ 输的消æ¯ç»“构体数目 | +| è´Ÿæ•° | 执行失败 | + +I3Cä¼ è¾“æ¶ˆæ¯ç±»åž‹ä¸ºI3cMsg,æ¯ä¸ªä¼ 输消æ¯ç»“构体表示一次读或写,通过一个消æ¯æ•°ç»„,å¯ä»¥æ‰§è¡Œè‹¥å¹²æ¬¡çš„读写组åˆæ“作。 + +```c +int32_t ret; +uint8_t wbuff[2] = { 0x12, 0x13 }; +uint8_t rbuff[2] = { 0 }; +struct I3cMsg msgs[2]; /* è‡ªå®šä¹‰ä¼ è¾“çš„æ¶ˆæ¯ç»“构体数组 */ +msgs[0].buf = wbuff; /* å†™å…¥çš„æ•°æ® */ +msgs[0].len = 2; /* 写入数æ®é•¿åº¦ä¸º2 */ +msgs[0].addr = 0x3F; /* 写入设备地å€ä¸º0x3F */ +msgs[0].flags = 0; /* ä¼ è¾“æ ‡è®°ä¸º0,默认为写 */ +msgs[1].buf = rbuff; /* è¦è¯»å–çš„æ•°æ® */ +msgs[1].len = 2; /* 读å–æ•°æ®é•¿åº¦ä¸º2 */ +msgs[1].addr = 0x3F; /* 读å–设备地å€ä¸º0x3F */ +msgs[1].flags = I3C_FLAG_READ /* I3C_FLAG_READç½®ä½ */ +/* 进行一次I2C模å¼è‡ªå®šä¹‰ä¼ è¾“ï¼Œä¼ è¾“çš„æ¶ˆæ¯ä¸ªæ•°ä¸º2 */ +ret = I3cTransfer(i3cHandle, msgs, 2, I2C_MODE); +if (ret != 2) { + HDF_LOGE("I3cTransfer: failed, ret %d\n", ret); + return; +} +``` + +> **注æ„:** +>- I3cMsg结构体ä¸çš„设备地å€ä¸åŒ…å«è¯»å†™æ ‡å¿—ä½ï¼Œè¯»å†™ä¿¡æ¯ç”±flagsæˆå‘˜å˜é‡çš„读写控制ä½ä¼ 递。 +>- 本函数ä¸å¯¹æ¶ˆæ¯ç»“构体个数åšé™åˆ¶ï¼Œå…¶æœ€å¤§ä¸ªæ•°åº¦ç”±å…·ä½“I3C控制器决定。 +>- 本函数ä¸å¯¹æ¯ä¸ªæ¶ˆæ¯ç»“构体ä¸çš„æ•°æ®é•¿åº¦åšé™åˆ¶ï¼ŒåŒæ ·ç”±å…·ä½“I3C控制器决定。 +>- 本函数å¯èƒ½ä¼šå¼•èµ·ç³»ç»Ÿä¼‘çœ ï¼Œç¦æ¢åœ¨ä¸æ–上下文调用。 + #### 请求IBI(带内ä¸æ–)<a name="section9"></a> ```c @@ -310,9 +313,9 @@ I3C通信完æˆä¹‹åŽï¼Œéœ€è¦å…³é—I3C控制器,关é—函数如下所示: void I3cClose(DevHandle handle); ``` -**表 4** I3cCloseå‚数和返回值æè¿° +**表 8** I3cCloseå‚数和返回值æè¿° -<a name="table4"></a> +<a name="table8"></a> | å‚æ•° | å‚æ•°æè¿° | | ---------- | -------------- | @@ -326,15 +329,13 @@ I3cClose(i3cHandle); /* å…³é—I3C控制器 */ ## 使用实例<a name="section10"></a> -本例程以æ“作开å‘æ¿ä¸Šçš„I3C设备为例,详细展示I3C接å£çš„完整使用æµç¨‹ã€‚ - -由于Hi3516DV300系列SOC没有I3C控制器,本例拟在Hi3516DV300æŸå¼€å‘æ¿ä¸Šå¯¹è™šæ‹Ÿé©±åŠ¨è¿›è¡Œç®€å•çš„ä¼ è¾“æ“作,基本硬件信æ¯å¦‚下: +本例程以æ“作Hi3516DV300å¼€å‘æ¿ä¸Šçš„I3C虚拟设备为例,详细展示I3C接å£çš„完整使用æµç¨‹ï¼ŒåŸºæœ¬ç¡¬ä»¶ä¿¡æ¯å¦‚下。 - SOC:hi3516dv300。 -- 虚拟:I3C地å€ä¸º0x3f, 寄å˜å™¨ä½å®½ä¸º1å—节。 +- 虚拟I3C设备:I3C地å€ä¸º0x3f, 寄å˜å™¨ä½å®½ä¸º1å—节。 -- 原ç†å›¾ä¿¡æ¯ï¼šè™šæ‹ŸI3C设备挂接在18å·å’Œ19å·I3C控制器下。 +- 硬件连接:虚拟I3C设备挂接在18å·å’Œ19å·I3C控制器下。 本例程进行简å•çš„I3Cä¼ è¾“ï¼Œæµ‹è¯•I3C通路是å¦æ£å¸¸ã€‚ diff --git a/zh-cn/device-dev/driver/driver-platform-i3c-develop.md b/zh-cn/device-dev/driver/driver-platform-i3c-develop.md index cb91d218e6ce2baa475efed246cf8d2d1d2f1725..125f67535d37a6a4ae9bbbf8303a69155fde5b0a 100755 --- a/zh-cn/device-dev/driver/driver-platform-i3c-develop.md +++ b/zh-cn/device-dev/driver/driver-platform-i3c-develop.md @@ -6,7 +6,7 @@ I3C(Improved Inter Integrated Circuit)总线是由MIPI Allianceå¼€å‘的一ç§ç®€å•ã€ä½Žæˆæœ¬çš„åŒå‘二线制åŒæ¥ä¸²è¡Œæ€»çº¿ã€‚ -I3C是两线åŒå‘ä¸²è¡Œæ€»çº¿ï¼Œé’ˆå¯¹å¤šä¸ªä¼ æ„Ÿå™¨ä»Žè®¾å¤‡è¿›è¡Œäº†ä¼˜åŒ–ï¼Œå¹¶ä¸”ä¸€æ¬¡åªèƒ½ç”±ä¸€ä¸ªI3C主设备控制。 相比于I2C,I3C总线拥有更高的速度ã€æ›´ä½Žçš„功耗,支æŒå¸¦å†…ä¸æ–ã€ä»Žè®¾å¤‡çƒæŽ¥å…¥ä»¥åŠåˆ‡æ¢å½“å‰ä¸»è®¾å¤‡ï¼ŒåŒæ—¶å‘åŽå…¼å®¹I2C从设备。 +I3C是两线åŒå‘ä¸²è¡Œæ€»çº¿ï¼Œé’ˆå¯¹å¤šä¸ªä¼ æ„Ÿå™¨ä»Žè®¾å¤‡è¿›è¡Œäº†ä¼˜åŒ–ï¼Œå¹¶ä¸”ä¸€æ¬¡åªèƒ½ç”±ä¸€ä¸ªI3C主设备控制。相比于I2C,I3C总线拥有更高的速度ã€æ›´ä½Žçš„功耗,支æŒå¸¦å†…ä¸æ–ã€ä»Žè®¾å¤‡çƒæŽ¥å…¥ä»¥åŠåˆ‡æ¢å½“å‰ä¸»è®¾å¤‡ï¼ŒåŒæ—¶å‘åŽå…¼å®¹I2C从设备。I3Cå¢žåŠ äº†å¸¦å†…ä¸æ–(In-Bind Interrupt)功能,支æŒI3C设备进行çƒæŽ¥å…¥æ“作,弥补了I2C总线需è¦é¢å¤–å¢žåŠ ä¸æ–线æ¥å®Œæˆä¸æ–çš„ä¸è¶³ã€‚I3C总线上å…许åŒæ—¶å˜åœ¨I2C设备ã€I3C从设备和I3C次级主设备。 ### 基本概念<a name="3"></a> @@ -16,11 +16,11 @@ I3C是两线åŒå‘ä¸²è¡Œæ€»çº¿ï¼Œé’ˆå¯¹å¤šä¸ªä¼ æ„Ÿå™¨ä»Žè®¾å¤‡è¿›è¡Œäº†ä¼˜åŒ– - DAA(Dynamic Address Assignment):动æ€åœ°å€åˆ†é…。 - I3C支æŒå¯¹ä»Žè®¾å¤‡åœ°å€è¿›è¡ŒåŠ¨æ€åˆ†é…从而é¿å…地å€å†²çªã€‚在分é…动æ€åœ°å€ä¹‹å‰ï¼Œè¿žæŽ¥åˆ°I3C总线上的æ¯ä¸ªI3C设备都应以两ç§æ–¹å¼ä¹‹ä¸€æ¥å”¯ä¸€æ ‡è¯†ï¼š + I3C支æŒå¯¹ä»Žè®¾å¤‡åœ°å€è¿›è¡ŒåŠ¨æ€åˆ†é…从而é¿å…地å€å†²çªã€‚在分é…动æ€åœ°å€ä¹‹å‰ï¼Œè¿žæŽ¥åˆ°I3C总线上的æ¯ä¸ªI3C/I2C设备都应以两ç§æ–¹å¼ä¹‹ä¸€æ¥å”¯ä¸€æ ‡è¯†ï¼š - 设备å¯èƒ½æœ‰ä¸€ä¸ªç¬¦åˆI2C规范的é™æ€åœ°å€ï¼Œä¸»æœºå¯ä»¥ä½¿ç”¨æ¤é™æ€åœ°å€ã€‚ - - 在任何情况下,设备å‡åº”具有48ä½çš„临时ID。除éžè®¾å¤‡å…·æœ‰é™æ€åœ°å€ä¸”主机使用é™æ€åœ°å€ï¼Œå¦åˆ™ä¸»æœºåº”使用æ¤48ä½ä¸´æ—¶ID。 + - 在任何情况下,I3C设备å‡åº”具有48ä½çš„临时ID。除éžè®¾å¤‡å…·æœ‰é™æ€åœ°å€ä¸”主机使用é™æ€åœ°å€ï¼Œå¦åˆ™ä¸»æœºåº”使用æ¤48ä½ä¸´æ—¶ID。 - CCC(Common Command Code):通用命令代ç 。 @@ -37,31 +37,39 @@ I3C是两线åŒå‘ä¸²è¡Œæ€»çº¿ï¼Œé’ˆå¯¹å¤šä¸ªä¼ æ„Ÿå™¨ä»Žè®¾å¤‡è¿›è¡Œäº†ä¼˜åŒ– ### è¿ä½œæœºåˆ¶<a name="4"></a> -在HDF框架ä¸ï¼ŒåŒç±»åž‹æŽ§åˆ¶å™¨å¯¹è±¡è¾ƒå¤šæ—¶ï¼ˆå¯èƒ½åŒæ—¶å˜åœ¨åå‡ ä¸ªåŒç±»åž‹æŽ§åˆ¶å™¨ï¼‰ï¼Œå¦‚果采用独立æœåŠ¡æ¨¡å¼åˆ™éœ€è¦é…置更多的设备节点,且相关æœåŠ¡ä¼šå æ®æ›´å¤šçš„内å˜èµ„æºã€‚相å,采用统一æœåŠ¡æ¨¡å¼å¯ä»¥ä½¿ç”¨ä¸€ä¸ªè®¾å¤‡æœåŠ¡ä½œä¸ºç®¡ç†å™¨ï¼Œç»Ÿä¸€å¤„ç†æ‰€æœ‰åŒç±»åž‹å¯¹è±¡çš„外部访问(这会在é…置文件ä¸æœ‰æ‰€ä½“现),实现便æ·ç®¡ç†å’ŒèŠ‚约资æºçš„目的。I3C模å—接å£é€‚é…模å¼é‡‡ç”¨ç»Ÿä¸€æœåŠ¡æ¨¡å¼ï¼ˆå¦‚图1所示)。 +在HDF框架ä¸ï¼ŒåŒç±»åž‹æŽ§åˆ¶å™¨å¯¹è±¡è¾ƒå¤šæ—¶ï¼ˆå¯èƒ½åŒæ—¶å˜åœ¨åå‡ ä¸ªåŒç±»åž‹æŽ§åˆ¶å™¨ï¼‰ï¼Œå¦‚果采用独立æœåŠ¡æ¨¡å¼åˆ™éœ€è¦é…置更多的设备节点,且相关æœåŠ¡ä¼šå æ®æ›´å¤šçš„内å˜èµ„æºã€‚相å,采用统一æœåŠ¡æ¨¡å¼å¯ä»¥ä½¿ç”¨ä¸€ä¸ªè®¾å¤‡æœåŠ¡ä½œä¸ºç®¡ç†å™¨ï¼Œç»Ÿä¸€å¤„ç†æ‰€æœ‰åŒç±»åž‹å¯¹è±¡çš„外部访问(这会在é…置文件ä¸æœ‰æ‰€ä½“现),实现便æ·ç®¡ç†å’ŒèŠ‚约资æºçš„目的。I3C模å—采用统一æœåŠ¡æ¨¡å¼ï¼ˆå¦‚图1)。 I3C模å—å„分层的作用为: -- 接å£å±‚æ供打开控制器ã€ä¼ 输消æ¯ã€èŽ·å–和设置控制器å‚数以åŠå…³é—控制器的接å£ã€‚ -- æ ¸å¿ƒå±‚ä¸»è¦æ供绑定设备ã€åˆå§‹åŒ–设备以åŠé‡Šæ”¾è®¾å¤‡çš„能力。 -- 适é…层实现其他具体的功能。 - **图 1** I3C统一æœåŠ¡æ¨¡å¼<a name="fig1"></a> +- 接å£å±‚:æ供打开设备,写入数æ®ï¼Œå…³é—设备的能力。 +- æ ¸å¿ƒå±‚ï¼šä¸»è¦è´Ÿè´£æœåŠ¡ç»‘定ã€åˆå§‹åŒ–以åŠé‡Šæ”¾ç®¡ç†å™¨ï¼Œå¹¶æä¾›æ·»åŠ ã€åˆ 除以åŠèŽ·å–控制器的能力。由于框架需è¦ç»Ÿä¸€ç®¡ç†I3Cæ€»çº¿ä¸ŠæŒ‚è½½çš„æ‰€æœ‰è®¾å¤‡ï¼Œå› æ¤è¿˜æä¾›äº†æ·»åŠ ã€åˆ 除以åŠèŽ·å–设备的能力,以åŠä¸æ–回调函数。 +- 适é…层:由驱动适é…者实现与硬件相关的具体功能,如控制器的åˆå§‹åŒ–ç‰ã€‚ + +在统一模å¼ä¸‹ï¼Œæ‰€æœ‰çš„æŽ§åˆ¶å™¨éƒ½è¢«æ ¸å¿ƒå±‚ç»Ÿä¸€ç®¡ç†ï¼Œå¹¶ç”±æ ¸å¿ƒå±‚统一å‘布一个æœåŠ¡ä¾›æŽ¥å£å±‚ï¼Œå› æ¤è¿™ç§æ¨¡å¼ä¸‹é©±åŠ¨æ— 需å†ä¸ºæ¯ä¸ªæŽ§åˆ¶å™¨å‘布æœåŠ¡ã€‚ + + **图 1** I3C统一æœåŠ¡æ¨¡å¼ç»“构图<a name="fig1"></a>  ### 约æŸä¸Žé™åˆ¶<a name="5"></a> -I3C模å—当å‰ä»…支æŒè½»é‡å’Œå°åž‹ç³»ç»Ÿå†…æ ¸ï¼ˆLiteOS) 。 +I3C模å—当å‰ä»…支æŒè½»é‡å’Œå°åž‹ç³»ç»Ÿå†…æ ¸ï¼ˆLiteOS-A) 。 ## å¼€å‘指导 <a name="6"></a> ### åœºæ™¯ä»‹ç» <a name="7"></a> I3Cå¯è¿žæŽ¥å•ä¸ªæˆ–多个I3Cã€I2C从器件,它主è¦ç”¨äºŽï¼š + - ä¸Žä¼ æ„Ÿå™¨é€šä¿¡ï¼Œå¦‚é™€èžºä»ªã€æ°”压计或支æŒI3Cå议的图åƒä¼ 感器ç‰ã€‚ - 通过软件或硬件å议转æ¢ï¼Œä¸Žå…¶ä»–通信接å£ï¼ˆå¦‚UART串å£ç‰ï¼‰çš„设备进行通信。 +当驱动开å‘者需è¦å°†I3C设备适é…到OpenHarmony时,需è¦è¿›è¡ŒI3C驱动适é…,下文将介ç»å¦‚何进行I3C驱动适é…。 + ### 接å£è¯´æ˜Ž <a name="8"></a> +为了ä¿è¯ä¸Šå±‚在调用I3C接å£æ—¶èƒ½å¤Ÿæ£ç¡®çš„æ“ä½œç¡¬ä»¶ï¼Œæ ¸å¿ƒå±‚åœ¨//drivers/hdf_core/framework/support/platform/include/i3c/i3c_core.hä¸å®šä¹‰äº†ä»¥ä¸‹é’©å函数。驱动适é…者需è¦åœ¨é€‚é…层实现这些函数的具体功能,并与这些钩å函数挂接,从而完æˆæŽ¥å£å±‚ä¸Žæ ¸å¿ƒå±‚çš„äº¤äº’ã€‚ + I3cMethod定义: ```c struct I3cMethod { @@ -75,7 +83,7 @@ struct I3cMethod { }; ``` -**表1** I3cMethod结构体æˆå‘˜çš„回调函数功能说明 +**表1** I3cMethod结构体æˆå‘˜çš„é’©å函数功能说明 |函数æˆå‘˜|å…¥å‚|出å‚|返回值|功能| |-|-|-|-|-| |sendCccCmd| **cntlr**ï¼šç»“æž„ä½“æŒ‡é’ˆï¼Œæ ¸å¿ƒå±‚I3C控制器<br />**ccc**ï¼šä¼ å…¥çš„é€šç”¨å‘½ä»¤ä»£ç 结构体指针 | **ccc**ï¼šä¼ å‡ºçš„é€šç”¨å‘½ä»¤ä»£ç 结构体指针 | HDF_STATUS相关状æ€|å‘é€CCC(Common command Code,å³é€šç”¨å‘½ä»¤ä»£ç )| @@ -98,54 +106,53 @@ I3C模å—适é…的四个环节是实例化驱动入å£ã€é…置属性文件〠- 在device_info.hcs文件ä¸æ·»åŠ deviceNodeæ述。 - ã€å¯é€‰ã€‘æ·»åŠ i3c_config.hcs器件属性文件。 - + - 实例化I3C控制器对象: - åˆå§‹åŒ–I3cCntlræˆå‘˜ã€‚ - 实例化I3cCntlræˆå‘˜I3cMethod方法集åˆï¼Œå…¶å®šä¹‰å’Œæˆå‘˜å‡½æ•°è¯´æ˜Žè§ä¸‹æ–‡ã€‚ - + - 注册ä¸æ–处ç†å程åºï¼š 为控制器注册ä¸æ–处ç†ç¨‹åºï¼Œå®žçŽ°è®¾å¤‡çƒæŽ¥å…¥å’ŒIBI(带内ä¸æ–)功能。 1. å®žä¾‹åŒ–é©±åŠ¨å…¥å£ - 驱动入å£å¿…须为HdfDriverEntry(在hdf_device_desc.hä¸å®šä¹‰ï¼‰ç±»åž‹çš„全局å˜é‡ï¼Œä¸”moduleNameè¦å’Œdevice_info.hcsä¸ä¿æŒä¸€è‡´ã€‚HDFæ¡†æž¶ä¼šå°†æ‰€æœ‰åŠ è½½çš„é©±åŠ¨çš„HdfDriverEntry对象首地å€æ±‡æ€»ï¼Œå½¢æˆä¸€ä¸ªç±»ä¼¼æ•°ç»„的段地å€ç©ºé—´ï¼Œæ–¹ä¾¿ä¸Šå±‚调用。 - + 驱动入å£å¿…须为HdfDriverEntry(在//drivers/hdf_core/framework/include/core/hdf_device_desc.hä¸å®šä¹‰ï¼‰ç±»åž‹çš„全局å˜é‡ï¼Œä¸”moduleNameè¦å’Œdevice_info.hcsä¸ä¿æŒä¸€è‡´ã€‚HDFæ¡†æž¶ä¼šå°†æ‰€æœ‰åŠ è½½çš„é©±åŠ¨çš„HdfDriverEntry对象首地å€æ±‡æ€»ï¼Œå½¢æˆä¸€ä¸ªç±»ä¼¼æ•°ç»„的段地å€ç©ºé—´ï¼Œæ–¹ä¾¿ä¸Šå±‚调用。 + ä¸€èˆ¬åœ¨åŠ è½½é©±åŠ¨æ—¶HDF会先调用Bind函数,å†è°ƒç”¨Initå‡½æ•°åŠ è½½è¯¥é©±åŠ¨ã€‚å½“Init调用异常时,HDF框架会调用Release释放驱动资æºå¹¶é€€å‡ºã€‚ - + I3C驱动入å£å‚考: - >  **说明:**<br> > I3CæŽ§åˆ¶å™¨ä¼šå‡ºçŽ°å¾ˆå¤šä¸ªæŽ§åˆ¶å™¨æŒ‚æŽ¥çš„æƒ…å†µï¼Œå› è€Œåœ¨HDF框架ä¸é¦–先会为æ¤ç±»åž‹çš„控制器创建一个管ç†å™¨å¯¹è±¡ï¼Œå¹¶åŒæ—¶å¯¹å¤–å‘布一个管ç†å™¨æœåŠ¡æ¥ç»Ÿä¸€å¤„ç†å¤–éƒ¨è®¿é—®ã€‚è¿™æ ·ï¼Œç”¨æˆ·éœ€è¦æ‰“å¼€æŸä¸ªæŽ§åˆ¶å™¨æ—¶ï¼Œä¼šå…ˆèŽ·å–到管ç†å™¨æœåŠ¡ï¼Œç„¶åŽç®¡ç†å™¨æœåŠ¡æ ¹æ®ç”¨æˆ·æŒ‡å®šå‚数查找到指定控制器。 > - > I3C管ç†å™¨æœåŠ¡çš„é©±åŠ¨ç”±æ ¸å¿ƒå±‚å®žçŽ°ï¼ŒåŽ‚å•†ä¸éœ€è¦å…³æ³¨è¿™éƒ¨åˆ†å†…容的实现,但在实现Init函数的时候需è¦è°ƒç”¨æ ¸å¿ƒå±‚çš„I3cCntlrAdd函数,它会实现相应功能。 + > I3C管ç†å™¨æœåŠ¡çš„é©±åŠ¨ç”±æ ¸å¿ƒå±‚å®žçŽ°ï¼Œé©±åŠ¨é€‚é…者ä¸éœ€è¦å…³æ³¨è¿™éƒ¨åˆ†å†…容的实现,但在实现Init函数的时候需è¦è°ƒç”¨æ ¸å¿ƒå±‚çš„I3cCntlrAdd函数,它会实现相应功能。 ```c static struct HdfDriverEntry g_virtualI3cDriverEntry = { .moduleVersion = 1, .Init = VirtualI3cInit, .Release = VirtualI3cRelease, - .moduleName = "virtual_i3c_driver", // ã€å¿…è¦ä¸”与hcs文件ä¸çš„åå—匹é…】 + .moduleName = "virtual_i3c_driver", // ã€å¿…è¦ä¸”与hcs文件ä¸çš„åå—匹é…】 }; - HDF_INIT(g_virtualI3cDriverEntry); // 调用HDF_INIT将驱动入å£æ³¨å†Œåˆ°HDFæ¡†æž¶ä¸ + HDF_INIT(g_virtualI3cDriverEntry); // 调用HDF_INIT将驱动入å£æ³¨å†Œåˆ°HDFæ¡†æž¶ä¸ /* æ ¸å¿ƒå±‚i3c_core.c管ç†å™¨æœåŠ¡çš„é©±åŠ¨å…¥å£ */ struct HdfDriverEntry g_i3cManagerEntry = { .moduleVersion = 1, .Init = I3cManagerInit, .Release = I3cManagerRelease, - .moduleName = "HDF_PLATFORM_I3C_MANAGER",// 这与device_info文件ä¸device0对应 + .moduleName = "HDF_PLATFORM_I3C_MANAGER", // 这与device_info.hcs文件ä¸device0对应 }; HDF_INIT(g_i3cManagerEntry); ``` 2. é…置属性文件 - 完æˆé©±åŠ¨å…¥å£æ³¨å†Œä¹‹åŽï¼Œä¸‹ä¸€æ¥è¯·åœ¨device_info.hcs文件ä¸æ·»åŠ deviceNodeä¿¡æ¯ï¼Œå¹¶åœ¨i3c_config.hcsä¸é…置器件属性。 + 完æˆé©±åŠ¨å…¥å£æ³¨å†Œä¹‹åŽï¼Œä¸‹ä¸€æ¥è¯·åœ¨//vendor/hisilicon/hispark_taurus/hdf_config/device_info/device_info.hcs文件ä¸æ·»åŠ deviceNodeä¿¡æ¯ï¼Œå¹¶åœ¨i3c_config.hcsä¸é…置器件属性。 - deviceNodeä¿¡æ¯ä¸Žé©±åŠ¨å…¥å£æ³¨å†Œç›¸å…³ï¼Œå™¨ä»¶å±žæ€§å€¼å¯¹äºŽåŽ‚商驱动的实现以åŠæ ¸å¿ƒå±‚I3cCntlr相关æˆå‘˜çš„默认值或é™åˆ¶èŒƒå›´æœ‰å¯†åˆ‡å…³ç³»ã€‚ + deviceNodeä¿¡æ¯ä¸Žé©±åŠ¨å…¥å£æ³¨å†Œç›¸å…³ï¼Œå™¨ä»¶å±žæ€§å€¼å¯¹äºŽé©±åŠ¨é€‚é…者的驱动实现以åŠæ ¸å¿ƒå±‚I3cCntlr相关æˆå‘˜çš„默认值或é™åˆ¶èŒƒå›´æœ‰å¯†åˆ‡å…³ç³»ã€‚ - 统一æœåŠ¡æ¨¡å¼çš„特点是device_info文件ä¸ç¬¬ä¸€ä¸ªè®¾å¤‡èŠ‚点必须为I3C管ç†å™¨ï¼Œå…¶å„项å‚数必须如下设置: + 统一æœåŠ¡æ¨¡å¼çš„特点是device_info.hcs文件ä¸ç¬¬ä¸€ä¸ªè®¾å¤‡èŠ‚点必须为I3C管ç†å™¨ï¼Œå…¶å„项å‚数必须如下设置: |æˆå‘˜å|值| |-|-| @@ -154,7 +161,7 @@ I3C模å—适é…的四个环节是实例化驱动入å£ã€é…置属性文件〠|policy|0| |cntlrMatchAttr| æ— ï¼ˆé¢„ç•™ï¼‰| - 从第二个节点开始é…置具体I3C控制器信æ¯ï¼Œæ¤èŠ‚点并ä¸è¡¨ç¤ºæŸä¸€è·¯I3C控制器,而是代表一个资æºæ€§è´¨è®¾å¤‡ï¼Œç”¨äºŽæ述一类I3C控制器的信æ¯ã€‚本例åªæœ‰ä¸€ä¸ªI3C控制器,如有多个控制器,则需è¦åœ¨device_infoæ–‡ä»¶å¢žåŠ deviceNodeä¿¡æ¯ï¼Œä»¥åŠåœ¨i3c_config文件ä¸å¢žåŠ 对应的器件属性。 + 从第二个节点开始é…置具体I3C控制器信æ¯ï¼Œæ¤èŠ‚点并ä¸è¡¨ç¤ºæŸä¸€è·¯I3C控制器,而是代表一个资æºæ€§è´¨è®¾å¤‡ï¼Œç”¨äºŽæ述一类I3C控制器的信æ¯ã€‚本例åªæœ‰ä¸€ä¸ªI3C控制器,如有多个控制器,则需è¦åœ¨device_info.hcsæ–‡ä»¶å¢žåŠ deviceNodeä¿¡æ¯ï¼Œä»¥åŠåœ¨i3c_config文件ä¸å¢žåŠ 对应的器件属性。 - device_info.hcsé…ç½®å‚考 @@ -207,13 +214,21 @@ I3C模å—适é…的四个环节是实例化驱动入å£ã€é…置属性文件〠} ``` + 需è¦æ³¨æ„的是,新增i3c_config.hcsé…置文件åŽï¼Œå¿…须在hdf.hcs文件ä¸å°†å…¶åŒ…å«ï¼Œå¦åˆ™é…ç½®æ–‡ä»¶æ— æ³•ç”Ÿæ•ˆã€‚ + + 例如:本例ä¸i3c_config.hcs所在路径为device/soc/hisilicon/hi3516dv300/sdk_liteos/hdf_config/i3c/i3c_config.hcs,则必须在产å“对应的hdf.hcsä¸æ·»åŠ 如下è¯å¥ï¼š + + ```c + #include "../../../../device/soc/hisilicon/hi3516dv300/sdk_liteos/hdf_config/i3c/i3c_config.hcs" // é…置文件相对路径 + ``` + 3. 实例化I3C控制器对象 - é…置属性文件完æˆåŽï¼Œè¦ä»¥æ ¸å¿ƒå±‚I3cCntlr对象的åˆå§‹åŒ–ä¸ºæ ¸å¿ƒï¼ŒåŒ…æ‹¬åŽ‚å•†è‡ªå®šä¹‰ç»“æž„ä½“ï¼ˆä¼ é€’å‚数和数æ®ï¼‰ï¼Œå®žä¾‹åŒ–I3cCntlræˆå‘˜I3cMethod(让用户å¯ä»¥é€šè¿‡æŽ¥å£æ¥è°ƒç”¨é©±åŠ¨åº•å±‚函数)。 + é…置属性文件完æˆåŽï¼Œè¦ä»¥æ ¸å¿ƒå±‚I3cCntlr对象的åˆå§‹åŒ–ä¸ºæ ¸å¿ƒï¼ŒåŒ…æ‹¬é©±åŠ¨é€‚é…è€…è‡ªå®šä¹‰ç»“æž„ä½“ï¼ˆä¼ é€’å‚数和数æ®ï¼‰ï¼Œå®žä¾‹åŒ–I3cCntlræˆå‘˜I3cMethod(让用户å¯ä»¥é€šè¿‡æŽ¥å£æ¥è°ƒç”¨é©±åŠ¨åº•å±‚函数)。 æ¤æ¥éª¤éœ€è¦é€šè¿‡å®žçŽ°HdfDriverEntryæˆå‘˜å‡½æ•°ï¼ˆBind,Init,Release)æ¥å®Œæˆã€‚ - I3cCntlræˆå‘˜å›žè°ƒå‡½æ•°ç»“构体I3cMethod的实例化,I3cLockMethod回调函数结构体本例未实现,若è¦å®žä¾‹åŒ–,å¯å‚考I2C驱动开å‘,其他æˆå‘˜åœ¨Init函数ä¸åˆå§‹åŒ–。 + I3cCntlræˆå‘˜é’©å函数结构体I3cMethod的实例化,I3cLockMethodé’©å函数结构体本例未实现,若è¦å®žä¾‹åŒ–,å¯å‚考I2C驱动开å‘,其他æˆå‘˜åœ¨Init函数ä¸åˆå§‹åŒ–。 - 自定义结构体å‚考 @@ -222,11 +237,11 @@ I3C模å—适é…的四个环节是实例化驱动入å£ã€é…置属性文件〠```c struct VirtualI3cCntlr { - struct I3cCntlr cntlr; // ã€å¿…è¦ã€‘æ˜¯æ ¸å¿ƒå±‚æŽ§åˆ¶å¯¹è±¡ï¼Œå…·ä½“æè¿°è§ä¸‹é¢ã€‚ - volatile unsigned char *regBase;// ã€å¿…è¦ã€‘寄å˜å™¨åŸºåœ°å€ - uint32_t regBasePhy; // ã€å¿…è¦ã€‘寄å˜å™¨ç‰©ç†åŸºåœ°å€ - uint32_t regSize; // ã€å¿…è¦ã€‘寄å˜å™¨ä½å®½ - uint16_t busId; // ã€å¿…è¦ã€‘è®¾å¤‡å· + struct I3cCntlr cntlr; // ã€å¿…è¦ã€‘æ˜¯æ ¸å¿ƒå±‚æŽ§åˆ¶å¯¹è±¡ï¼Œå…·ä½“æè¿°è§ä¸‹é¢ã€‚ + volatile unsigned char *regBase; // ã€å¿…è¦ã€‘寄å˜å™¨åŸºåœ°å€ + uint32_t regBasePhy; // ã€å¿…è¦ã€‘寄å˜å™¨ç‰©ç†åŸºåœ°å€ + uint32_t regSize; // ã€å¿…è¦ã€‘寄å˜å™¨ä½å®½ + uint16_t busId; // ã€å¿…è¦ã€‘è®¾å¤‡å· uint16_t busMode; uint16_t IrqNum; uint32_t i3cMaxRate; @@ -249,17 +264,15 @@ I3C模å—适é…的四个环节是实例化驱动入å£ã€é…置属性文件〠}; ``` - - - - Init函数å‚考 + - Init函数开å‘å‚考 **å…¥å‚:** - HdfDeviceObject是整个驱动对外暴露的接å£å‚数,具备HCSé…置文件的信æ¯ã€‚ + HdfDeviceObject是整个驱动对外æ供的接å£å‚数,具备HCSé…置文件的信æ¯ã€‚ **返回值:** - HDF_STATUS相关状æ€ï¼ˆä¸‹è¡¨ä¸ºéƒ¨åˆ†å±•ç¤ºï¼Œå¦‚需使用其他状æ€ï¼Œå¯è§//drivers/framework/include/utils/hdf_base.hä¸HDF_STATUS 定义)。 + HDF_STATUS相关状æ€ï¼ˆä¸‹è¡¨ä¸ºéƒ¨åˆ†å±•ç¤ºï¼Œå¦‚需使用其他状æ€ï¼Œå¯è§//drivers/hdf_core/framework/include/utils/hdf_base.hä¸HDF_STATUS 定义)。 |状æ€(值)|问题æè¿°| @@ -279,7 +292,7 @@ I3C模å—适é…的四个环节是实例化驱动入å£ã€é…置属性文件〠static int32_t VirtualI3cParseAndInit(struct HdfDeviceObject *device, const struct DeviceResourceNode *node) { int32_t ret; - struct VirtualI3cCntlr *virtual = NULL; // ã€å¿…è¦ã€‘自定义结构体对象 + struct VirtualI3cCntlr *virtual = NULL; // ã€å¿…è¦ã€‘自定义结构体对象 (void)device; virtual = (struct VirtualI3cCntlr *)OsalMemCalloc(sizeof(*virtual)); // ã€å¿…è¦ã€‘内å˜åˆ†é… @@ -288,7 +301,7 @@ I3C模å—适é…的四个环节是实例化驱动入å£ã€é…置属性文件〠return HDF_ERR_MALLOC_FAIL; } - ret = VirtualI3cReadDrs(virtual, node); // ã€å¿…è¦ã€‘å°†i3c_configæ–‡ä»¶çš„é»˜è®¤å€¼å¡«å……åˆ°ç»“æž„ä½“ä¸ + ret = VirtualI3cReadDrs(virtual, node); // ã€å¿…è¦ã€‘å°†i3c_config文件的默认值填充到结构体ä¸ï¼Œå‡½æ•°å®šä¹‰è§ä¸‹æ–¹ if (ret != HDF_SUCCESS) { HDF_LOGE("%s: Read drs fail! ret:%d", __func__, ret); goto __ERR__; @@ -342,13 +355,40 @@ I3C模å—适é…的四个环节是实例化驱动入å£ã€é…置属性文件〠return ret; } + + static int32_t VirtualI3cReadDrs(struct VirtualI3cCntlr *virtual, const struct DeviceResourceNode *node) + { + struct DeviceResourceIface *drsOps = NULL; + + /* 获å–drsOps方法 */ + drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE); + if (drsOps == NULL || drsOps->GetUint32 == NULL || drsOps->GetUint16 == NULL) { + HDF_LOGE("%s: Invalid drs ops fail!", __func__); + return HDF_FAILURE; + } + /* å°†é…ç½®å‚æ•°ä¾æ¬¡è¯»å‡ºï¼Œå¹¶å¡«å……è‡³ç»“æž„ä½“ä¸ */ + if (drsOps->GetUint16(node, "busId", &virtual->busId, 0) != HDF_SUCCESS) { + HDF_LOGE("%s: Read busId fail!", __func__); + return HDF_ERR_IO; + } + if (drsOps->GetUint16(node, "busMode", &virtual->busMode, 0) != HDF_SUCCESS) { + HDF_LOGE("%s: Read busMode fail!", __func__); + return HDF_ERR_IO; + } + if (drsOps->GetUint16(node, "IrqNum", &virtual->IrqNum, 0) != HDF_SUCCESS) { + HDF_LOGE("%s: Read IrqNum fail!", __func__); + return HDF_ERR_IO; + } + ··· + return HDF_SUCCESS; + } ``` - - Release函数å‚考 + - Release函数开å‘å‚考 **å…¥å‚:** - HdfDeviceObject是整个驱动对外暴露的接å£å‚数,具备HCSé…置文件的信æ¯ã€‚ + HdfDeviceObject是整个驱动对外æ供的接å£å‚数,具备HCSé…置文件的信æ¯ã€‚ **返回值:** @@ -386,8 +426,8 @@ I3C模å—适é…的四个环节是实例化驱动入å£ã€é…置属性文件〠cntlr = I3cCntlrGet(busId); if (cntlr != NULL && cntlr->priv == node) { I3cCntlrPut(cntlr); - I3cCntlrRemove(cntlr); // ã€å¿…è¦ã€‘主è¦æ˜¯ä»Žç®¡ç†å™¨é©±åŠ¨é‚£è¾¹ç§»é™¤I3cCntlr对象 - virtual = (struct VirtualI3cCntlr *)cntlr;// ã€å¿…è¦ã€‘通过强制转æ¢èŽ·å–自定义的对象并进行releaseæ“作 + I3cCntlrRemove(cntlr); // ã€å¿…è¦ã€‘主è¦æ˜¯ä»Žç®¡ç†å™¨é©±åŠ¨é‚£è¾¹ç§»é™¤I3cCntlr对象 + virtual = (struct VirtualI3cCntlr *)cntlr; // ã€å¿…è¦ã€‘通过强制转æ¢èŽ·å–自定义的对象并进行releaseæ“作 (void)OsalSpinDestroy(&virtual->spin); OsalMemFree(virtual); } @@ -405,7 +445,7 @@ I3C模å—适é…的四个环节是实例化驱动入å£ã€é…置属性文件〠return; } ... - // é历ã€è§£æži3c_config.hcsä¸çš„所有é…置节点,并分别进行releaseæ“作 + /* é历ã€è§£æži3c_config.hcsä¸çš„所有é…置节点,并分别进行releaseæ“作 */ DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) { VirtualI3cRemoveByNode(childNode); //函数定义如上 } @@ -438,12 +478,10 @@ I3C模å—适é…的四个环节是实例化驱动入å£ã€é…置属性文件〠HDF_LOGD("%s: Reserved address which is not supported!", __func__); break; } - + return HDF_SUCCESS; } - ``` - - ```c + static int32_t I3cIbiHandle(uint32_t irq, void *data) { struct VirtualI3cCntlr *virtual = NULL; diff --git a/zh-cn/device-dev/driver/driver-platform-mipicsi-des.md b/zh-cn/device-dev/driver/driver-platform-mipicsi-des.md index 7fb0abc67f48187518dc435dbcff153f92bf9a3c..31aad8035c3f0b6eafdfafbc93a93b5dcb3a61a1 100755 --- a/zh-cn/device-dev/driver/driver-platform-mipicsi-des.md +++ b/zh-cn/device-dev/driver/driver-platform-mipicsi-des.md @@ -1,7 +1,8 @@ -# MIPI CSI<a name="title_MIPI_CSIDes"></a> +# MIPI CSI +## 概述 -## 概述<a name="section1_MIPI_CSIDes"></a> +### 功能简介 CSI(Camera Serial Interface)是由MIPIè”盟下Camera工作组指定的接å£æ ‡å‡†ã€‚CSI-2是MIPI CSI第二版,主è¦ç”±åº”用层ã€å议层ã€ç‰©ç†å±‚组æˆï¼Œæœ€å¤§æ”¯æŒ4通é“æ•°æ®ä¼ 输ã€å•çº¿ä¼ 输速度高达1Gb/s。 @@ -9,12 +10,62 @@ CSI(Camera Serial Interface)是由MIPIè”盟下Camera工作组指定的接 图1显示了简化的CSI接å£ã€‚D-PHY采用1对æºåŒæ¥çš„差分时钟和1~4对差分数æ®çº¿æ¥è¿›è¡Œæ•°æ®ä¼ 输。数æ®ä¼ 输采用DDRæ–¹å¼ï¼Œå³åœ¨æ—¶é’Ÿçš„上下边沿都有数æ®ä¼ 输。 - **图 1** CSIå‘é€ã€æŽ¥æ”¶æŽ¥å£<a name="fig1_MIPI_CSIDes"></a> -  +**图1** CSIå‘é€ã€æŽ¥æ”¶æŽ¥å£<a name="fig1_MIPI_CSIDes"></a> + -### ComboDevAttr结构体<a name="section1.1_MIPI_CSIDes"></a> +MIPI CSIæ ‡å‡†åˆ†ä¸ºåº”ç”¨å±‚ã€å议层与物ç†å±‚,å议层åˆç»†åˆ†ä¸ºåƒç´ å—节转æ¢å±‚ã€ä½Žçº§å议层ã€Lane管ç†å±‚。 -**表** **1** ComboDevAttrç»“æž„ä½“ä»‹ç» +- 物ç†å±‚(PHY Layer) + + PHYå±‚æŒ‡å®šäº†ä¼ è¾“åª’ä»‹ï¼Œåœ¨ç”µæ°”å±‚é¢ä»Žä¸²è¡Œbitæµä¸æ•æ‰â€œ0â€ä¸Žâ€œ1â€ï¼ŒåŒæ—¶ç”ŸæˆSoT与EoTç‰ä¿¡å·ã€‚ + +- å议层(Protocol Layer) + + å议层由三个å层组æˆï¼Œæ¯ä¸ªå层有ä¸åŒçš„èŒè´£ã€‚CSI-2å议能够在host侧处ç†å™¨ä¸Šç”¨ä¸€ä¸ªå•ç‹¬çš„接å£å¤„ç†å¤šæ¡æ•°æ®æµã€‚å议层规定了多æ¡æ•°æ®æµè¯¥å¦‚ä½•æ ‡è®°å’Œäº¤ç»‡èµ·æ¥ï¼Œä»¥ä¾¿æ¯æ¡æ•°æ®æµèƒ½å¤Ÿè¢«æ£ç¡®åœ°æ¢å¤å‡ºæ¥ã€‚ + + - åƒç´ å—节转æ¢å±‚(Pixel/Byte Packing/Unpacking Layer) + + CSI-2规范支æŒå¤šç§ä¸åŒåƒç´ æ ¼å¼çš„图åƒåº”用。在å‘é€æ–¹ä¸ï¼Œæœ¬å±‚在å‘é€æ•°æ®åˆ°Low Level Protocol层之å‰ï¼Œå°†æ¥è‡ªåº”用层的åƒç´ å°åŒ…为å—节数æ®ã€‚在接收方ä¸ï¼Œæœ¬å±‚在å‘é€æ•°æ®åˆ°åº”用层之å‰ï¼Œå°†æ¥è‡ªLow Level Protocol层的å—节数æ®è§£åŒ…为åƒç´ 。8ä½çš„åƒç´ æ•°æ®åœ¨æœ¬å±‚ä¸ä¼ 输时ä¿æŒä¸å˜ã€‚ + + - 低级å议层(Low Level Protocol) + + LLP主è¦åŒ…å«äº†åœ¨SoTå’ŒEoT事件之间的bitå’Œbyte级别的åŒæ¥æ–¹æ³•ï¼Œä»¥åŠå’Œä¸‹ä¸€å±‚ä¼ é€’æ•°æ®çš„方法。LLP最å°æ•°æ®ç²’度是1个å—节。LLP也包å«äº†ä¸€ä¸ªå—节内的bit值解æžï¼Œå³Endian(大å°ç«¯é‡Œçš„Endiançš„æ„æ€)的处ç†ã€‚ + + - Lane管ç†å±‚(Lane Management) + + CSI-2çš„Lane是å¯æ‰©å±•çš„。具体的数æ®Laneçš„æ•°é‡è§„范并没有给出é™åˆ¶ï¼Œå…·ä½“æ ¹æ®åº”用的带宽需求而定。å‘é€ä¾§åˆ†å‘(distributor功能)æ¥è‡ªå‡ºå£æ–¹å‘æ•°æ®æµçš„å—节到1æ¡æˆ–多æ¡Lane上。接收侧则从一æ¡æˆ–多æ¡Laneä¸æ”¶é›†å—节并åˆå¹¶ï¼ˆmerge功能)到一个数æ®æµä¸Šï¼Œå¤åŽŸå‡ºåŽŸå§‹æµçš„å—节顺åºã€‚对于C-PHY物ç†å±‚æ¥è¯´ï¼Œæœ¬å±‚专门分å‘å—节对(16 bits)到数æ®Lane或从数æ®Laneä¸æ”¶é›†å—节对。基于æ¯Lane的扰ç 功能是å¯é€‰ç‰¹æ€§ã€‚ + + å议层的数æ®ç»„织形å¼æ˜¯åŒ…(packet)。接å£çš„å‘é€ä¾§ä¼šå¢žåŠ 包头(headerï¼‰å’Œé”™è¯¯æ ¡éªŒï¼ˆerror-checking)信æ¯åˆ°å³å°†è¢«LLPå‘é€çš„æ•°æ®ä¸Šã€‚接收侧在LLP将包头剥掉,包头会被接收器ä¸å¯¹åº”的逻辑所解æžã€‚é”™è¯¯æ ¡éªŒä¿¡æ¯å¯ä»¥ç”¨æ¥åšå…¥å£æ•°æ®çš„完整性检查。 + +- 应用层(Application Layer) + + 本层æ述了更高层级的应用对于数æ®ä¸çš„æ•°æ®çš„处ç†ï¼Œè§„范并ä¸æ¶µç›–应用层。CSI-2规范åªç»™å‡ºäº†åƒç´ 值和å—èŠ‚çš„æ˜ å°„å…³ç³»ã€‚ + +### è¿ä½œæœºåˆ¶ + +MIPI CSI模å—å„分层的作用为:接å£å±‚æ供打开设备ã€å†™å…¥æ•°æ®å’Œå…³é—设备的接å£ã€‚æ ¸å¿ƒå±‚ä¸»è¦æ供绑定设备ã€åˆå§‹åŒ–设备以åŠé‡Šæ”¾è®¾å¤‡çš„能力。适é…层实现其它具体的功能。 + + **说明:**<br>æ ¸å¿ƒå±‚å¯ä»¥è°ƒç”¨æŽ¥å£å±‚çš„å‡½æ•°ï¼Œæ ¸å¿ƒå±‚é€šè¿‡é’©å函数调用适é…层函数,从而适é…层å¯ä»¥é—´æŽ¥çš„调用接å£å±‚函数,但是ä¸å¯é€†è½¬æŽ¥å£å±‚调用适é…层函数。 + +**图2**CSIæ— æœåŠ¡æ¨¡å¼ç»“构图 + + + +### 约æŸä¸Žé™åˆ¶ + +ç”±äºŽä½¿ç”¨æ— æœåŠ¡æ¨¡å¼ï¼ŒMIPI_CSI接å£æš‚ä¸æ”¯æŒç”¨æˆ·æ€ä½¿ç”¨ã€‚ + +## 使用指导 + +### åœºæ™¯ä»‹ç» + +MIPI CSI主è¦ç”¨äºŽè¿žæŽ¥æ‘„åƒå¤´ç»„件。 + +### 接å£è¯´æ˜Ž + +MIPI CSI模å—æ供的主è¦æŽ¥å£å¦‚表1所示,具体API详è§//drivers/hdf_core/framework/include/platform/mipi_csi_if.h。 + +**表1** ComboDevAttrç»“æž„ä½“ä»‹ç» <a name="table1_MIPI_CSIDes"></a> @@ -27,47 +78,51 @@ CSI(Camera Serial Interface)是由MIPIè”盟下Camera工作组指定的接 | MIPIAttr | Mipi设备属性 | | lvdsAttr | LVDS/SubLVDS/HiSPi设备属性 | -### ExtDataType结构体<a name="section1.2_MIPI_CSIDes"></a> - -**表** **2** ExtDataTypeç»“æž„ä½“ä»‹ç» +**表2** ExtDataTypeç»“æž„ä½“ä»‹ç» <a name="table2_MIPI_CSIDes"></a> | å称 | æè¿° | | --------------- | ------------------------------- | | devno | è®¾å¤‡å· | -| num | sensorå· | +| num | Sensorå· | | extDataBitWidth | 图片的ä½æ·± | | extDataType | 定义YUV和原始数æ®æ ¼å¼ä»¥åŠä½æ·±åº¦ | -### 接å£è¯´æ˜Ž<a name="section1.3_MIPI_CSIDes"></a> - -**表 3** MIPI CSI API接å£åŠŸèƒ½ä»‹ç» +**表3** MIPI CSI API接å£åŠŸèƒ½ä»‹ç» <a name="table3_MIPI_CSIDes"></a> - | 功能分类 | 接å£å | +| 接å£å | 接å£æè¿° | | -------- | -------- | -| 获å–/释放MIPI CSI控制器æ“作å¥æŸ„ | MipiCsiOpen:获å–MIPI CSI控制器æ“作å¥æŸ„<br/>MipiCsiClose:释放MIPI CSI控制器æ“作å¥æŸ„ | -| MIPI CSI相应é…ç½® | MipiCsiSetComboDevAttr:设置MIPI,CMOS或者LVDS相机的å‚数给控制器,å‚数包括工作模å¼ï¼Œå›¾åƒåŒºåŸŸï¼Œå›¾åƒæ·±åº¦ï¼Œæ•°æ®é€ŸçŽ‡å’Œç‰©ç†é€šé“ç‰<br/>MipiCsiSetExtDataType(å¯é€‰):设置YUVå’ŒRAWæ•°æ®æ ¼å¼å’Œä½æ·±<br/>MipiCsiSetHsMode:设置MIPI RXçš„Laneåˆ†å¸ƒã€‚æ ¹æ®ç¡¬ä»¶è¿žæŽ¥çš„å½¢å¼é€‰æ‹©å…·ä½“çš„mode<br/>MipiCsiSetPhyCmvmodeï¼šè®¾ç½®å…±æ¨¡ç”µåŽ‹æ¨¡å¼ | -| å¤ä½/撤销å¤ä½Sensor | MipiCsiResetSensor:å¤ä½Sensor<br/>MipiCsiUnresetSensor:撤销å¤ä½Sensor | -| å¤ä½/撤销å¤ä½MIPI RX | MipiCsiResetRx:å¤ä½MIPI RX。ä¸åŒçš„s32WorkingViNum有ä¸åŒçš„enSnsType<br/>MipiCsiUnresetRx:撤销å¤ä½MIPI RX | -| 使能/å…³é—MIPI的时钟 | MipiCsiEnableClock:使能MIPIçš„æ—¶é’Ÿã€‚æ ¹æ®ä¸Šå±‚å‡½æ•°ç”µæ³³ä¼ é€’çš„enSnsTypeå‚数决定是用MIPI还是LVDS<br/>MipiCsiDisableClock:关é—MIPI设备的时钟 | -| 使能/ç¦ç”¨MIPI上的Sensor时钟 | MipiCsiEnableSensorClock:使能MIPI上的Sensor时钟<br/>MipiCsiDisableSensorClock:关é—Sensor的时钟 | +| DevHandle MipiCsiOpen(uint8_t id) | 获å–MIPI_CSI控制器æ“作å¥æŸ„ | +| void MipiCsiClose(DevHandle handle) | 释放MIPI_CSI控制器æ“作å¥æŸ„ | +| int32_t MipiCsiSetComboDevAttr(DevHandle handle, ComboDevAttr \*pAttr) | 设置MIPI,CMOS或者LVDS相机的å‚数给控制器,å‚数包括工作模å¼ï¼Œå›¾åƒåŒºåŸŸï¼Œå›¾åƒæ·±åº¦ï¼Œæ•°æ®é€ŸçŽ‡å’Œç‰©ç†é€šé“ç‰ | +| int32_t MipiCsiSetExtDataType(DevHandle handle, ExtDataType \*dataType) | 设置YUVå’ŒRAWæ•°æ®æ ¼å¼å’Œä½æ·±ï¼ˆå¯é€‰ï¼‰ | +| int32_t MipiCsiSetHsMode(DevHandle handle, LaneDivideMode laneDivideMode) | 设置MIPI RXçš„Laneåˆ†å¸ƒã€‚æ ¹æ®ç¡¬ä»¶è¿žæŽ¥çš„å½¢å¼é€‰æ‹©å…·ä½“çš„mode | +| int32_t MipiCsiSetPhyCmvmode(DevHandle handle, uint8_t devno, PhyCmvMode cmvMode) | è®¾ç½®å…±æ¨¡ç”µåŽ‹æ¨¡å¼ | +| int32_t MipiCsiResetSensor(DevHandle handle, uint8_t snsResetSource) | å¤ä½Sensor | +| int32_t MipiCsiUnresetSensor(DevHandle handle, uint8_t snsResetSource) | 撤销å¤ä½Sensor | +| int32_t MipiCsiResetRx(DevHandle handle, uint8_t comboDev) | å¤ä½MIPI RX。ä¸åŒçš„s32WorkingViNum有ä¸åŒçš„enSnsType | +| int32_t MipiCsiUnresetRx(DevHandle handle, uint8_t comboDev) | 撤销å¤ä½MIPI RX | +| int32_t MipiCsiEnableClock(DevHandle handle, uint8_t comboDev) | 使能MIPIçš„æ—¶é’Ÿã€‚æ ¹æ®ä¸Šå±‚å‡½æ•°ç”µæ³³ä¼ é€’çš„enSnsTypeå‚数决定是用MIPI还是LVDS | +| int32_t MipiCsiDisableClock(DevHandle handle, uint8_t comboDev) | å…³é—MIPI设备的时钟 | +| int32_t MipiCsiEnableSensorClock(DevHandle handle, uint8_t snsClkSource) | 使能MIPI上的Sensor时钟 | +| int32_t MipiCsiDisableSensorClock(DevHandle handle, uint8_t snsClkSource) | å…³é—Sensor的时钟 | -## 使用指导<a name="section2_MIPI_CSIDes"></a> +## å¼€å‘æ¥éª¤ -### 使用æµç¨‹<a name="section2.1_MIPI_CSIDes"></a> +#### 使用æµç¨‹ -使用MIPI CSI的一般æµç¨‹å¦‚图2所示。 +使用MIPI CSI的一般æµç¨‹å¦‚图3所示。 -**图 2** MIPI CSI使用æµç¨‹å›¾<a name="fig2_MIPI_CSIDes"></a> +**图3** MIPI CSI使用æµç¨‹å›¾  -### 获å–MIPI CSI控制器æ“作å¥æŸ„<a name="section2.2_MIPI_CSIDes"></a> +#### 获å–MIPI CSI控制器æ“作å¥æŸ„ 在进行MIPI CSI进行通信å‰ï¼Œé¦–å…ˆè¦è°ƒç”¨MipiCsiOpen获å–控制器æ“作å¥æŸ„,该函数会返回指定通é“ID的控制器æ“作å¥æŸ„。 @@ -75,9 +130,7 @@ CSI(Camera Serial Interface)是由MIPIè”盟下Camera工作组指定的接 DevHandle MipiCsiOpen(uint8_t id); ``` -**表 4** MipiCsiOpençš„å‚数和返回值æè¿° - -<a name="table4_MIPI_CSIDes"></a> +**表4** MipiCsiOpençš„å‚数和返回值æè¿° | å‚æ•° | å‚æ•°æè¿° | | ---------- | ----------------------------------------------- | @@ -100,7 +153,7 @@ if (MipiCsiHandle == NULL) { } ``` -### MIPI CSI相应é…ç½®<a name="section2.3_MIPI_CSIDes"></a> +#### 进行MIPI CSI相应é…ç½® - 写入MIPI CSIé…ç½® @@ -108,7 +161,7 @@ if (MipiCsiHandle == NULL) { int32_t MipiCsiSetComboDevAttr(DevHandle handle, ComboDevAttr *pAttr); ``` - **表 5** MipiCsiSetComboDevAttrçš„å‚数和返回值æè¿° + **表5** MipiCsiSetComboDevAttrçš„å‚数和返回值æè¿° <a name="table5_MIPI_CSIDes"></a> @@ -147,7 +200,7 @@ if (MipiCsiHandle == NULL) { int32_t MipiCsiSetExtDataType(DevHandle handle, ExtDataType* dataType); ``` - **表 6** MipiCsiSetExtDataTypeçš„å‚数和返回值æè¿° + **表6** MipiCsiSetExtDataTypeçš„å‚数和返回值æè¿° <a name="table6_MIPI_CSIDes"></a> @@ -165,7 +218,7 @@ if (MipiCsiHandle == NULL) { /* é…ç½®YUVå’ŒRAWæ•°æ®æ ¼å¼å’Œä½æ·±å‚æ•° */ dataType.devno = 0; /* 设备0 */ - dataType.num = 0; /* sensor 0 */ + dataType.num = 0; /* Sensor 0 */ dataType.extDataBitWidth[0] = 12; /* ä½æ·±æ•°ç»„å…ƒç´ 0 */ dataType.extDataBitWidth[1] = 12; /* ä½æ·±æ•°ç»„å…ƒç´ 1 */ dataType.extDataBitWidth[2] = 12; /* ä½æ·±æ•°ç»„å…ƒç´ 2 */ @@ -187,23 +240,21 @@ if (MipiCsiHandle == NULL) { int32_t MipiCsiSetHsMode(DevHandle handle, LaneDivideMode laneDivideMode); ``` - **表 7** MipiCsiSetHsModeçš„å‚数和返回值æè¿° - - <a name="table7_MIPI_CSIDes"></a> + **表7** MipiCsiSetHsModeçš„å‚数和返回值æè¿° | å‚æ•° | å‚æ•°æè¿° | | -------------- | -------------- | | handle | 控制器æ“作å¥æŸ„ | - | laneDivideMode | lane模å¼å‚æ•° | + | laneDivideMode | Lane模å¼å‚æ•° | | **返回值** | **返回值æè¿°** | | 0 | 设置æˆåŠŸ | | è´Ÿæ•° | 设置失败 | - + ```c int32_t ret; enum LaneDivideMode mode; - - /* lane模å¼å‚数为0 */ + + /* Lane模å¼å‚数为0 */ mode = LANE_DIVIDE_MODE_0; /* 设置MIPI RXçš„ Lane分布 */ ret = MipiCsiSetHsMode(MipiCsiHandle, mode); @@ -212,16 +263,14 @@ if (MipiCsiHandle == NULL) { return -1; } ``` - + - è®¾ç½®å…±æ¨¡ç”µåŽ‹æ¨¡å¼ ```c int32_t MipiCsiSetPhyCmvmode(DevHandle handle, uint8_t devno, PhyCmvMode cmvMode); ``` - **表 8** MipiCsiSetPhyCmvmodeçš„å‚数和返回值æè¿° - - <a name="table8_MIPI_CSIDes"></a> + **表8** MipiCsiSetPhyCmvmodeçš„å‚数和返回值æè¿° | å‚æ•° | å‚æ•°æè¿° | | ---------- | ---------------- | @@ -231,7 +280,7 @@ if (MipiCsiHandle == NULL) { | **返回值** | **返回值æè¿°** | | 0 | 设置æˆåŠŸ | | è´Ÿæ•° | 设置失败 | - + ```c int32_t ret; enum PhyCmvMode mode; @@ -249,7 +298,7 @@ if (MipiCsiHandle == NULL) { } ``` -### å¤ä½/撤销å¤ä½Sensor<a name="section2.4_MIPI_CSIDes"></a> +#### å¤ä½/撤销å¤ä½Sensor - å¤ä½Sensor @@ -257,9 +306,7 @@ if (MipiCsiHandle == NULL) { int32_t MipiCsiResetSensor(DevHandle handle, uint8_t snsResetSource); ``` - **表 9** MipiCsiResetSensorçš„å‚数和返回值æè¿° - - <a name="table9_MIPI_CSIDes"></a> + **表9** MipiCsiResetSensorçš„å‚数和返回值æè¿° | å‚æ•° | å‚æ•°æè¿° | | -------------- | ------------------------------------------------ | @@ -268,30 +315,28 @@ if (MipiCsiHandle == NULL) { | **返回值** | **返回值æè¿°** | | 0 | å¤ä½æˆåŠŸ | | è´Ÿæ•° | å¤ä½å¤±è´¥ | - + ```c int32_t ret; uint8_t snsResetSource; - + /* ä¼ æ„Ÿå™¨å¤ä½ä¿¡å·çº¿å·ä¸º0 */ snsResetSource = 0; - /* å¤ä½sensor */ + /* å¤ä½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çš„å‚数和返回值æè¿° - - <a name="table10_MIPI_CSIDes"></a> + **表10** MipiCsiUnresetSensorçš„å‚数和返回值æè¿° | å‚æ•° | å‚æ•°æè¿° | | -------------- | ------------------------------------------------ | @@ -300,14 +345,14 @@ if (MipiCsiHandle == NULL) { | **返回值** | **返回值æè¿°** | | 0 | 撤销å¤ä½æˆåŠŸ | | è´Ÿæ•° | 撤销å¤ä½å¤±è´¥ | - + ```c int32_t ret; uint8_t snsResetSource; - + /* ä¼ æ„Ÿå™¨æ’¤é”€å¤ä½ä¿¡å·çº¿å·ä¸º0 */ snsResetSource = 0; - /* 撤销å¤ä½sensor */ + /* 撤销å¤ä½Sensor */ ret = MipiCsiUnresetSensor(MipiCsiHandle, snsResetSource); if (ret != 0) { HDF_LOGE("%s: MipiCsiUnresetSensor fail! ret=%d\n", __func__, ret); @@ -315,7 +360,7 @@ if (MipiCsiHandle == NULL) { } ``` -### å¤ä½/撤销å¤ä½MIPI RX<a name="section2.5_MIPI_CSIDes"></a> +#### å¤ä½/撤销å¤ä½MIPI RX - å¤ä½MIPI RX @@ -323,9 +368,7 @@ if (MipiCsiHandle == NULL) { int32_t MipiCsiResetRx(DevHandle handle, uint8_t comboDev); ``` - **表 11** MipiCsiResetRxçš„å‚数和返回值æè¿° - - <a name="table11_MIPI_CSIDes"></a> + **表11** MipiCsiResetRxçš„å‚数和返回值æè¿° | å‚æ•° | å‚æ•°æè¿° | | ---------- | --------------------- | @@ -334,11 +377,11 @@ if (MipiCsiHandle == NULL) { | **返回值** | **返回值æè¿°** | | 0 | å¤ä½æˆåŠŸ | | è´Ÿæ•° | å¤ä½å¤±è´¥ | - + ```c int32_t ret; uint8_t comboDev; - + /* 通路åºå·ä¸º0 */ comboDev = 0; /* å¤ä½MIPI RX */ @@ -348,16 +391,14 @@ if (MipiCsiHandle == NULL) { return -1; } ``` - + - 撤销å¤ä½MIPI RX ```c int32_t MipiCsiUnresetRx(DevHandle handle, uint8_t comboDev); ``` - **表 12** MipiCsiUnresetRxçš„å‚数和返回值æè¿° - - <a name="table12_MIPI_CSIDes"></a> + **表12** MipiCsiUnresetRxçš„å‚数和返回值æè¿° | å‚æ•° | å‚æ•°æè¿° | | ---------- | --------------------- | @@ -366,11 +407,11 @@ if (MipiCsiHandle == NULL) { | **返回值** | **返回值æè¿°** | | 0 | 撤销å¤ä½æˆåŠŸ | | è´Ÿæ•° | 撤销å¤ä½å¤±è´¥ | - + ```c int32_t ret; uint8_t comboDev; - + /* 通路åºå·ä¸º0 */ comboDev = 0; /* 撤销å¤ä½MIPI RX */ @@ -381,7 +422,7 @@ if (MipiCsiHandle == NULL) { } ``` -### 使能/å…³é—MIPI的时钟<a name="section2.6_MIPI_CSIDes"></a> +#### 使能/å…³é—MIPI的时钟 - 使能MIPI的时钟 @@ -389,7 +430,7 @@ if (MipiCsiHandle == NULL) { int32_t MipiCsiEnableClock(DevHandle handle, uint8_t comboDev); ``` - **表 13** MipiCsiEnableClockçš„å‚数和返回值æè¿° + **表13** MipiCsiEnableClockçš„å‚数和返回值æè¿° <a name="table13_MIPI_CSIDes"></a> @@ -421,7 +462,7 @@ if (MipiCsiHandle == NULL) { int32_t MipiCsiDisableClock(DevHandle handle, uint8_t comboDev); ``` - **表 14** MipiCsiDisableClockçš„å‚数和返回值æè¿° + **表14** MipiCsiDisableClockçš„å‚数和返回值æè¿° <a name="table14_MIPI_CSIDes"></a> @@ -436,7 +477,7 @@ if (MipiCsiHandle == NULL) { ```c int32_t ret; uint8_t comboDev; - + /* 通路åºå·ä¸º0 */ comboDev = 0; /* å…³é—MIPI的时钟 */ @@ -447,7 +488,7 @@ if (MipiCsiHandle == NULL) { } ``` -### 使能/å…³é—MIPI上的Sensor时钟<a name="section2.7_MIPI_CSIDes"></a> +#### 使能/å…³é—MIPI上的Sensor时钟<a name="section2.7_MIPI_CSIDes"></a> - 使能MIPI上的Sensor时钟 @@ -455,7 +496,7 @@ if (MipiCsiHandle == NULL) { int32_t MipiCsiEnableSensorClock(DevHandle handle, uint8_t snsClkSource); ``` - **表 15** MipiCsiEnableSensorClockçš„å‚数和返回值æè¿° + **表15** MipiCsiEnableSensorClockçš„å‚数和返回值æè¿° <a name="table15_MIPI_CSIDes"></a> @@ -473,7 +514,7 @@ if (MipiCsiHandle == NULL) { /* ä¼ æ„Ÿå™¨çš„æ—¶é’Ÿä¿¡å·çº¿å·ä¸º0 */ snsClkSource = 0; - /* 使能MIPI上的sensor时钟 */ + /* 使能MIPI上的Sensor时钟 */ ret = MipiCsiEnableSensorClock(MipiCsiHandle, snsClkSource); if (ret != 0) { HDF_LOGE("%s: MipiCsiEnableSensorClock fail! ret=%d\n", __func__, ret); @@ -487,7 +528,7 @@ if (MipiCsiHandle == NULL) { int32_t MipiCsiDisableSensorClock(DevHandle handle, uint8_t snsClkSource); ``` - **表 16** MipiCsiDisableSensorClockçš„å‚数和返回值æè¿° + **表16** MipiCsiDisableSensorClockçš„å‚数和返回值æè¿° <a name="table16_MIPI_CSIDes"></a> @@ -502,7 +543,7 @@ if (MipiCsiHandle == NULL) { ```c int32_t ret; uint8_t snsClkSource; - + /* ä¼ æ„Ÿå™¨çš„æ—¶é’Ÿä¿¡å·çº¿å·ä¸º0 */ snsClkSource = 0; /* å…³é—MIPI上的Sensor时钟 */ @@ -513,7 +554,7 @@ if (MipiCsiHandle == NULL) { } ``` -### 释放MIPI CSI控制器æ“作å¥æŸ„<a name="section2.8_MIPI_CSIDes"></a> +#### 释放MIPI CSI控制器æ“作å¥æŸ„<a name="section2.8_MIPI_CSIDes"></a> MIPI CSI使用完æˆä¹‹åŽï¼Œéœ€è¦é‡Šæ”¾æŽ§åˆ¶å™¨æ“作å¥æŸ„,释放å¥æŸ„的函数如下所示: @@ -523,13 +564,13 @@ void MipiCsiClose(DevHandle handle); 该函数会释放掉由MipiCsiOpen申请的资æºã€‚ -**表 17** MipiCsiCloseçš„å‚数和返回值æè¿° +**表17** MipiCsiCloseçš„å‚数和返回值æè¿° <a name="table17_MIPI_CSIDes"></a> - | å‚æ•° | å‚æ•°æè¿° | - | ------------ | ------------------------------------------------ | - | handle | MIPI CSI控制器æ“作å¥æŸ„ | +| å‚æ•° | å‚æ•°æè¿° | +| ------------ | ------------------------------------------------ | +| handle | MIPI CSI控制器æ“作å¥æŸ„ | ```c MipiCsiClose(MIPIHandle); /* 释放掉MIPI CSI控制器æ“作å¥æŸ„ */ @@ -537,6 +578,8 @@ MipiCsiClose(MIPIHandle); /* 释放掉MIPI CSI控制器æ“作å¥æŸ„ */ ## 使用实例<a name="section3_MIPI_CSIDes"></a> +本例拟对Hi3516DV300å¼€å‘æ¿ä¸ŠMIPI CSI设备进行æ“作。 + MIPI CSI完整的使用示例如下所示: ```c @@ -565,7 +608,7 @@ void PalMipiCsiTestSample(void) return; } - /* lane模å¼å‚数为0 */ + /* Lane模å¼å‚数为0 */ mode = LANE_DIVIDE_MODE_0; /* 设置MIPI RXçš„Lane分布 */ ret = MipiCsiSetHsMode(MipiCsiHandle, mode); @@ -592,14 +635,14 @@ void PalMipiCsiTestSample(void) /* ä¼ æ„Ÿå™¨çš„æ—¶é’Ÿä¿¡å·çº¿å·ä¸º0 */ snsClkSource = 0; - /* 使能MIPI上的sensor时钟 */ + /* 使能MIPI上的Sensor时钟 */ ret = MipiCsiEnableSensorClock(MipiCsiHandle, snsClkSource); if (ret != 0) { HDF_LOGE("%s: MipiCsiEnableSensorClock fail! ret=%d\n", __func__, ret); return; } - /* å¤ä½sensor */ + /* å¤ä½Sensor */ ret = MipiCsiResetSensor(MipiCsiHandle, snsResetSource); if (ret != 0) { HDF_LOGE("%s: MipiCsiResetSensor fail! ret=%d\n", __func__, ret); @@ -651,14 +694,14 @@ void PalMipiCsiTestSample(void) /* ä¼ æ„Ÿå™¨æ’¤é”€å¤ä½ä¿¡å·çº¿å·ä¸º0 */ snsResetSource = 0; - /* 撤销å¤ä½sensor */ + /* 撤销å¤ä½Sensor */ ret = MipiCsiUnresetSensor(MipiCsiHandle, snsResetSource); if (ret != 0) { HDF_LOGE("%s: MipiCsiUnresetSensor fail! ret=%d\n", __func__, ret); return; } - /* å…³é—MIPI上的sensor时钟 */ + /* å…³é—MIPI上的Sensor时钟 */ ret = MipiCsiDisableSensorClock(MipiCsiHandle, snsClkSource); if (ret != 0) { HDF_LOGE("%s: MipiCsiDisableSensorClock fail! ret=%d\n", __func__, ret); diff --git a/zh-cn/device-dev/driver/driver-platform-mipicsi-develop.md b/zh-cn/device-dev/driver/driver-platform-mipicsi-develop.md index 0134b7f8096875b6a83cb38d88e5938c13a491b4..fd4c6675b305cb91851a01c5e38fc9618fd9f369 100755 --- a/zh-cn/device-dev/driver/driver-platform-mipicsi-develop.md +++ b/zh-cn/device-dev/driver/driver-platform-mipicsi-develop.md @@ -2,13 +2,66 @@ ## 概述 -CSI(Camera Serial Interface)是由MIPI(Mobile Industry Processor Interface)è”盟下Camera工作组指定的接å£æ ‡å‡†ã€‚在HDF框架ä¸ï¼ŒMIPI CSI的接å£é€‚é…模å¼é‡‡ç”¨æ— æœåŠ¡æ¨¡å¼ï¼Œç”¨äºŽä¸éœ€è¦åœ¨ç”¨æˆ·æ€æä¾›API的设备类型,或者没有用户æ€å’Œå†…æ ¸åŒºåˆ†çš„OS系统,MIPI CSI的接å£å…³è”æ–¹å¼æ˜¯DevHandle直接指å‘è®¾å¤‡å¯¹è±¡å†…æ ¸æ€åœ°å€ï¼ˆDevHandle是一个void类型指针)。 +### 功能简介 -图 1 æ— æœåŠ¡æ¨¡å¼ç»“构图 +CSI(Camera Serial Interface)是由MIPIè”盟下Camera工作组指定的接å£æ ‡å‡†ã€‚CSI-2是MIPI CSI第二版,主è¦ç”±åº”用层ã€å议层ã€ç‰©ç†å±‚组æˆï¼Œæœ€å¤§æ”¯æŒ4通é“æ•°æ®ä¼ 输ã€å•çº¿ä¼ 输速度高达1Gb/s。 + +物ç†å±‚支æŒHS(High Speed)和LP(Low Speed)两ç§å·¥ä½œæ¨¡å¼ã€‚HS模å¼ä¸‹é‡‡ç”¨ä½ŽåŽ‹å·®åˆ†ä¿¡å·ï¼ŒåŠŸè€—较大,但数æ®ä¼ 输速率å¯ä»¥å¾ˆé«˜ï¼ˆæ•°æ®é€ŸçŽ‡ä¸º80M~1Gbps);LP模å¼ä¸‹é‡‡ç”¨å•ç«¯ä¿¡å·ï¼Œæ•°æ®é€ŸçŽ‡å¾ˆä½Žï¼ˆ<10Mbps),但是相应的功耗也很低。两ç§æ¨¡å¼çš„结åˆä¿è¯äº†MIPI总线在需è¦ä¼ 输大é‡æ•°æ®ï¼ˆå¦‚图åƒï¼‰æ—¶å¯ä»¥é«˜é€Ÿä¼ 输,而在ä¸éœ€è¦ä¼ 输大数æ®é‡æ—¶åˆèƒ½å¤Ÿå‡å°‘功耗。 + +图1显示了简化的CSI接å£ã€‚D-PHY采用1对æºåŒæ¥çš„差分时钟和1~4对差分数æ®çº¿æ¥è¿›è¡Œæ•°æ®ä¼ 输。数æ®ä¼ 输采用DDRæ–¹å¼ï¼Œå³åœ¨æ—¶é’Ÿçš„上下边沿都有数æ®ä¼ 输。 + + **图 1** CSIå‘é€ã€æŽ¥æ”¶æŽ¥å£ + + +MIPI CSIæ ‡å‡†åˆ†ä¸ºåº”ç”¨å±‚ã€å议层与物ç†å±‚,å议层åˆç»†åˆ†ä¸ºåƒç´ å—节转æ¢å±‚ã€ä½Žçº§å议层ã€Lane管ç†å±‚。 + +- 物ç†å±‚(PHY Layer) + + PHYå±‚æŒ‡å®šäº†ä¼ è¾“åª’ä»‹ï¼Œåœ¨ç”µæ°”å±‚é¢ä»Žä¸²è¡Œbitæµä¸æ•æ‰â€œ0â€ä¸Žâ€œ1â€ï¼ŒåŒæ—¶ç”ŸæˆSoT与EoTç‰ä¿¡å·ã€‚ + +- å议层(Protocol Layer) + + å议层由三个å层组æˆï¼Œæ¯ä¸ªå层有ä¸åŒçš„èŒè´£ã€‚CSI-2å议能够在host侧处ç†å™¨ä¸Šç”¨ä¸€ä¸ªå•ç‹¬çš„接å£å¤„ç†å¤šæ¡æ•°æ®æµã€‚å议层规定了多æ¡æ•°æ®æµè¯¥å¦‚ä½•æ ‡è®°å’Œäº¤ç»‡èµ·æ¥ï¼Œä»¥ä¾¿æ¯æ¡æ•°æ®æµèƒ½å¤Ÿè¢«æ£ç¡®åœ°æ¢å¤å‡ºæ¥ã€‚ + + - åƒç´ å—节转æ¢å±‚(Pixel/Byte Packing/Unpacking Layer) + + CSI-2规范支æŒå¤šç§ä¸åŒåƒç´ æ ¼å¼çš„图åƒåº”用。在å‘é€æ–¹ä¸ï¼Œæœ¬å±‚在å‘é€æ•°æ®åˆ°Low Level Protocol层之å‰ï¼Œå°†æ¥è‡ªåº”用层的åƒç´ å°åŒ…为å—节数æ®ã€‚在接收方ä¸ï¼Œæœ¬å±‚在å‘é€æ•°æ®åˆ°åº”用层之å‰ï¼Œå°†æ¥è‡ªLow Level Protocol层的å—节数æ®è§£åŒ…为åƒç´ 。8ä½çš„åƒç´ æ•°æ®åœ¨æœ¬å±‚ä¸ä¼ 输时ä¿æŒä¸å˜ã€‚ + + - 低级å议层(Low Level Protocol) + + LLP主è¦åŒ…å«äº†åœ¨SoTå’ŒEoT事件之间的bitå’Œbyte级别的åŒæ¥æ–¹æ³•ï¼Œä»¥åŠå’Œä¸‹ä¸€å±‚ä¼ é€’æ•°æ®çš„方法。LLP最å°æ•°æ®ç²’度是1个å—节。LLP也包å«äº†ä¸€ä¸ªå—节内的bit值解æžï¼Œå³Endian(大å°ç«¯é‡Œçš„Endiançš„æ„æ€)的处ç†ã€‚ + + - Lane管ç†å±‚(Lane Management) + + CSI-2çš„Lane是å¯æ‰©å±•çš„。具体的数æ®Laneçš„æ•°é‡è§„范并没有给出é™åˆ¶ï¼Œå…·ä½“æ ¹æ®åº”用的带宽需求而定。å‘é€ä¾§åˆ†å‘(distributor功能)æ¥è‡ªå‡ºå£æ–¹å‘æ•°æ®æµçš„å—节到1æ¡æˆ–多æ¡Lane上。接收侧则从一æ¡æˆ–多æ¡Laneä¸æ”¶é›†å—节并åˆå¹¶ï¼ˆmerge功能)到一个数æ®æµä¸Šï¼Œå¤åŽŸå‡ºåŽŸå§‹æµçš„å—节顺åºã€‚对于C-PHY物ç†å±‚æ¥è¯´ï¼Œæœ¬å±‚专门分å‘å—节对(16 bits)到数æ®Lane或从数æ®Laneä¸æ”¶é›†å—节对。基于æ¯Lane的扰ç 功能是å¯é€‰ç‰¹æ€§ã€‚ + + å议层的数æ®ç»„织形å¼æ˜¯åŒ…(packet)。接å£çš„å‘é€ä¾§ä¼šå¢žåŠ 包头(headerï¼‰å’Œé”™è¯¯æ ¡éªŒï¼ˆerror-checking)信æ¯åˆ°å³å°†è¢«LLPå‘é€çš„æ•°æ®ä¸Šã€‚接收侧在LLP将包头剥掉,包头会被接收器ä¸å¯¹åº”的逻辑所解æžã€‚é”™è¯¯æ ¡éªŒä¿¡æ¯å¯ä»¥ç”¨æ¥åšå…¥å£æ•°æ®çš„完整性检查。 + +- 应用层(Application Layer) + + 本层æ述了更高层级的应用对于数æ®ä¸çš„æ•°æ®çš„处ç†ï¼Œè§„范并ä¸æ¶µç›–应用层。CSI-2规范åªç»™å‡ºäº†åƒç´ 值和å—èŠ‚çš„æ˜ å°„å…³ç³»ã€‚ + +### è¿ä½œæœºåˆ¶ + +MIPI CSI模å—å„分层的作用为: + +- 接å£å±‚æ供打开设备ã€å†™å…¥æ•°æ®å’Œå…³é—设备的接å£ã€‚ +- æ ¸å¿ƒå±‚ä¸»è¦æ供绑定设备ã€åˆå§‹åŒ–设备以åŠé‡Šæ”¾è®¾å¤‡çš„能力。 +- 适é…层实现其它具体的功能。 + + **说明:**<br>æ ¸å¿ƒå±‚å¯ä»¥è°ƒç”¨æŽ¥å£å±‚çš„å‡½æ•°ï¼Œæ ¸å¿ƒå±‚é€šè¿‡é’©å函数调用适é…层函数,从而适é…层å¯ä»¥é—´æŽ¥çš„调用接å£å±‚函数,但是ä¸å¯é€†è½¬æŽ¥å£å±‚调用适é…层函数。  -## 接å£è¯´æ˜Ž +## å¼€å‘指导 + +### åœºæ™¯ä»‹ç» + +MIPI CSI仅是一个软件层é¢çš„概念,主è¦å·¥ä½œæ˜¯CSI资æºç®¡ç†ã€‚å¼€å‘者å¯ä»¥é€šè¿‡ä½¿ç”¨æ供的CSIæ“作接å£ï¼Œå®žçŽ°å¯¹CSI资æºç®¡ç†ã€‚当驱动开å‘者需è¦å°†MIPI CSI设备适é…到OpenHarmony时,需è¦è¿›è¡ŒMIPI CSI驱动适é…,下文将介ç»å¦‚何进行MIPI CSI驱动适é…。 + +### 接å£è¯´æ˜Ž + +为了ä¿è¯ä¸Šå±‚在调用MIPI CSI接å£æ—¶èƒ½å¤Ÿæ£ç¡®çš„æ“ä½œç¡¬ä»¶ï¼Œæ ¸å¿ƒå±‚åœ¨//drivers/hdf_core/framework/support/platform/include/mipi/mipi_csi_core.hä¸å®šä¹‰äº†ä»¥ä¸‹é’©å函数。驱动适é…者需è¦åœ¨é€‚é…层实现这些函数的具体功能,并与这些钩å函数挂接,从而完æˆæŽ¥å£å±‚ä¸Žæ ¸å¿ƒå±‚çš„äº¤äº’ã€‚ MipiCsiCntlrMethod定义: @@ -28,13 +81,13 @@ struct MipiCsiCntlrMethod { int32_t (*unresetSensor)(struct MipiCsiCntlr *cntlr, uint8_t snsResetSource); }; ``` -表1 MipiCsiCntlrMethodæˆå‘˜çš„回调函数功能说明 +**表1** MipiCsiCntlrMethodæˆå‘˜çš„é’©å函数功能说明 | æˆå‘˜å‡½æ•° | å…¥å‚ | å‡ºå‚ | è¿”å›žçŠ¶æ€ | 功能 | | ------------------ | ------------------------------------------------------------ | ---- | ------------------ | -------------------------- | | setComboDevAttr | **cntlr**:结构体指针,MipiCsi控制器 ;<br>**pAttr**:结构体指针,MIPI CSI相应é…置结构体指针 | æ— | HDF_STATUSç›¸å…³çŠ¶æ€ | 写入MIPI CSIé…ç½® | | setPhyCmvmode | **cntlr**:结构体指针,MipiCsi控制器 ;<br>**devno**:uint8_t,设备编å·;<br>**cmvMode**:枚举类型,共模电压模å¼å‚æ•° | æ— | HDF_STATUSç›¸å…³çŠ¶æ€ | è®¾ç½®å…±æ¨¡ç”µåŽ‹æ¨¡å¼ | | setExtDataType | **cntlr**:结构体指针,MipiCsi控制器 ;<br>**dataType**:结构体指针,定义YUV和原始数æ®æ ¼å¼ä»¥åŠä½æ·±åº¦ | æ— | HDF_STATUSç›¸å…³çŠ¶æ€ | 设置YUVå’ŒRAWæ•°æ®æ ¼å¼å’Œä½æ·± | -| setHsMode | **cntlr**:结构体指针,MipiCsi控制器 ;<br>**laneDivideMode**:枚举类型,lane模å¼å‚æ•° | æ— | HDF_STATUSç›¸å…³çŠ¶æ€ | 设置MIPI RXçš„Lane分布 | +| setHsMode | **cntlr**:结构体指针,MipiCsi控制器 ;<br>**laneDivideMode**:枚举类型,Lane模å¼å‚æ•° | æ— | HDF_STATUSç›¸å…³çŠ¶æ€ | 设置MIPI RXçš„Lane分布 | | enableClock | **cntlr**:结构体指针,MipiCsi控制器 ;<br>**comboDev**:uint8_t,通路åºå· | æ— | HDF_STATUSç›¸å…³çŠ¶æ€ | 使能MIPI的时钟 | | disableClock | **cntlr**:结构体指针,MipiCsi控制器 ;<br/>**comboDev**:uint8_t,通路åºå· | æ— | HDF_STATUSç›¸å…³çŠ¶æ€ | å…³é—MIPI的时钟 | | resetRx | **cntlr**:结构体指针,MipiCsi控制器 ;<br/>**comboDev**:uint8_t,通路åºå· | æ— | HDF_STATUSç›¸å…³çŠ¶æ€ | å¤ä½MIPI RX | @@ -44,7 +97,7 @@ struct MipiCsiCntlrMethod { | resetSensor | **cntlr**:结构体指针,MipiCsi控制器 ;<br/>**snsClkSource**:uint8_tï¼Œä¼ æ„Ÿå™¨çš„æ—¶é’Ÿä¿¡å·çº¿å· | æ— | HDF_STATUSç›¸å…³çŠ¶æ€ | å¤ä½Sensor | | unresetSensor | **cntlr**:结构体指针,MipiCsi控制器 ;<br/>**snsClkSource**:uint8_tï¼Œä¼ æ„Ÿå™¨çš„æ—¶é’Ÿä¿¡å·çº¿å· | æ— | HDF_STATUSç›¸å…³çŠ¶æ€ | 撤销å¤ä½Sensor | -## å¼€å‘æ¥éª¤ +### å¼€å‘æ¥éª¤ MIPI CSI模å—适é…的三个必选环节是é…置属性文件ã€å®žä¾‹åŒ–驱动入å£ã€ä»¥åŠå®žä¾‹åŒ–æ ¸å¿ƒå±‚æŽ¥å£å‡½æ•°ã€‚ @@ -70,269 +123,264 @@ MIPI CSI模å—适é…的三个必选环节是é…置属性文件ã€å®žä¾‹åŒ–驱动 ã€å¯é€‰ã€‘针对新增驱动程åºï¼Œå»ºè®®éªŒè¯é©±åŠ¨åŸºæœ¬åŠŸèƒ½ï¼Œä¾‹å¦‚挂载åŽçš„ä¿¡æ¯å馈,数æ®ä¼ 输的æˆåŠŸä¸Žå¦ç‰ã€‚ -## å¼€å‘实例 +### å¼€å‘实例 下方将以mipi_rx_hi35xx.c为示例,展示需è¦åŽ‚商æ供哪些内容æ¥å®Œæ•´å®žçŽ°è®¾å¤‡åŠŸèƒ½ã€‚ -1. 一般æ¥è¯´ï¼Œé©±åŠ¨å¼€å‘首先需è¦åœ¨busxx_config.hcsä¸é…置器件属性,并在device_info.hcs文件ä¸æ·»åŠ deviceNodeæ述。 +1. 一般æ¥è¯´ï¼Œé©±åŠ¨å¼€å‘首先需è¦æ–°å¢žmipicsi_config.hcsé…置文件,在其ä¸é…置器件属性,并在//vendor/hisilicon/hispark_taurus/hdf_config/device_info/device_info.hcs文件ä¸æ·»åŠ deviceNodeæ述。deviceNode与é…置属性的对应关系是ä¾é deviceMatchAttrå—段æ¥å®Œæˆçš„。åªæœ‰å½“deviceNode下的deviceMatchAttrå—段与é…置属性文件ä¸çš„match_attrå—段完全相åŒæ—¶ï¼Œé©±åŠ¨æ‰èƒ½æ£ç¡®è¯»å–é…置数æ®ã€‚ å™¨ä»¶å±žæ€§å€¼ä¸Žæ ¸å¿ƒå±‚MipiCsiCntlr æˆå‘˜çš„默认值或é™åˆ¶èŒƒå›´æœ‰å¯†åˆ‡å…³ç³»ï¼ŒdeviceNodeä¿¡æ¯ä¸Žé©±åŠ¨å…¥å£æ³¨å†Œç›¸å…³ã€‚ - > **说明:**<br> - >本例ä¸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"; // ã€å¿…è¦ä¸”唯一】驱动对外å‘布æœåŠ¡çš„å称 - } - } - } - } - } - ``` + > **说明:**<br> + >本例ä¸MIPI控制器é…置属性在æºæ–‡ä»¶ä¸ï¼Œæ²¡æœ‰æ–°å¢žé…置文件,驱动适é…者如有需è¦ï¼Œå¯åœ¨device_info.hcs文件的deviceNodeå¢žåŠ deviceMatchAttrå—段,åŒæ—¶æ–°å¢žmipicsi_config.hcs文件,并使其match_attrå—段与之相åŒã€‚ + + 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对象首地å€æ±‡æ€»ï¼Œå½¢æˆä¸€ä¸ªç±»ä¼¼æ•°ç»„,方便调用。 + 驱动入å£å¿…须为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]; + 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; }; - } MipiDevAttr; - - typedef struct { - /** è®¾å¤‡å· */ - uint8_t devno; - /** 输入模å¼: MIPI/LVDS/SUBLVDS/HISPI/DC */ - InputMode inputMode; - MipiDataRate dataRate; - /** MIPI Rx设备è£å‰ªåŒºåŸŸï¼ˆä¸ŽåŽŸå§‹ä¼ 感器输入图åƒå¤§å°ç›¸å¯¹åº”) */ - ImgRect imgRect; - - union { - MipiDevAttr mipiAttr; - LvdsDevAttr lvdsAttr; + ``` + + - MipiCsiCntlræˆå‘˜é’©å函数结构体MipiCsiCntlrMethod的实例化 + + > **说明:**<br> + >其他æˆå‘˜åœ¨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 }; - } 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的实例化 - - > **说明:**<br> - >其他æˆå‘˜åœ¨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__); + ``` + + - Init函数开å‘å‚考 + + å…¥å‚: + + HdfDeviceObject是整个驱动对外暴露的接å£å‚数,具备HCSé…置文件的信æ¯ã€‚ + + 返回值: + + HDF_STATUS相关状æ€ï¼ˆä¸‹è¡¨ä¸ºéƒ¨åˆ†å±•ç¤ºï¼Œå¦‚需使用其他状æ€ï¼Œå¯è§//drivers/hdf_core/framework/include/utils/hdf_base.hä¸HDF_STATUS定义)。 + + **表2** 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; } - #endif - - OsalSpinInit(&g_mipiCsi.ctxLock); - HDF_LOGI("%s: load mipi csi driver success!", __func__); - - return ret; - } - - // mipi_csi_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; + + /* mipi_csi_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; } - - HDF_LOGE("%s: cntlr already exists.", __func__); - return HDF_FAILURE; - } - ``` - -- **Release函数å‚考** - - **å…¥å‚:** - - HdfDeviceObject是整个驱动对外暴露的接å£å‚数,具备HCSé…置文件的信æ¯ã€‚ - - **返回值:** - - æ— - - **函数说明:** - - 该函数需è¦åœ¨é©±åŠ¨å…¥å£ç»“构体ä¸èµ‹å€¼ç»™Release接å£ï¼Œå½“HDF框架调用Init函数åˆå§‹åŒ–驱动失败时,å¯ä»¥è°ƒç”¨Release释放驱动资æºï¼Œè¯¥å‡½æ•°ä¸éœ€åŒ…å«é‡Šæ”¾å†…å˜å’Œåˆ 除控制器ç‰æ“作。 - - > **说明:**<br> - >所有强制转æ¢èŽ·å–相应对象的æ“作å‰æ是在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__); - } - ``` + ``` + + - Release函数开å‘å‚考 + + å…¥å‚: + + HdfDeviceObject是整个驱动对外暴露的接å£å‚数,具备HCSé…置文件的信æ¯ã€‚ + + 返回值: + æ— + + 函数说明: + + 该函数需è¦åœ¨é©±åŠ¨å…¥å£ç»“构体ä¸èµ‹å€¼ç»™Release接å£ï¼Œå½“HDF框架调用Init函数åˆå§‹åŒ–驱动失败时,å¯ä»¥è°ƒç”¨Release释放驱动资æºï¼Œè¯¥å‡½æ•°ä¸éœ€åŒ…å«é‡Šæ”¾å†…å˜å’Œåˆ 除控制器ç‰æ“作。 + + > **说明:**<br> + >所有强制转æ¢èŽ·å–相应对象的æ“作å‰æ是在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 5d3b48a232838a6aad9c30379454759d86153f5c..73b158b58f3380dc511e95cff958e58959b3af01 100644 --- a/zh-cn/device-dev/driver/driver-platform-mipidsi-des.md +++ b/zh-cn/device-dev/driver/driver-platform-mipidsi-des.md @@ -1,52 +1,93 @@ # MIPI DSI - ## 概述 +### 功能简介 + DSI(Display Serial Interface)是由移动行业处ç†å™¨æŽ¥å£è”盟(Mobile Industry Processor Interface (MIPI) Alliance)制定的规范,旨在é™ä½Žç§»åŠ¨è®¾å¤‡ä¸æ˜¾ç¤ºæŽ§åˆ¶å™¨çš„æˆæœ¬ã€‚它以串行的方å¼å‘é€åƒç´ æ•°æ®æˆ–指令给外设(通常是LCD或者类似的显示设备),或从外设ä¸è¯»å–状æ€ä¿¡æ¯æˆ–åƒç´ ä¿¡æ¯ï¼›å®ƒå®šä¹‰äº†ä¸»æœºã€å›¾åƒæ•°æ®æºå’Œç›®æ ‡è®¾å¤‡ä¹‹é—´çš„串行总线和通信å议。 MIPI DSI具备高速模å¼å’Œä½Žé€Ÿæ¨¡å¼ä¸¤ç§å·¥ä½œæ¨¡å¼ï¼Œå…¨éƒ¨æ•°æ®é€šé“都å¯ä»¥ç”¨äºŽå•å‘çš„é«˜é€Ÿä¼ è¾“ï¼Œä½†åªæœ‰ç¬¬ä¸€ä¸ªæ•°æ®é€šé“æ‰å¯ç”¨äºŽä½Žé€ŸåŒå‘ä¼ è¾“ï¼Œä»Žå±žç«¯çš„çŠ¶æ€ä¿¡æ¯ã€åƒç´ ç‰æ˜¯é€šè¿‡è¯¥æ•°æ®é€šé“返回。时钟通é“ä¸“ç”¨äºŽåœ¨é«˜é€Ÿä¼ è¾“æ•°æ®çš„过程ä¸ä¼ 输åŒæ¥æ—¶é’Ÿä¿¡å·ã€‚ 图1显示了简化的DSI接å£ã€‚从概念上看,符åˆDSI的接å£ä¸ŽåŸºäºŽDBI-2å’ŒDPI-2æ ‡å‡†çš„æŽ¥å£å…·æœ‰ç›¸åŒçš„功能。它å‘å¤–å›´è®¾å¤‡ä¼ è¾“åƒç´ 或命令数æ®ï¼Œå¹¶ä¸”å¯ä»¥ä»Žå¤–围设备读å–状æ€æˆ–åƒç´ ä¿¡æ¯ã€‚主è¦åŒºåˆ«åœ¨äºŽï¼ŒDSI对所有åƒç´ æ•°æ®ã€å‘½ä»¤å’Œäº‹ä»¶è¿›è¡Œåºåˆ—åŒ–ï¼Œè€Œåœ¨ä¼ ç»ŸæŽ¥å£ä¸ï¼Œè¿™äº›åƒç´ æ•°æ®ã€å‘½ä»¤å’Œäº‹ä»¶é€šå¸¸éœ€è¦é™„åŠ æŽ§åˆ¶ä¿¡å·æ‰èƒ½åœ¨å¹¶è¡Œæ•°æ®æ€»çº¿ä¸Šä¼ 输。 - **图1** DSIå‘é€ã€æŽ¥æ”¶æŽ¥å£ +**图1** DSIå‘é€ã€æŽ¥æ”¶æŽ¥å£ -  + +DSIæ ‡å‡†å¯¹åº”D-PHYã€DSIã€DCS规范,å¯åˆ†ä¸ºå››å±‚: -## 接å£è¯´æ˜Ž +- PHY Layer - **表1** MIPI DSI API接å£åŠŸèƒ½ä»‹ç» + å®šä¹‰äº†ä¼ è¾“åª’ä»‹ï¼Œè¾“å…¥/输出电路和和时钟和信å·æœºåˆ¶ã€‚PHYå±‚æŒ‡å®šä¼ è¾“ä»‹è´¨(电导体)ã€è¾“å…¥/输出电路和从串行比特æµä¸æ•èŽ·â€œ1â€å’Œâ€œ0â€çš„æ—¶é’Ÿæœºåˆ¶ã€‚è¿™ä¸€éƒ¨åˆ†çš„è§„èŒƒè®°å½•äº†ä¼ è¾“ä»‹è´¨çš„ç‰¹æ€§ã€ä¿¡å·çš„电气å‚数以åŠæ—¶é’Ÿä¸Žæ•°æ®é€šé“之间的时åºå…³ç³»ã€‚在DSI链路的å‘é€ç«¯ï¼Œå¹¶è¡Œæ•°æ®ã€ä¿¡å·äº‹ä»¶å’Œå‘½ä»¤æŒ‰ç…§åŒ…组织在å议层转æ¢ä¸ºåŒ…。åè®®å±‚é™„åŠ åŒ…å议信æ¯å’ŒæŠ¥å¤´ï¼Œç„¶åŽé€šè¿‡Lane Management层å‘PHYå‘é€å®Œæ•´çš„å—节。数æ®ç”±PHY进行åºåˆ—化,并通过串行链路å‘é€ã€‚DSI链路的接收端执行与å‘é€ç«¯ç›¸åçš„æ“作,将数æ®åŒ…分解为并行的数æ®ã€ä¿¡å·äº‹ä»¶å’Œå‘½ä»¤ã€‚如果有多个Lane, Lane管ç†å±‚å°†å—节分é…ç»™å•ç‹¬çš„物ç†å±‚,æ¯ä¸ªLane一个PHY。 -| 功能分类 | 接å£å | -| -------- | -------- | -| 设置/获å–当å‰MIPI DSI相关é…ç½® | - MipiDsiSetCfg:设置MIPI DSI相关é…ç½®<br/>- MipiDsiGetCfg:获å–当å‰MIPI DSI相关é…ç½® | -| 获å–/释放MIPI DSIæ“作å¥æŸ„ | - MipiDsiOpen:获å–MIPI DSIæ“作å¥æŸ„<br/>- MipiDsiClose:释放MIPI DSIæ“作å¥æŸ„ | -| 设置MIPI DSI进入Low power模å¼/High speedæ¨¡å¼ | - MipiDsiSetLpMode:设置MIPI DSI进入Low power模å¼<br/>- MipiDsiSetHsMode:设置MIPI DSI进入High speedæ¨¡å¼ | -| MIPI DSIå‘é€/回读指令 | - MipiDsiTx:MIPI DSIå‘é€ç›¸åº”指令的接å£<br/>- MipiDsiRx:MIPI DSIæŒ‰æœŸæœ›é•¿åº¦å›žè¯»çš„æŽ¥å£ | +- Lane Management层 + + è´Ÿè´£å‘é€å’Œæ”¶é›†æ•°æ®æµåˆ°æ¯æ¡Lane。数æ®Lane的三ç§æ“ä½œæ¨¡å¼ ï¼šespace mode,High-Speed(Burst) mode,Control mode。 + +- Low Level Protocol层 + + 定义了如何组帧和解æžä»¥åŠé”™è¯¯æ£€æµ‹ç‰ã€‚ + +- Application层 + + æ述高层编ç 和解æžæ•°æ®æµã€‚这一层æ述了数æ®æµä¸åŒ…å«çš„æ•°æ®çš„更高级的编ç å’Œè§£é‡Šã€‚æ ¹æ®æ˜¾ç¤ºå系统架构的ä¸åŒï¼Œå®ƒå¯èƒ½ç”±å…·æœ‰æŒ‡å®šæ ¼å¼çš„åƒç´ 或编ç çš„ä½æµç»„æˆï¼Œæˆ–者由显示模å—内的显示控制器解释的命令组æˆã€‚DSI规范æ述了åƒç´ 值ã€ä½æµã€å‘½ä»¤å’Œå‘½ä»¤å‚数到包集åˆä¸çš„å—èŠ‚çš„æ˜ å°„ã€‚ ->  **说明:**<br> -> 本文涉åŠçš„所有接å£ï¼Œä»…é™å†…æ ¸æ€ä½¿ç”¨ï¼Œä¸æ”¯æŒåœ¨ç”¨æˆ·æ€ä½¿ç”¨ã€‚ +### è¿ä½œæœºåˆ¶ +MIPI DSI软件模å—å„分层的作用为: + +- 接å£å±‚:æ供打开设备ã€å†™å…¥æ•°æ®å’Œå…³é—设备的接å£ã€‚ +- æ ¸å¿ƒå±‚ï¼šä¸»è¦æ供绑定设备ã€åˆå§‹åŒ–设备以åŠé‡Šæ”¾è®¾å¤‡çš„能力。 +- 适é…层:实现其它具体的功能。 + + **说明:**<br>æ ¸å¿ƒå±‚å¯ä»¥è°ƒç”¨æŽ¥å£å±‚çš„å‡½æ•°ï¼Œæ ¸å¿ƒå±‚é€šè¿‡é’©å函数调用适é…层函数,从而适é…层å¯ä»¥é—´æŽ¥çš„调用接å£å±‚函数,但是ä¸å¯é€†è½¬æŽ¥å£å±‚调用适é…层函数。 + +**图2** DSIæ— æœåŠ¡æ¨¡å¼ç»“构图 + + + +### 约æŸä¸Žé™åˆ¶ + +ç”±äºŽä½¿ç”¨æ— æœåŠ¡æ¨¡å¼ï¼ŒMIPI_DSI接å£æš‚ä¸æ”¯æŒç”¨æˆ·æ€ä½¿ç”¨ã€‚ ## 使用指导 +### åœºæ™¯ä»‹ç» + +MIPI DSI主è¦ç”¨äºŽè¿žæŽ¥æ˜¾ç¤ºå±ã€‚ -### 使用æµç¨‹ +### 接å£è¯´æ˜Ž + +MIPI DSI模å—æ供的主è¦æŽ¥å£å¦‚表1所示,具体API详è§//drivers/hdf_core/framework/include/platform/mipi_dsi_if.h。 + +**表1** MIPI DSI API接å£åŠŸèƒ½ä»‹ç» + +| 功能分类 | 接å£å | +| -------- | -------- | +| DevHandle MipiDsiOpen(uint8_t id) | 获å–MIPI DSIæ“作å¥æŸ„ | +| void MipiDsiClose(DevHandle handle) | 释放MIPI DSIæ“作å¥æŸ„ | +| int32_t MipiDsiSetCfg(DevHandle handle, struct MipiCfg \*cfg) | 设置MIPI DSI相关é…ç½® | +| int32_t MipiDsiGetCfg(DevHandle handle, struct MipiCfg \*cfg) | 获å–当å‰MIPI DSI相关é…ç½® | +| void MipiDsiSetLpMode(DevHandle handle) | 设置MIPI DSI进入Low poweræ¨¡å¼ | +| void MipiDsiSetHsMode(DevHandle handle) | 设置MIPI DSI进入High speedæ¨¡å¼ | +| int32_t MipiDsiTx(DevHandle handle, struct DsiCmdDesc \*cmd) | DSIå‘é€æŒ‡ä»¤ | +| int32_t MipiDsiRx(DevHandle handle, struct DsiCmdDesc \*cmd, int32_t readLen, uint8_t \*out) | MIPI DSIæŒ‰æœŸæœ›é•¿åº¦å›žè¯»æ•°æ® | + +### å¼€å‘æ¥éª¤ 使用MIPI DSI的一般æµç¨‹å¦‚下图所示。 - **图2** MIPI DSI使用æµç¨‹å›¾ +**图3** MIPI DSI使用æµç¨‹å›¾ -  + -### 获å–MIPI DSIæ“作å¥æŸ„ +#### 获å–MIPI DSIæ“作å¥æŸ„ 在进行MIPI DSI进行通信å‰ï¼Œé¦–å…ˆè¦è°ƒç”¨MipiDsiOpen获å–æ“作å¥æŸ„,该函数会返回指定通é“IDçš„æ“作å¥æŸ„。 - -``` + +```c DevHandle MipiDsiOpen(uint8_t id); ``` @@ -61,8 +102,8 @@ DevHandle MipiDsiOpen(uint8_t id); å‡è®¾ç³»ç»Ÿä¸çš„MIPI DSI通é“为0,获å–该通é“æ“作å¥æŸ„的示例如下: - -``` + +```c DevHandle mipiDsiHandle = NULL; /* 设备å¥æŸ„ */ chnId = 0; /* MIPI DSI通é“ID */ @@ -75,11 +116,11 @@ if (mipiDsiHandle == NULL) { ``` -### MIPI DSI相应é…ç½® +#### MIPI DSI相应é…ç½® - 写入MIPI DSIé…ç½® - - ``` + + ```c int32_t MipiDsiSetCfg(DevHandle handle, struct MipiCfg *cfg); ``` @@ -93,8 +134,8 @@ if (mipiDsiHandle == NULL) { | 0 | 设置æˆåŠŸ | | è´Ÿæ•° | 设置失败 | - - ``` + + ```c int32_t ret; struct MipiCfg cfg = {0}; @@ -122,8 +163,8 @@ if (mipiDsiHandle == NULL) { ``` - 获å–当å‰MIPI DSIçš„é…ç½® - - ``` + + ```c int32_t MipiDsiGetCfg(DevHandle handle, struct MipiCfg *cfg); ``` @@ -137,8 +178,8 @@ if (mipiDsiHandle == NULL) { | 0 | 获å–æˆåŠŸ | | è´Ÿæ•° | 获å–失败 | - - ``` + + ```c int32_t ret; struct MipiCfg cfg; memset(&cfg, 0, sizeof(struct MipiCfg)); @@ -150,11 +191,11 @@ if (mipiDsiHandle == NULL) { ``` -### å‘é€/回读控制指令 +#### å‘é€/回读控制指令 - å‘é€æŒ‡ä»¤ - - ``` + + ```c int32_t MipiDsiTx(PalHandle handle, struct DsiCmdDesc *cmd); ``` @@ -168,8 +209,8 @@ if (mipiDsiHandle == NULL) { | 0 | å‘é€æˆåŠŸ | | è´Ÿæ•° | å‘é€å¤±è´¥ | - - ``` + + ```c int32_t ret; struct DsiCmdDesc *cmd = OsalMemCalloc(sizeof(struct DsiCmdDesc)); if (cmd == NULL) { @@ -197,8 +238,8 @@ if (mipiDsiHandle == NULL) { ``` - 回读指令 - - ``` + + ```c int32_t MipiDsiRx(DevHandle handle, struct DsiCmdDesc *cmd, uint32_t readLen, uint8_t *out); ``` @@ -214,8 +255,8 @@ if (mipiDsiHandle == NULL) { | 0 | 获å–æˆåŠŸ | | è´Ÿæ•° | 获å–失败 | - - ``` + + ```c int32_t ret; uint8_t readVal = 0; @@ -245,12 +286,11 @@ if (mipiDsiHandle == NULL) { ``` -### 释放MIPI DSIæ“作å¥æŸ„ +#### 释放MIPI DSIæ“作å¥æŸ„ MIPI DSI使用完æˆä¹‹åŽï¼Œéœ€è¦é‡Šæ”¾æ“作å¥æŸ„,释放å¥æŸ„的函数如下所示: - -``` +```c void MipiDsiClose(DevHandle handle); ``` @@ -262,18 +302,18 @@ void MipiDsiClose(DevHandle handle); | -------- | -------- | | handle | MIPI DSIæ“作å¥æŸ„ | - -``` +```c MipiDsiClose(mipiHandle); /* 释放掉MIPI DSIæ“作å¥æŸ„ */ ``` ## 使用实例 +本例拟对Hi3516DV300å¼€å‘æ¿ä¸ŠMIPI DSI设备进行æ“作。 + MIPI DSI完整的使用示例如下所示: - -``` +```c #include "hdf.h" #include "mipi_dsi_if.h" diff --git a/zh-cn/device-dev/driver/driver-platform-mipidsi-develop.md b/zh-cn/device-dev/driver/driver-platform-mipidsi-develop.md index dd819669cac4eb97072375ed70622840d4c2e44e..a83b5de1313a6454aafbd089ee54b4fc80086d57 100755 --- a/zh-cn/device-dev/driver/driver-platform-mipidsi-develop.md +++ b/zh-cn/device-dev/driver/driver-platform-mipidsi-develop.md @@ -1,35 +1,79 @@ # MIPI DSI - ## 概述 -DSI(Display Serial Interface)是由移动行业处ç†å™¨æŽ¥å£è”盟(Mobile Industry Processor Interface (MIPI) Alliance)制定的规范。在HDF框架ä¸ï¼ŒMIPI DSI的接å£é€‚é…模å¼é‡‡ç”¨æ— æœåŠ¡æ¨¡å¼ï¼Œç”¨äºŽä¸éœ€è¦åœ¨ç”¨æˆ·æ€æä¾›API的设备类型,或者没有用户æ€å’Œå†…æ ¸åŒºåˆ†çš„OS系统,其关è”æ–¹å¼æ˜¯DevHandle直接指å‘è®¾å¤‡å¯¹è±¡å†…æ ¸æ€åœ°å€ï¼ˆDevHandle是一个void类型指针)。 +### 功能简介 + +DSI(Display Serial Interface)是由移动行业处ç†å™¨æŽ¥å£è”盟(Mobile Industry Processor Interface (MIPI) Alliance)制定的规范,旨在é™ä½Žç§»åŠ¨è®¾å¤‡ä¸æ˜¾ç¤ºæŽ§åˆ¶å™¨çš„æˆæœ¬ã€‚它以串行的方å¼å‘é€åƒç´ æ•°æ®æˆ–指令给外设(通常是LCD或者类似的显示设备),或从外设ä¸è¯»å–状æ€ä¿¡æ¯æˆ–åƒç´ ä¿¡æ¯ï¼›å®ƒå®šä¹‰äº†ä¸»æœºã€å›¾åƒæ•°æ®æºå’Œç›®æ ‡è®¾å¤‡ä¹‹é—´çš„串行总线和通信å议。 + +MIPI DSI具备高速模å¼å’Œä½Žé€Ÿæ¨¡å¼ä¸¤ç§å·¥ä½œæ¨¡å¼ï¼Œå…¨éƒ¨æ•°æ®é€šé“都å¯ä»¥ç”¨äºŽå•å‘çš„é«˜é€Ÿä¼ è¾“ï¼Œä½†åªæœ‰ç¬¬ä¸€ä¸ªæ•°æ®é€šé“æ‰å¯ç”¨äºŽä½Žé€ŸåŒå‘ä¼ è¾“ï¼Œä»Žå±žç«¯çš„çŠ¶æ€ä¿¡æ¯ã€åƒç´ ç‰æ˜¯é€šè¿‡è¯¥æ•°æ®é€šé“返回。时钟通é“ä¸“ç”¨äºŽåœ¨é«˜é€Ÿä¼ è¾“æ•°æ®çš„过程ä¸ä¼ 输åŒæ¥æ—¶é’Ÿä¿¡å·ã€‚ + +图1显示了简化的DSI接å£ã€‚从概念上看,符åˆDSI的接å£ä¸ŽåŸºäºŽDBI-2å’ŒDPI-2æ ‡å‡†çš„æŽ¥å£å…·æœ‰ç›¸åŒçš„功能。它å‘å¤–å›´è®¾å¤‡ä¼ è¾“åƒç´ 或命令数æ®ï¼Œå¹¶ä¸”å¯ä»¥ä»Žå¤–围设备读å–状æ€æˆ–åƒç´ ä¿¡æ¯ã€‚主è¦åŒºåˆ«åœ¨äºŽï¼ŒDSI对所有åƒç´ æ•°æ®ã€å‘½ä»¤å’Œäº‹ä»¶è¿›è¡Œåºåˆ—åŒ–ï¼Œè€Œåœ¨ä¼ ç»ŸæŽ¥å£ä¸ï¼Œè¿™äº›åƒç´ æ•°æ®ã€å‘½ä»¤å’Œäº‹ä»¶é€šå¸¸éœ€è¦é™„åŠ æŽ§åˆ¶ä¿¡å·æ‰èƒ½åœ¨å¹¶è¡Œæ•°æ®æ€»çº¿ä¸Šä¼ 输。 + +**图1** DSIå‘é€ã€æŽ¥æ”¶æŽ¥å£ + + + +DSIæ ‡å‡†å¯¹åº”D-PHYã€DSIã€DCS规范,å¯åˆ†ä¸ºå››å±‚: + +- PHY Layer + + å®šä¹‰äº†ä¼ è¾“åª’ä»‹ï¼Œè¾“å…¥/输出电路和和时钟和信å·æœºåˆ¶ã€‚PHYå±‚æŒ‡å®šä¼ è¾“ä»‹è´¨(电导体)ã€è¾“å…¥/输出电路和从串行比特æµä¸æ•èŽ·â€œ1â€å’Œâ€œ0â€çš„æ—¶é’Ÿæœºåˆ¶ã€‚è¿™ä¸€éƒ¨åˆ†çš„è§„èŒƒè®°å½•äº†ä¼ è¾“ä»‹è´¨çš„ç‰¹æ€§ã€ä¿¡å·çš„电气å‚数以åŠæ—¶é’Ÿä¸Žæ•°æ®é€šé“之间的时åºå…³ç³»ã€‚在DSI链路的å‘é€ç«¯ï¼Œå¹¶è¡Œæ•°æ®ã€ä¿¡å·äº‹ä»¶å’Œå‘½ä»¤æŒ‰ç…§åŒ…组织在å议层转æ¢ä¸ºåŒ…。åè®®å±‚é™„åŠ åŒ…å议信æ¯å’ŒæŠ¥å¤´ï¼Œç„¶åŽé€šè¿‡Lane Management层å‘PHYå‘é€å®Œæ•´çš„å—节。数æ®ç”±PHY进行åºåˆ—化,并通过串行链路å‘é€ã€‚DSI链路的接收端执行与å‘é€ç«¯ç›¸åçš„æ“作,将数æ®åŒ…分解为并行的数æ®ã€ä¿¡å·äº‹ä»¶å’Œå‘½ä»¤ã€‚如果有多个Lane, Lane管ç†å±‚å°†å—节分é…ç»™å•ç‹¬çš„物ç†å±‚,æ¯ä¸ªLane一个PHY。 + +- Lane Management层 + + è´Ÿè´£å‘é€å’Œæ”¶é›†æ•°æ®æµåˆ°æ¯æ¡Lane。数æ®Lane的三ç§æ“ä½œæ¨¡å¼ ï¼šespace mode, High-Speed(Burst) mode, Control mode 。 + +- Low Level Protocol层 - **图1** DSIæ— æœåŠ¡æ¨¡å¼ç»“构图 + 定义了如何组帧和解æžä»¥åŠé”™è¯¯æ£€æµ‹ç‰ã€‚ + +- Application层 + + æ述高层编ç 和解æžæ•°æ®æµã€‚这一层æ述了数æ®æµä¸åŒ…å«çš„æ•°æ®çš„更高级的编ç å’Œè§£é‡Šã€‚æ ¹æ®æ˜¾ç¤ºå系统架构的ä¸åŒï¼Œå®ƒå¯èƒ½ç”±å…·æœ‰æŒ‡å®šæ ¼å¼çš„åƒç´ 或编ç çš„ä½æµç»„æˆï¼Œæˆ–者由显示模å—内的显示控制器解释的命令组æˆã€‚DSI规范æ述了åƒç´ 值ã€ä½æµã€å‘½ä»¤å’Œå‘½ä»¤å‚数到包集åˆä¸çš„å—èŠ‚çš„æ˜ å°„ã€‚ + +### è¿ä½œæœºåˆ¶ + +MIPI DSI软件模å—å„分层的作用为: + +- 接å£å±‚:æ供打开设备ã€å†™å…¥æ•°æ®å’Œå…³é—设备的接å£ã€‚ +- æ ¸å¿ƒå±‚ï¼šä¸»è¦æ供绑定设备ã€åˆå§‹åŒ–设备以åŠé‡Šæ”¾è®¾å¤‡çš„能力。 +- 适é…层:实现其它具体的功能。 + + **说明:**<br>æ ¸å¿ƒå±‚å¯ä»¥è°ƒç”¨æŽ¥å£å±‚çš„å‡½æ•°ï¼Œæ ¸å¿ƒå±‚é€šè¿‡é’©å函数调用适é…层函数,从而适é…层å¯ä»¥é—´æŽ¥çš„调用接å£å±‚函数,但是ä¸å¯é€†è½¬æŽ¥å£å±‚调用适é…层函数。 + + + **图2** DSIæ— æœåŠ¡æ¨¡å¼ç»“构图  +## å¼€å‘指导 + + ### åœºæ™¯ä»‹ç» -## 接å£è¯´æ˜Ž +MIPI DSI仅是一个软件层é¢çš„概念,主è¦å·¥ä½œæ˜¯MIPI DSI资æºç®¡ç†ã€‚å¼€å‘者å¯ä»¥é€šè¿‡ä½¿ç”¨æ供的æ供的æ“作接å£ï¼Œå®žçŽ°DSI资æºç®¡ç†ã€‚当驱动开å‘者需è¦å°†MIPI DSI设备适é…到OpenHarmony时,需è¦è¿›è¡ŒMIPI DSI驱动适é…,下文将介ç»å¦‚何进行MIPI DSI驱动适é…。 + +### 接å£è¯´æ˜Ž + +为了ä¿è¯ä¸Šå±‚在调用MIPI DSI接å£æ—¶èƒ½å¤Ÿæ£ç¡®çš„æ“ä½œç¡¬ä»¶ï¼Œæ ¸å¿ƒå±‚åœ¨//drivers/hdf_core/framework/support/platform/include/mipi/mipi_dsi_core.hä¸å®šä¹‰äº†ä»¥ä¸‹é’©å函数。驱动适é…者需è¦åœ¨é€‚é…层实现这些函数的具体功能,并与这些钩å函数挂接,从而完æˆæŽ¥å£å±‚ä¸Žæ ¸å¿ƒå±‚çš„äº¤äº’ã€‚ MipiDsiCntlrMethod定义: - -``` +```c struct MipiDsiCntlrMethod { // æ ¸å¿ƒå±‚ç»“æž„ä½“çš„æˆå‘˜å‡½æ•° int32_t (*setCntlrCfg)(struct MipiDsiCntlr *cntlr); int32_t (*setCmd)(struct MipiDsiCntlr *cntlr, struct DsiCmdDesc *cmd); int32_t (*getCmd)(struct MipiDsiCntlr *cntlr, struct DsiCmdDesc *cmd, uint32_t readLen, uint8_t *out); void (*toHs)(struct MipiDsiCntlr *cntlr); void (*toLp)(struct MipiDsiCntlr *cntlr); - void (*enterUlps)(struct MipiDsiCntlr *cntlr); //ã€å¯é€‰ã€‘è¿›å…¥è¶…ä½ŽåŠŸè€—æ¨¡å¼ - void (*exitUlps)(struct MipiDsiCntlr *cntlr); //ã€å¯é€‰ã€‘é€€å‡ºè¶…ä½ŽåŠŸè€—æ¨¡å¼ - int32_t (*powerControl)(struct MipiDsiCntlr *cntlr, uint8_t enable);//ã€å¯é€‰ã€‘使能/去使能功耗控制 - int32_t (*attach)(struct MipiDsiCntlr *cntlr); //ã€å¯é€‰ã€‘将一个DSI设备连接上host + void (*enterUlps)(struct MipiDsiCntlr *cntlr); //ã€å¯é€‰ã€‘è¿›å…¥è¶…ä½ŽåŠŸè€—æ¨¡å¼ + void (*exitUlps)(struct MipiDsiCntlr *cntlr); //ã€å¯é€‰ã€‘é€€å‡ºè¶…ä½ŽåŠŸè€—æ¨¡å¼ + int32_t (*powerControl)(struct MipiDsiCntlr *cntlr, uint8_t enable); //ã€å¯é€‰ã€‘使能/去使能功耗控制 + int32_t (*attach)(struct MipiDsiCntlr *cntlr); //ã€å¯é€‰ã€‘将一个DSI设备连接上host }; ``` - **表1** MipiDsiCntlrMethodæˆå‘˜çš„回调函数功能说明 + **表1** MipiDsiCntlrMethodæˆå‘˜çš„é’©å函数功能说明 | æˆå‘˜å‡½æ•° | å…¥å‚ | å‡ºå‚ | è¿”å›žçŠ¶æ€ | 功能 | | -------- | -------- | -------- | -------- | -------- | @@ -40,7 +84,7 @@ struct MipiDsiCntlrMethod { // æ ¸å¿ƒå±‚ç»“æž„ä½“çš„æˆå‘˜å‡½æ•° | toLp | cntlr:结构体指针,MipiDsi控制器 | æ— | HDF_STATUSç›¸å…³çŠ¶æ€ | è®¾ç½®ä¸ºä½Žç”µæ¨¡å¼ | -## å¼€å‘æ¥éª¤ +### å¼€å‘æ¥éª¤ MIPI DSI模å—适é…的三个必选环节是é…置属性文件,实例化驱动入å£ï¼Œä»¥åŠå®žä¾‹åŒ–æ ¸å¿ƒå±‚æŽ¥å£å‡½æ•°ã€‚ @@ -63,91 +107,91 @@ MIPI DSI模å—适é…的三个必选环节是é…置属性文件,实例化驱动 ã€å¯é€‰ã€‘针对新增驱动程åºï¼Œå»ºè®®éªŒè¯é©±åŠ¨åŸºæœ¬åŠŸèƒ½ï¼Œä¾‹å¦‚挂载åŽçš„ä¿¡æ¯å馈,数æ®ä¼ 输的æˆåŠŸä¸Žå¦ç‰ã€‚ -## å¼€å‘实例 +### å¼€å‘实例 -下方将以mipi_tx_hi35xx.c为示例,展示需è¦åŽ‚商æ供哪些内容æ¥å®Œæ•´å®žçŽ°è®¾å¤‡åŠŸèƒ½ã€‚ +下方将以mipi_tx_hi35xx.c为示例,展示需è¦é©±åŠ¨é€‚é…者æ供哪些内容æ¥å®Œæ•´å®žçŽ°è®¾å¤‡åŠŸèƒ½ã€‚ -1. 一般æ¥è¯´ï¼Œé©±åŠ¨å¼€å‘首先需è¦åœ¨xx_config.hcsä¸é…置器件属性,并在device_info.hcs文件ä¸æ·»åŠ deviceNodeæ述。 +1. 一般æ¥è¯´ï¼Œé©±åŠ¨å¼€å‘首先需è¦mipicsi_config.hcsé…置文件,在其ä¸é…置器件属性,并在//vendor/hisilicon/hispark_taurus/hdf_config/device_info/device_info.hcs文件ä¸æ·»åŠ deviceNodeæ述。deviceNode与é…置属性的对应关系是ä¾é deviceMatchAttrå—段æ¥å®Œæˆçš„。åªæœ‰å½“deviceNode下的deviceMatchAttrå—段与é…置属性文件ä¸çš„match_attrå—段完全相åŒæ—¶ï¼Œé©±åŠ¨æ‰èƒ½æ£ç¡®è¯»å–é…置数æ®ã€‚ å™¨ä»¶å±žæ€§å€¼ä¸Žæ ¸å¿ƒå±‚MipiDsiCntlræˆå‘˜çš„默认值或é™åˆ¶èŒƒå›´æœ‰å¯†åˆ‡å…³ç³»ï¼ŒdeviceNodeä¿¡æ¯ä¸Žé©±åŠ¨å…¥å£æ³¨å†Œç›¸å…³ã€‚ - 但本例ä¸MIPIæŽ§åˆ¶å™¨æ— éœ€é…ç½®é¢å¤–属性,如有厂商需è¦ï¼Œåˆ™éœ€è¦åœ¨device_info文件的deviceNodeå¢žåŠ deviceMatchAtträ¿¡æ¯ï¼Œä»¥åŠå¢žåŠ mipidsi_config文件。 + 但本例ä¸MIPIæŽ§åˆ¶å™¨æ— éœ€é…ç½®é¢å¤–属性,驱动适é…者如有需è¦ï¼Œåˆ™éœ€è¦åœ¨device_info.hcs文件的deviceNodeå¢žåŠ deviceMatchAtträ¿¡æ¯ï¼Œä»¥åŠå¢žåŠ mipidsi_config.hcs文件。 - device_info.hcs é…ç½®å‚考: - - ``` + device_info.hcs é…ç½®å‚考: + + ```c root { - device_info { - match_attr = "hdf_manager"; - platform :: host { - hostName = "platform_host"; - priority = 50; - device_mipi_dsi:: device { - device0 :: deviceNode { - policy = 0; - priority = 150; - permission = 0644; - moduleName = "HDF_MIPI_TX"; // ã€å¿…è¦ã€‘用于指定驱动å称,需è¦ä¸ŽæœŸæœ›çš„驱动Entryä¸çš„moduleName一致。 - serviceName = "HDF_MIPI_TX"; // ã€å¿…è¦ä¸”唯一】驱动对外å‘布æœåŠ¡çš„å称。 + device_info { + match_attr = "hdf_manager"; + platform :: host { + hostName = "platform_host"; + priority = 50; + device_mipi_dsi:: device { + device0 :: deviceNode { + policy = 0; + priority = 150; + permission = 0644; + moduleName = "HDF_MIPI_TX"; // ã€å¿…è¦ã€‘用于指定驱动å称,需è¦ä¸ŽæœŸæœ›çš„驱动Entryä¸çš„moduleName一致。 + serviceName = "HDF_MIPI_TX"; // ã€å¿…è¦ä¸”唯一】驱动对外å‘布æœåŠ¡çš„å称。 + } + } } } - } - } } ``` 2. 完æˆå™¨ä»¶å±žæ€§æ–‡ä»¶çš„é…置之åŽï¼Œä¸‹ä¸€æ¥è¯·å®žä¾‹åŒ–驱动入å£ã€‚ - 驱动入å£å¿…须为HdfDriverEntry(在hdf_device_desc.hä¸å®šä¹‰ï¼‰ç±»åž‹çš„全局å˜é‡ï¼Œä¸”moduleNameè¦å’Œdevice_info.hcsä¸ä¿æŒä¸€è‡´ã€‚HdfDriverEntry结构体的函数指针æˆå‘˜ä¼šè¢«åŽ‚商æ“作函数填充,HDFæ¡†æž¶ä¼šå°†æ‰€æœ‰åŠ è½½çš„é©±åŠ¨çš„HdfDriverEntry对象首地å€æ±‡æ€»ï¼Œå½¢æˆä¸€ä¸ªç±»ä¼¼æ•°ç»„,方便调用。 + 驱动入å£å¿…须为HdfDriverEntry(在hdf_device_desc.hä¸å®šä¹‰ï¼‰ç±»åž‹çš„全局å˜é‡ï¼Œä¸”moduleNameè¦å’Œdevice_info.hcsä¸ä¿æŒä¸€è‡´ã€‚HdfDriverEntry结构体的函数指针æˆå‘˜éœ€è¦è¢«é©±åŠ¨é€‚é…者æ“作函数填充,HDFæ¡†æž¶ä¼šå°†æ‰€æœ‰åŠ è½½çš„é©±åŠ¨çš„HdfDriverEntry对象首地å€æ±‡æ€»ï¼Œå½¢æˆä¸€ä¸ªç±»ä¼¼æ•°ç»„,方便调用。 ä¸€èˆ¬åœ¨åŠ è½½é©±åŠ¨æ—¶HDF框架会先调用Bind函数,å†è°ƒç”¨Initå‡½æ•°åŠ è½½è¯¥é©±åŠ¨ã€‚å½“Init调用异常时,HDF框架会调用Release释放驱动资æºå¹¶é€€å‡ºã€‚ MIPI DSI驱动入å£å‚考: - ``` + ```c struct HdfDriverEntry g_mipiTxDriverEntry = { - .moduleVersion = 1, - .Init = Hi35xxMipiTxInit, // è§Initå‚考 - .Release = Hi35xxMipiTxRelease,// è§Releaseå‚考 - .moduleName = "HDF_MIPI_TX", // ã€å¿…è¦ã€‘需è¦ä¸Ždevice_info.hcs ä¸ä¿æŒä¸€è‡´ã€‚ + .moduleVersion = 1, + .Init = Hi35xxMipiTxInit, // è§Initå¼€å‘å‚考 + .Release = Hi35xxMipiTxRelease, // è§Releaseå¼€å‘å‚考 + .moduleName = "HDF_MIPI_TX", // ã€å¿…è¦ã€‘需è¦ä¸Ždevice_info.hcs ä¸ä¿æŒä¸€è‡´ã€‚ }; - HDF_INIT(g_mipiTxDriverEntry); // 调用HDF_INIT将驱动入å£æ³¨å†Œåˆ°HDFæ¡†æž¶ä¸ + HDF_INIT(g_mipiTxDriverEntry); // 调用HDF_INIT将驱动入å£æ³¨å†Œåˆ°HDFæ¡†æž¶ä¸ ``` -3. 完æˆé©±åŠ¨å…¥å£æ³¨å†Œä¹‹åŽï¼Œä¸‹ä¸€æ¥å°±æ˜¯ä»¥æ ¸å¿ƒå±‚MipiDsiCntlr对象的åˆå§‹åŒ–ä¸ºæ ¸å¿ƒï¼ŒåŒ…æ‹¬åŽ‚å•†è‡ªå®šä¹‰ç»“æž„ä½“ï¼ˆä¼ é€’å‚数和数æ®ï¼‰ï¼Œå®žä¾‹åŒ–MipiDsiCntlræˆå‘˜MipiDsiCntlrMethod(让用户å¯ä»¥é€šè¿‡æŽ¥å£æ¥è°ƒç”¨é©±åŠ¨åº•å±‚函数),实现HdfDriverEntryæˆå‘˜å‡½æ•°ï¼ˆBindã€Initã€Release)。 +3. 完æˆé©±åŠ¨å…¥å£æ³¨å†Œä¹‹åŽï¼Œä¸‹ä¸€æ¥å°±æ˜¯ä»¥æ ¸å¿ƒå±‚MipiDsiCntlr对象的åˆå§‹åŒ–ä¸ºæ ¸å¿ƒï¼ŒåŒ…æ‹¬é©±åŠ¨é€‚é…è€…è‡ªå®šä¹‰ç»“æž„ä½“ï¼ˆä¼ é€’å‚数和数æ®ï¼‰ï¼Œå®žä¾‹åŒ–MipiDsiCntlræˆå‘˜MipiDsiCntlrMethod(让用户å¯ä»¥é€šè¿‡æŽ¥å£æ¥è°ƒç”¨é©±åŠ¨åº•å±‚函数),实现HdfDriverEntryæˆå‘˜å‡½æ•°ï¼ˆBindã€Initã€Release)。 - 自定义结构体å‚考 从驱动的角度看,自定义结构体是å‚数和数æ®çš„载体,一般æ¥è¯´ï¼Œconfig文件ä¸çš„数值也会用æ¥åˆå§‹åŒ–结构体æˆå‘˜ï¼Œä½†æœ¬ä¾‹çš„mipidsiæ— å™¨ä»¶å±žæ€§æ–‡ä»¶ï¼Œæ•…åŸºæœ¬æˆå‘˜ç»“构与MipiDsiCntlræ— å¤ªå¤§å·®å¼‚ã€‚ - - ``` + + ```c typedef struct { - unsigned int devno; // è®¾å¤‡å· - short laneId[LANE_MAX_NUM]; // laneå· - OutPutModeTag outputMode; // 输出模å¼é€‰æ‹©ï¼šåˆ·æ–°æ¨¡å¼ï¼Œå‘½ä»¤è¡Œæ¨¡å¼æˆ–视频æµæ¨¡å¼ - VideoModeTag videoMode; // 显示设备的åŒæ¥æ¨¡å¼ - OutputFormatTag outputFormat; // 输出DSI图åƒæ•°æ®æ ¼å¼ï¼šRGB或YUV - SyncInfoTag syncInfo; // æ—¶åºç›¸å…³çš„设置 - unsigned int phyDataRate; // æ•°æ®é€ŸçŽ‡ï¼Œå•ä½Mbps - unsigned int pixelClk; // 时钟,å•ä½KHz + unsigned int devno; // è®¾å¤‡å· + short laneId[LANE_MAX_NUM]; // Laneå· + OutPutModeTag outputMode; // 输出模å¼é€‰æ‹©ï¼šåˆ·æ–°æ¨¡å¼ï¼Œå‘½ä»¤è¡Œæ¨¡å¼æˆ–视频æµæ¨¡å¼ + VideoModeTag videoMode; // 显示设备的åŒæ¥æ¨¡å¼ + OutputFormatTag outputFormat; // 输出DSI图åƒæ•°æ®æ ¼å¼ï¼šRGB或YUV + SyncInfoTag syncInfo; // æ—¶åºç›¸å…³çš„设置 + unsigned int phyDataRate; // æ•°æ®é€ŸçŽ‡ï¼Œå•ä½Mbps + unsigned int pixelClk; // 时钟,å•ä½KHz } ComboDevCfgTag; - // MipiDsiCntlræ˜¯æ ¸å¿ƒå±‚æŽ§åˆ¶å™¨ç»“æž„ä½“ï¼Œå…¶ä¸çš„æˆå‘˜åœ¨Init函数ä¸ä¼šè¢«èµ‹å€¼ã€‚ + /* MipiDsiCntlræ˜¯æ ¸å¿ƒå±‚æŽ§åˆ¶å™¨ç»“æž„ä½“ï¼Œå…¶ä¸çš„æˆå‘˜åœ¨Init函数ä¸ä¼šè¢«èµ‹å€¼ã€‚ */ struct MipiDsiCntlr { - struct IDeviceIoService service; - struct HdfDeviceObject *device; - unsigned int devNo; // è®¾å¤‡å· - struct MipiCfg cfg; - struct MipiDsiCntlrMethod *ops; - struct OsalMutex lock; - void *priv; + struct IDeviceIoService service; + struct HdfDeviceObject *device; + unsigned int devNo; // è®¾å¤‡å· + struct MipiCfg cfg; + struct MipiDsiCntlrMethod *ops; + struct OsalMutex lock; + void *priv; }; ``` - - MipiDsiCntlræˆå‘˜å›žè°ƒå‡½æ•°ç»“构体MipiDsiCntlrMethod的实例化,其他æˆå‘˜åœ¨Init函数ä¸åˆå§‹åŒ–。 + - MipiDsiCntlræˆå‘˜é’©å函数结构体MipiDsiCntlrMethod的实例化,其他æˆå‘˜åœ¨Init函数ä¸åˆå§‹åŒ–。 - - ``` + + ```c static struct MipiDsiCntlrMethod g_method = { .setCntlrCfg = Hi35xxSetCntlrCfg, .setCmd = Hi35xxSetCmd, @@ -156,7 +200,7 @@ MIPI DSI模å—适é…的三个必选环节是é…置属性文件,实例化驱动 .toLp = Hi35xxToLp, }; ``` - - Init函数å‚考 + - Init函数开å‘å‚考 å…¥å‚: @@ -164,8 +208,9 @@ MIPI DSI模å—适é…的三个必选环节是é…置属性文件,实例化驱动 返回值: - HDF_STATUS相关状æ€ï¼ˆä¸‹è¡¨ä¸ºéƒ¨åˆ†å±•ç¤ºï¼Œå¦‚需使用其他状æ€ï¼Œå¯è§//drivers/framework/include/utils/hdf_base.hä¸HDF_STATUS定义)。 + HDF_STATUS相关状æ€ï¼ˆä¸‹è¡¨ä¸ºéƒ¨åˆ†å±•ç¤ºï¼Œå¦‚需使用其他状æ€ï¼Œå¯è§//drivers/hdf_core/framework/include/utils/hdf_base.hä¸HDF_STATUS定义)。 + **表2** HDF_STATUS返回值æè¿° | 状æ€(值) | 问题æè¿° | | -------- | -------- | @@ -178,45 +223,45 @@ MIPI DSI模å—适é…的三个必选环节是é…置属性文件,实例化驱动 函数说明: - MipiDsiCntlrMethod的实例化对象的挂载,调用MipiDsiRegisterCntlr,以åŠå…¶ä»–厂商自定义åˆå§‹åŒ–æ“作。 + MipiDsiCntlrMethod的实例化对象的挂载,调用MipiDsiRegisterCntlr,以åŠå…¶ä»–驱动适é…者自定义åˆå§‹åŒ–æ“作。 - - ``` + + ```c static int32_t Hi35xxMipiTxInit(struct HdfDeviceObject *device) { - int32_t ret; - g_mipiTx.priv = NULL; // g_mipiTx是定义的全局å˜é‡ - // static struct MipiDsiCntlr g_mipiTx { - // .devNo=0 - //}; - g_mipiTx.ops = &g_method; // MipiDsiCntlrMethod的实例化对象的挂载 - ret = MipiDsiRegisterCntlr(&g_mipiTx, device);// ã€å¿…è¦ã€‘è°ƒç”¨æ ¸å¿ƒå±‚å‡½æ•°å’Œg_mipiTxåˆå§‹åŒ–æ ¸å¿ƒå±‚å…¨å±€å˜é‡ - ... - return MipiTxDrvInit(0); // ã€å¿…è¦ã€‘厂商对设备的åˆå§‹åŒ–,形å¼ä¸é™ + int32_t ret; + g_mipiTx.priv = NULL; // g_mipiTx是定义的全局å˜é‡ + // static struct MipiDsiCntlr g_mipiTx { + // .devNo=0 + //}; + g_mipiTx.ops = &g_method; // MipiDsiCntlrMethod的实例化对象的挂载 + ret = MipiDsiRegisterCntlr(&g_mipiTx, device); // ã€å¿…è¦ã€‘è°ƒç”¨æ ¸å¿ƒå±‚å‡½æ•°å’Œg_mipiTxåˆå§‹åŒ–æ ¸å¿ƒå±‚å…¨å±€å˜é‡ + ... + return MipiTxDrvInit(0); // ã€å¿…è¦ã€‘驱动适é…者对设备的åˆå§‹åŒ–,形å¼ä¸é™ } - // mipi_dsi_core.cæ ¸å¿ƒå±‚ + /* mipi_dsi_core.cæ ¸å¿ƒå±‚ */ int32_t MipiDsiRegisterCntlr(struct MipiDsiCntlr *cntlr, struct HdfDeviceObject *device) { - ... - // 定义的全局å˜é‡ï¼šstatic struct MipiDsiHandle g_mipiDsihandle[MAX_CNTLR_CNT]; - if (g_mipiDsihandle[cntlr->devNo].cntlr == NULL) { - (void)OsalMutexInit(&g_mipiDsihandle[cntlr->devNo].lock); - (void)OsalMutexInit(&(cntlr->lock)); - - g_mipiDsihandle[cntlr->devNo].cntlr = cntlr;// åˆå§‹åŒ–MipiDsiHandleæˆå‘˜ - g_mipiDsihandle[cntlr->devNo].priv = NULL; - cntlr->device = device; // 使HdfDeviceObject与MipiDsiHandleå¯ä»¥ç›¸äº’转化的å‰æ - device->service = &(cntlr->service); // 使HdfDeviceObject与MipiDsiHandleå¯ä»¥ç›¸äº’转化的å‰æ - cntlr->priv = NULL; ... - return HDF_SUCCESS; - } - ... - return HDF_FAILURE; + /* 定义的全局å˜é‡ï¼šstatic struct MipiDsiHandle g_mipiDsihandle[MAX_CNTLR_CNT]; */ + if (g_mipiDsihandle[cntlr->devNo].cntlr == NULL) { + (void)OsalMutexInit(&g_mipiDsihandle[cntlr->devNo].lock); + (void)OsalMutexInit(&(cntlr->lock)); + + g_mipiDsihandle[cntlr->devNo].cntlr = cntlr; // åˆå§‹åŒ–MipiDsiHandleæˆå‘˜ + g_mipiDsihandle[cntlr->devNo].priv = NULL; + cntlr->device = device; // 使HdfDeviceObject与MipiDsiHandleå¯ä»¥ç›¸äº’转化的å‰æ + device->service = &(cntlr->service); // 使HdfDeviceObject与MipiDsiHandleå¯ä»¥ç›¸äº’转化的å‰æ + cntlr->priv = NULL; + ... + return HDF_SUCCESS; + } + ... + return HDF_FAILURE; } ``` - - Release函数å‚考 + - Release函数开å‘å‚考 å…¥å‚: @@ -232,18 +277,18 @@ MIPI DSI模å—适é…的三个必选环节是é…置属性文件,实例化驱动 >  **说明:**<br> > 所有强制转æ¢èŽ·å–相应对象的æ“作å‰æ是在Init函数ä¸å…·å¤‡å¯¹åº”赋值的æ“作。 - - ``` + + ```c static void Hi35xxMipiTxRelease(struct HdfDeviceObject *device) { - struct MipiDsiCntlr *cntlr = NULL; - ... - cntlr = MipiDsiCntlrFromDevice(device);// 这里有HdfDeviceObject到MipiDsiCntlr的强制转化 - // return (device == NULL) ? NULL : (struct MipiDsiCntlr *)device->service; - ... - MipiTxDrvExit(); // ã€å¿…è¦ã€‘对厂商设备所å 资æºçš„释放 - MipiDsiUnregisterCntlr(&g_mipiTx); // 空函数 - g_mipiTx.priv = NULL; - HDF_LOGI("%s: unload mipi_tx driver 1212!", __func__); - } + struct MipiDsiCntlr *cntlr = NULL; + ... + cntlr = MipiDsiCntlrFromDevice(device); // 这里有HdfDeviceObject到MipiDsiCntlr的强制转化 + // return (device == NULL) ? NULL : (struct MipiDsiCntlr *)device->service; + ... + MipiTxDrvExit(); // ã€å¿…è¦ã€‘对设备所å 资æºçš„释放 + MipiDsiUnregisterCntlr(&g_mipiTx); // 空函数 + g_mipiTx.priv = NULL; + HDF_LOGI("%s: unload mipi_tx driver 1212!", __func__); + } ``` diff --git a/zh-cn/device-dev/driver/driver-platform-regulator-des.md b/zh-cn/device-dev/driver/driver-platform-regulator-des.md index ad0aba61272767671e3b9b74022972a521beb6cb..058114fcbb760cfa5ea74bd4d4610893a46dc147 100755 --- a/zh-cn/device-dev/driver/driver-platform-regulator-des.md +++ b/zh-cn/device-dev/driver/driver-platform-regulator-des.md @@ -30,22 +30,23 @@ Regulator接å£å®šä¹‰äº†æ“作Regulator设备的通用方法集åˆï¼ŒåŒ…括: 电æºç®¡ç†èŠ¯ç‰‡ï¼Œå†…å«å¤šä¸ªç”µæºç”šè‡³å…¶ä»–å系统。 - ### è¿ä½œæœºåˆ¶ -在HDF框架ä¸ï¼ŒRegulator模å—接å£é€‚é…模å¼é‡‡ç”¨ç»Ÿä¸€æœåŠ¡æ¨¡å¼ï¼Œè¿™éœ€è¦ä¸€ä¸ªè®¾å¤‡æœåŠ¡æ¥ä½œä¸ºRegulator模å—的管ç†å™¨ï¼Œç»Ÿä¸€å¤„ç†å¤–部访问,这会在é…置文件ä¸æœ‰æ‰€ä½“现。统一æœåŠ¡æ¨¡å¼é€‚åˆäºŽåŒç±»åž‹è®¾å¤‡å¯¹è±¡è¾ƒå¤šçš„情况,如Regulatorå¯èƒ½åŒæ—¶å…·å¤‡åå‡ ä¸ªæŽ§åˆ¶å™¨ï¼Œé‡‡ç”¨ç‹¬ç«‹æœåŠ¡æ¨¡å¼éœ€è¦é…置更多的设备节点,且æœåŠ¡ä¼šå æ®å†…å˜èµ„æºã€‚ +在HDF框架ä¸ï¼ŒRegulator模å—接å£é€‚é…模å¼é‡‡ç”¨ç»Ÿä¸€æœåŠ¡æ¨¡å¼ï¼ˆå¦‚图1),这需è¦ä¸€ä¸ªè®¾å¤‡æœåŠ¡æ¥ä½œä¸ºRegulator模å—的管ç†å™¨ï¼Œç»Ÿä¸€å¤„ç†å¤–部访问,这会在é…置文件ä¸æœ‰æ‰€ä½“现。统一æœåŠ¡æ¨¡å¼é€‚åˆäºŽåŒç±»åž‹è®¾å¤‡å¯¹è±¡è¾ƒå¤šçš„情况,如Regulatorå¯èƒ½åŒæ—¶å…·å¤‡åå‡ ä¸ªæŽ§åˆ¶å™¨ï¼Œé‡‡ç”¨ç‹¬ç«‹æœåŠ¡æ¨¡å¼éœ€è¦é…置更多的设备节点,且æœåŠ¡ä¼šå æ®å†…å˜èµ„æºã€‚相å,采用统一æœåŠ¡æ¨¡å¼å¯ä»¥ä½¿ç”¨ä¸€ä¸ªè®¾å¤‡æœåŠ¡ä½œä¸ºç®¡ç†å™¨ï¼Œç»Ÿä¸€å¤„ç†æ‰€æœ‰åŒç±»åž‹å¯¹è±¡çš„外部访问,实现便æ·ç®¡ç†å’ŒèŠ‚约资æºçš„目的。 -Regulator模å—å„分层的作用为:接å£å±‚æ供打开设备,写入数æ®ï¼Œå…³é—设备接å£çš„èƒ½åŠ›ã€‚æ ¸å¿ƒå±‚ä¸»è¦æ供绑定设备ã€åˆå§‹åŒ–设备以åŠé‡Šæ”¾è®¾å¤‡çš„能力。适é…层实现其他具体的功能。 +Regulator模å—å„分层的作用为: - 说明:<br>æ ¸å¿ƒå±‚å¯ä»¥è°ƒç”¨æŽ¥å£å±‚的函数,也å¯ä»¥é€šè¿‡é’©å函数调用适é…层函数,从而使得适é…层间接的å¯ä»¥è°ƒç”¨æŽ¥å£å±‚函数,但是ä¸å¯é€†è½¬æŽ¥å£å±‚调用适é…层函数。 +- 接å£å±‚:æ供打开设备,æ“作Regulator,关é—设备的能力。 +- æ ¸å¿ƒå±‚ï¼šä¸»è¦è´Ÿè´£æœåŠ¡ç»‘定ã€åˆå§‹åŒ–以åŠé‡Šæ”¾ç®¡ç†å™¨ï¼Œå¹¶æä¾›æ·»åŠ ã€åˆ 除以åŠèŽ·å–Regulator设备的能力。 +- 适é…层:由驱动适é…者实现与硬件相关的具体功能,如设备的åˆå§‹åŒ–ç‰ã€‚ -**图 1** 统一æœåŠ¡æ¨¡å¼ç»“构图 +**图 1** Regulator统一æœåŠ¡æ¨¡å¼ç»“构图<a name="fig1"></a>  ### 约æŸä¸Žé™åˆ¶ -Regulator模å—当å‰ä»…支æŒè½»é‡å’Œå°åž‹ç³»ç»Ÿå†…æ ¸ï¼ˆLiteOS)。 +Regulator模å—API当å‰ä»…支æŒå†…æ ¸æ€è°ƒç”¨ã€‚ ## 使用指导 @@ -58,27 +59,25 @@ Regulator主è¦ç”¨äºŽï¼š ### 接å£è¯´æ˜Ž +Regulator模å—æ供的主è¦æŽ¥å£å¦‚表1所示,具体API详è§//drivers/hdf_core/framework/include/platform/regulator_if.h。 + **表1** Regulator设备API接å£è¯´æ˜Ž -| 接å£å | æè¿° | +| 接å£å | 接å£æè¿° | | --------------------- | ------------------------- | -| RegulatorOpen | 获å–Regulator设备驱动å¥æŸ„ | -| RegulatorClose | 销æ¯Regulator设备驱动å¥æŸ„ | -| RegulatorEnable | 使能Regulator | -| RegulatorDisable | ç¦ç”¨Regulator | -| RegulatorForceDisable | 强制ç¦ç”¨Regulator | -| RegulatorSetVoltage | 设置Regulator输出电压 | -| RegulatorGetVoltage | 获å–Regulator输出电压 | -| RegulatorSetCurrent | 设置Regulatorè¾“å‡ºç”µæµ | -| RegulatorGetCurrent | 获å–Regulatorè¾“å‡ºç”µæµ | -| RegulatorGetStatus | 获å–RegulatorçŠ¶æ€ | - - +| DevHandle RegulatorOpen(const char \*name) | 获å–Regulator设备驱动å¥æŸ„ | +| void RegulatorClose(DevHandle handle) | 销æ¯Regulator设备驱动å¥æŸ„ | +| int32_t RegulatorEnable(DevHandle handle) | 使能Regulator | +| int32_t RegulatorDisable(DevHandle handle) | ç¦ç”¨Regulator | +| int32_t RegulatorForceDisable(DevHandle handle) | 强制ç¦ç”¨Regulator | +| int32_t RegulatorSetVoltage(DevHandle handle, uint32_t minUv, uint32_t maxUv) | 设置Regulator输出电压 | +| int32_t RegulatorGetVoltage(DevHandle handle, uint32_t \*voltage) | 获å–Regulator输出电压 | +| int32_t RegulatorSetCurrent(DevHandle handle, uint32_t minUa, uint32_t maxUa) | 设置Regulatorè¾“å‡ºç”µæµ | +| int32_t RegulatorGetCurrent(DevHandle handle, uint32_t \*regCurrent) | 获å–Regulatorè¾“å‡ºç”µæµ | +| int32_t RegulatorGetStatus(DevHandle handle, uint32_t \*status) | 获å–RegulatorçŠ¶æ€ | ### å¼€å‘æ¥éª¤ -在æ“作系统å¯åŠ¨è¿‡ç¨‹ä¸ï¼Œé©±åŠ¨ç®¡ç†æ¨¡å—æ ¹æ®é…ç½®æ–‡ä»¶åŠ è½½Regulator驱动,Regulator驱动会检测Regulator器件并åˆå§‹åŒ–驱动。 - 使用Regulator设备的一般æµç¨‹å¦‚图2所示。 **图 2** Regulator设备使用æµç¨‹å›¾ @@ -89,7 +88,7 @@ Regulator主è¦ç”¨äºŽï¼š 在æ“作Regulator设备时,首先è¦è°ƒç”¨RegulatorOpen获å–Regulator设备å¥æŸ„,该函数会返回指定设备å称的Regulator设备å¥æŸ„。 -``` +```c DevHandle RegulatorOpen(const char *name); ``` @@ -104,7 +103,7 @@ DevHandle RegulatorOpen(const char *name); -``` +```c /* Regulator设备å称 */ const char *name = "regulator_virtual_1"; DevHandle handle = NULL; @@ -120,7 +119,7 @@ if (handle == NULL) { å…³é—Regulator设备,系统释放对应的资æºã€‚ -``` +```c void RegulatorClose(DevHandle handle); ``` @@ -130,7 +129,7 @@ void RegulatorClose(DevHandle handle); | ------ | ----------------- | | handle | Regulator设备å¥æŸ„ | -``` +```c /* 销æ¯Regulator设备å¥æŸ„ */ RegulatorClose(handle); ``` @@ -139,7 +138,7 @@ RegulatorClose(handle); å¯ç”¨Regulator设备。 -``` +```c int32_t RegulatorEnable(DevHandle handle); ``` @@ -154,7 +153,7 @@ int32_t RegulatorEnable(DevHandle handle); -``` +```c int32_t ret; /* å¯ç”¨Regulator设备 */ @@ -168,7 +167,7 @@ if (ret != 0) { ç¦ç”¨Regulator设备。如果Regulator设备状æ€ä¸ºå¸¸å¼€ï¼Œæˆ–å˜åœ¨Regulator设备å节点未ç¦ç”¨ï¼Œåˆ™ç¦ç”¨å¤±è´¥ã€‚ -``` +```c int32_t RegulatorDisable(DevHandle handle); ``` @@ -181,7 +180,7 @@ int32_t RegulatorDisable(DevHandle handle); | 0 | ç¦ç”¨æˆåŠŸ | | è´Ÿæ•° | ç¦ç”¨å¤±è´¥ | -``` +```c int32_t ret; /* ç¦ç”¨Regulator设备 */ @@ -195,7 +194,7 @@ if (ret != 0) { 强制ç¦ç”¨Regulatorè®¾å¤‡ã€‚æ— è®ºRegulator设备的状æ€æ˜¯å¸¸å¼€è¿˜æ˜¯å节点已使能,Regulator设备都会被ç¦ç”¨ã€‚ -``` +```c int32_t RegulatorForceDisable(DevHandle handle); ``` @@ -209,7 +208,7 @@ int32_t RegulatorForceDisable(DevHandle handle); | 0 | ç¦ç”¨æˆåŠŸ | | è´Ÿæ•° | ç¦ç”¨å¤±è´¥ | -``` +```c int32_t ret; /* 强制ç¦ç”¨Regulator设备 */ @@ -221,9 +220,7 @@ if (ret != 0) { #### 设置Regulator输出电压范围 -设置Regulator电压输出电压范围。 - -``` +```c int32_t RegulatorSetVoltage(DevHandle handle, uint32_t minUv, uint32_t maxUv); ``` @@ -238,7 +235,7 @@ int32_t RegulatorSetVoltage(DevHandle handle, uint32_t minUv, uint32_t maxUv); | 0 | 设置æˆåŠŸ | | è´Ÿæ•° | 设置失败 | -``` +```c int32_t ret; int32_t minUv = 0; // 最å°ç”µåŽ‹ä¸º0µV int32_t maxUv = 20000; // 最大电压为20000µV @@ -252,9 +249,7 @@ if (ret != 0) { #### 获å–Regulator电压 -获å–Regulator电压。 - -``` +```c int32_t RegulatorGetVoltage(DevHandle handle, uint32_t *voltage); ``` @@ -269,7 +264,7 @@ int32_t RegulatorGetVoltage(DevHandle handle, uint32_t *voltage); | 0 | 获å–æˆåŠŸ | | è´Ÿæ•° | 获å–失败 | -``` +```c int32_t ret; uint32_t voltage; @@ -282,9 +277,7 @@ if (ret != 0) { #### 设置Regulator输出电æµèŒƒå›´ -设置Regulator输出电æµèŒƒå›´ã€‚ - -``` +```c int32_t RegulatorSetCurrent(DevHandle handle, uint32_t minUa, uint32_t maxUa); ``` @@ -299,9 +292,9 @@ int32_t RegulatorSetCurrent(DevHandle handle, uint32_t minUa, uint32_t maxUa); | 0<br>| 设置æˆåŠŸ | | è´Ÿæ•° | 设置失败 | -``` +```c int32_t ret; -int32_t minUa = 0; // 最å°ç”µæµä¸º0μA +int32_t minUa = 0; // 最å°ç”µæµä¸º0μA int32_t maxUa = 200; // 最大电æµä¸º200μA /* 设置Regulator输出电æµèŒƒå›´ */ @@ -313,9 +306,7 @@ if (ret != 0) { #### 获å–Regulatorç”µæµ -获å–Regulator电æµã€‚ - -``` +```c int32_t RegulatorGetCurrent(DevHandle handle, uint32_t *regCurrent); ``` @@ -329,7 +320,7 @@ int32_t RegulatorGetCurrent(DevHandle handle, uint32_t *regCurrent); | 0 | 获å–æˆåŠŸ | | è´Ÿæ•° | 获å–失败 | -``` +```c int32_t ret; uint32_t regCurrent; @@ -342,9 +333,7 @@ if (ret != 0) { #### 获å–RegulatorçŠ¶æ€ -获å–Regulator状æ€ã€‚ - -``` +```c int32_t RegulatorGetStatus(DevHandle handle, uint32_t *status); ``` @@ -358,7 +347,7 @@ int32_t RegulatorGetStatus(DevHandle handle, uint32_t *status); | 0 | 获å–æˆåŠŸ | | è´Ÿæ•° | 获å–失败 | -``` +```c int32_t ret; uint32_t status; @@ -373,9 +362,11 @@ if (ret != 0) { ## 使用实例 +本例拟对Hi3516DV300å¼€å‘æ¿ä¸ŠRegulator设备进行简å•çš„读å–æ“作。 + Regulator设备完整的使用示例如下所示,首先获å–Regulator设备å¥æŸ„,然åŽä½¿èƒ½ï¼Œè®¾ç½®ç”µåŽ‹ï¼ŒèŽ·å–电压ã€çŠ¶æ€ï¼Œç¦ç”¨ï¼Œæœ€åŽé”€æ¯Regulator设备å¥æŸ„。 -``` +```c void RegulatorTestSample(void) { int32_t ret; diff --git a/zh-cn/device-dev/driver/driver-platform-regulator-develop.md b/zh-cn/device-dev/driver/driver-platform-regulator-develop.md index b72c9c13199b7ac7b9a5067936366316c0e0785d..4db05339c9ca1561690cca164f41cb788c862e7c 100755 --- a/zh-cn/device-dev/driver/driver-platform-regulator-develop.md +++ b/zh-cn/device-dev/driver/driver-platform-regulator-develop.md @@ -5,42 +5,41 @@ ### 功能简介 -Regulator模å—用于控制系统ä¸æŸäº›è®¾å¤‡çš„电压/电æµä¾›åº”。在嵌入å¼ç³»ç»Ÿï¼ˆå°¤å…¶æ˜¯æ‰‹æœºï¼‰ä¸ï¼ŒæŽ§åˆ¶è€—电é‡å¾ˆé‡è¦ï¼Œç›´æŽ¥å½±å“åˆ°ç”µæ± çš„ç»èˆªæ—¶é—´ã€‚所以,如果系统ä¸æŸä¸€ä¸ªæ¨¡å—æš‚æ—¶ä¸éœ€è¦ä½¿ç”¨ï¼Œå°±å¯ä»¥é€šè¿‡Regulatorå…³é—其电æºä¾›åº”;或者é™ä½Žæ供给该模å—的电压ã€ç”µæµå¤§å°ã€‚ +Regulator模å—用于控制系统ä¸å„类设备的电压/电æµä¾›åº”。在嵌入å¼ç³»ç»Ÿï¼ˆå°¤å…¶æ˜¯æ‰‹æœºï¼‰ä¸ï¼ŒæŽ§åˆ¶è€—电é‡å¾ˆé‡è¦ï¼Œç›´æŽ¥å½±å“åˆ°ç”µæ± çš„ç»èˆªæ—¶é—´ã€‚所以,如果系统ä¸æŸä¸€ä¸ªæ¨¡å—æš‚æ—¶ä¸éœ€è¦ä½¿ç”¨ï¼Œå°±å¯ä»¥é€šè¿‡Regulatorå…³é—其电æºä¾›åº”;或者é™ä½Žæ供给该模å—的电压ã€ç”µæµå¤§å°ã€‚ ### è¿ä½œæœºåˆ¶ -在HDF框架ä¸ï¼ŒRegulator模å—接å£é€‚é…模å¼é‡‡ç”¨ç»Ÿä¸€æœåŠ¡æ¨¡å¼ï¼Œè¿™éœ€è¦ä¸€ä¸ªè®¾å¤‡æœåŠ¡æ¥ä½œä¸ºRegulator模å—的管ç†å™¨ï¼Œç»Ÿä¸€å¤„ç†å¤–部访问,这会在é…置文件ä¸æœ‰æ‰€ä½“现。统一æœåŠ¡æ¨¡å¼é€‚åˆäºŽåŒç±»åž‹è®¾å¤‡å¯¹è±¡è¾ƒå¤šçš„情况,如Regulatorå¯èƒ½åŒæ—¶å…·å¤‡åå‡ ä¸ªæŽ§åˆ¶å™¨ï¼Œé‡‡ç”¨ç‹¬ç«‹æœåŠ¡æ¨¡å¼éœ€è¦é…置更多的设备节点,且æœåŠ¡ä¼šå æ®å†…å˜èµ„æºã€‚ +在HDF框架ä¸ï¼ŒRegulator模å—接å£é€‚é…模å¼é‡‡ç”¨ç»Ÿä¸€æœåŠ¡æ¨¡å¼ï¼ˆå¦‚图1),这需è¦ä¸€ä¸ªè®¾å¤‡æœåŠ¡æ¥ä½œä¸ºRegulator模å—的管ç†å™¨ï¼Œç»Ÿä¸€å¤„ç†å¤–部访问,这会在é…置文件ä¸æœ‰æ‰€ä½“现。统一æœåŠ¡æ¨¡å¼é€‚åˆäºŽåŒç±»åž‹è®¾å¤‡å¯¹è±¡è¾ƒå¤šçš„情况,如Regulatorå¯èƒ½åŒæ—¶å…·å¤‡åå‡ ä¸ªæŽ§åˆ¶å™¨ï¼Œé‡‡ç”¨ç‹¬ç«‹æœåŠ¡æ¨¡å¼éœ€è¦é…置更多的设备节点,且æœåŠ¡ä¼šå æ®å†…å˜èµ„æºã€‚ Regulator模å—å„分层的作用为: -- 接å£å±‚æ供打开设备,写入数æ®ï¼Œå…³é—设备接å£çš„能力。 -- æ ¸å¿ƒå±‚ä¸»è¦æ供绑定设备ã€åˆå§‹åŒ–设备以åŠé‡Šæ”¾è®¾å¤‡çš„能力。 -- 适é…层实现其他具体的功能。 - 说明:<br>æ ¸å¿ƒå±‚å¯ä»¥è°ƒç”¨æŽ¥å£å±‚的函数,也å¯ä»¥é€šè¿‡é’©å函数调用适é…层函数,从而使得适é…层间接的å¯ä»¥è°ƒç”¨æŽ¥å£å±‚函数,但是ä¸å¯é€†è½¬æŽ¥å£å±‚调用适é…层函数。 +- 接å£å±‚:æ供打开设备,æ“作Regulator,关é—设备的能力。 +- æ ¸å¿ƒå±‚ï¼šä¸»è¦è´Ÿè´£æœåŠ¡ç»‘定ã€åˆå§‹åŒ–以åŠé‡Šæ”¾ç®¡ç†å™¨ï¼Œå¹¶æä¾›æ·»åŠ ã€åˆ 除以åŠèŽ·å–Regulator设备的能力。 +- 适é…层:由驱动适é…者实现与硬件相关的具体功能,如设备的åˆå§‹åŒ–ç‰ã€‚ -**图 1** 统一æœåŠ¡æ¨¡å¼ç»“构图 - - +在统一模å¼ä¸‹ï¼Œæ‰€æœ‰çš„æŽ§åˆ¶å™¨éƒ½è¢«æ ¸å¿ƒå±‚ç»Ÿä¸€ç®¡ç†ï¼Œå¹¶ç”±æ ¸å¿ƒå±‚统一å‘布一个æœåŠ¡ä¾›æŽ¥å£å±‚ï¼Œå› æ¤è¿™ç§æ¨¡å¼ä¸‹é©±åŠ¨æ— 需å†ä¸ºæ¯ä¸ªæŽ§åˆ¶å™¨å‘布æœåŠ¡ã€‚ +**图 1** 统一æœåŠ¡æ¨¡å¼ç»“构图<a name="fig1"></a> + ### 约æŸä¸Žé™åˆ¶ -Regulator模å—当å‰ä»…支æŒè½»é‡å’Œå°åž‹ç³»ç»Ÿå†…æ ¸ï¼ˆLiteOS)。 +Regulator模å—当å‰ä»…支æŒå°åž‹ç³»ç»Ÿã€‚ ## å¼€å‘指导 ### åœºæ™¯ä»‹ç» -Regulator模å—用于控制系统ä¸æŸäº›è®¾å¤‡çš„电压/电æµä¾›åº”。 +Regulator模å—用于控制系统ä¸æŸäº›è®¾å¤‡çš„电压/电æµä¾›åº”。当驱动开å‘者需è¦å°†Regulator设备适é…到OpenHarmony时,需è¦è¿›è¡ŒRegulator驱动适é…,下文将介ç»å¦‚何进行Regulator驱动适é…。 ### 接å£è¯´æ˜Ž -通过以下RegulatorMethodä¸çš„函数调用Regulator驱动对应的函数。 +为了ä¿è¯ä¸Šå±‚在调用Regulator接å£æ—¶èƒ½å¤Ÿæ£ç¡®çš„æ“ä½œç¡¬ä»¶ï¼Œæ ¸å¿ƒå±‚åœ¨//drivers/hdf_core/framework/support/platform/include/regulator/regulator_core.hä¸å®šä¹‰äº†ä»¥ä¸‹é’©å函数。驱动适é…者需è¦åœ¨é€‚é…层实现这些函数的具体功能,并与这些钩å函数挂接,从而完æˆæŽ¥å£å±‚ä¸Žæ ¸å¿ƒå±‚çš„äº¤äº’ã€‚ RegulatorMethod定义: -``` +```c struct RegulatorMethod { int32_t (*open)(struct RegulatorNode *node); int32_t (*close)(struct RegulatorNode *node); @@ -56,8 +55,7 @@ struct RegulatorMethod { }; ``` -**表 1** RegulatorMethod 结构体æˆå‘˜çš„回调函数功能说明 - +**表 1** RegulatorMethod 结构体æˆå‘˜çš„é’©å函数功能说明 | æˆå‘˜å‡½æ•° | å…¥å‚ | 返回值 | 功能 | | ------------ | ----------------------------------------------------------- | ----------------- | ---------------- | @@ -87,23 +85,23 @@ Regulator模å—适é…包å«ä»¥ä¸‹å››ä¸ªæ¥éª¤ï¼š 驱动开å‘首先需è¦å®žä¾‹åŒ–驱动入å£ï¼Œé©±åŠ¨å…¥å£å¿…须为HdfDriverEntry(在hdf_device_desc.hä¸å®šä¹‰ï¼‰ç±»åž‹çš„全局å˜é‡ï¼Œä¸”moduleNameè¦å’Œdevice_info.hcsä¸ä¿æŒä¸€è‡´ã€‚ HDFæ¡†æž¶ä¼šæ±‡æ€»æ‰€æœ‰åŠ è½½çš„é©±åŠ¨çš„HdfDriverEntry对象入å£ï¼Œå½¢æˆä¸€ä¸ªç±»ä¼¼æ•°ç»„的段地å€ç©ºé—´ï¼Œæ–¹ä¾¿ä¸Šå±‚调用。 - + ä¸€èˆ¬åœ¨åŠ è½½é©±åŠ¨æ—¶HDF会先调用Initå‡½æ•°åŠ è½½è¯¥é©±åŠ¨ã€‚å½“Init调用异常时,HDF框架会调用Release释放驱动资æºå¹¶é€€å‡ºã€‚ - - ``` + + ```c struct HdfDriverEntry g_regulatorDriverEntry = { .moduleVersion = 1, - .moduleName = "virtual_regulator_driver",// ã€å¿…è¦ä¸”与HCS文件ä¸é‡Œé¢çš„moduleName匹é…】 + .moduleName = "virtual_regulator_driver", // ã€å¿…è¦ä¸”与HCS文件ä¸é‡Œé¢çš„moduleName匹é…】 .Init = VirtualRegulatorInit, .Release = VirtualRegulatorRelease, }; - // 调用HDF_INIT将驱动入å£æ³¨å†Œåˆ°HDFæ¡†æž¶ä¸ + /* 调用HDF_INIT将驱动入å£æ³¨å†Œåˆ°HDFæ¡†æž¶ä¸ */ HDF_INIT(g_regulatorDriverEntry); ``` - + 2. é…置属性文件: - - 在vendor/hisilicon/hispark_taurus/hdf_config/device_info/device_info.hcs文件ä¸æ·»åŠ deviceNodeæ述。 + 以Hi3516DV300å¼€å‘æ¿ä¸ºä¾‹ï¼Œåœ¨//vendor/hisilicon/hispark_taurus/hdf_config/device_info/device_info.hcs文件ä¸æ·»åŠ deviceNodeæ述。 deviceNodeä¿¡æ¯ä¸Žé©±åŠ¨å…¥å£æ³¨å†Œç›¸å…³ï¼Œå™¨ä»¶å±žæ€§å€¼ä¸Žæ ¸å¿ƒå±‚RegulatorNodeæˆå‘˜çš„默认值或é™åˆ¶èŒƒå›´æœ‰å¯†åˆ‡å…³ç³»ã€‚ @@ -118,43 +116,43 @@ Regulator模å—适é…包å«ä»¥ä¸‹å››ä¸ªæ¥éª¤ï¼š | serviceName | 固定为HDF_PLATFORM_REGULATOR_MANAGER | | deviceMatchAttr | 没有使用,å¯å¿½ç•¥ | - 从第二个节点开始é…置具体Regulator控制器信æ¯ï¼Œæ¤èŠ‚点并ä¸è¡¨ç¤ºæŸä¸€è·¯Regulator控制器,而是代表一个资æºæ€§è´¨è®¾å¤‡ï¼Œç”¨äºŽæ述一类Regulator控制器的信æ¯ã€‚本例åªæœ‰ä¸€ä¸ªRegulator设备,如有多个设备,则需è¦åœ¨device_infoæ–‡ä»¶å¢žåŠ deviceNodeä¿¡æ¯ï¼Œä»¥åŠåœ¨regulator\_config文件ä¸å¢žåŠ 对应的器件属性。 + 从第二个节点开始é…置具体Regulator控制器信æ¯ï¼Œæ¤èŠ‚点并ä¸è¡¨ç¤ºæŸä¸€è·¯Regulator控制器,而是代表一个资æºæ€§è´¨è®¾å¤‡ï¼Œç”¨äºŽæ述一类Regulator控制器的信æ¯ã€‚本例åªæœ‰ä¸€ä¸ªRegulator设备,如有多个设备,则需è¦åœ¨device_info.hcsæ–‡ä»¶å¢žåŠ deviceNodeä¿¡æ¯ï¼Œä»¥åŠåœ¨regulator\_config文件ä¸å¢žåŠ 对应的器件属性。 - device_info.hcs é…ç½®å‚考 - ``` + ```c root { - device_info { - platform :: host { - hostName = "platform_host"; - priority = 50; - device_regulator :: device { - device0 :: deviceNode { // 为æ¯ä¸€ä¸ªRegulator控制器é…置一个HDF设备节点,å˜åœ¨å¤šä¸ªæ—¶æ·»åŠ ,å¦åˆ™ä¸ç”¨ã€‚ - policy = 1; // 2:用户æ€å¯è§ï¼›1ï¼šå†…æ ¸æ€å¯è§ï¼›0:ä¸éœ€è¦å‘布æœåŠ¡ã€‚ - priority = 50; // 驱动å¯åŠ¨ä¼˜å…ˆçº§ - permission = 0644; // 驱动创建设备节点æƒé™ - /* ã€å¿…è¦ã€‘用于指定驱动å称,需è¦ä¸ŽæœŸæœ›çš„驱动Entryä¸çš„moduleName一致。 */ - moduleName = "HDF_PLATFORM_REGULATOR_MANAGER"; - serviceName = "HDF_PLATFORM_REGULATOR_MANAGER"; //ã€å¿…è¦ä¸”唯一】驱动对外å‘布æœåŠ¡çš„å称 - /* ã€å¿…è¦ã€‘用于é…置控制器ç§æœ‰æ•°æ®ï¼Œè¦ä¸Žregulator_config.hcsä¸å¯¹åº”控制器ä¿æŒä¸€è‡´ï¼Œå…·ä½“的控制器信æ¯åœ¨regulator_config.hcsä¸ã€‚ */ - deviceMatchAttr = "hdf_platform_regulator_manager"; - } - device1 :: deviceNode { - policy = 0; - priority = 55; - permission = 0644; - moduleName = "linux_regulator_adapter"; - deviceMatchAttr = "linux_regulator_adapter"; + device_info { + platform :: host { + hostName = "platform_host"; + priority = 50; + device_regulator :: device { + device0 :: deviceNode { // 为æ¯ä¸€ä¸ªRegulator控制器é…置一个HDF设备节点,å˜åœ¨å¤šä¸ªæ—¶æ·»åŠ ,å¦åˆ™ä¸ç”¨ã€‚ + policy = 1; // 2:用户æ€ã€å†…æ ¸æ€å‡å¯è§ï¼›1ï¼šå†…æ ¸æ€å¯è§ï¼›0:ä¸éœ€è¦å‘布æœåŠ¡ã€‚ + priority = 50; // 驱动å¯åŠ¨ä¼˜å…ˆçº§ + permission = 0644; // 驱动创建设备节点æƒé™ + /* ã€å¿…è¦ã€‘用于指定驱动å称,需è¦ä¸ŽæœŸæœ›çš„驱动Entryä¸çš„moduleName一致。 */ + moduleName = "HDF_PLATFORM_REGULATOR_MANAGER"; + serviceName = "HDF_PLATFORM_REGULATOR_MANAGER"; // ã€å¿…è¦ä¸”唯一】驱动对外å‘布æœåŠ¡çš„å称 + /* ã€å¿…è¦ã€‘用于é…置控制器ç§æœ‰æ•°æ®ï¼Œè¦ä¸Žregulator_config.hcsä¸å¯¹åº”控制器ä¿æŒä¸€è‡´ï¼Œå…·ä½“的控制器信æ¯åœ¨regulator_config.hcsä¸ã€‚ */ + deviceMatchAttr = "hdf_platform_regulator_manager"; + } + device1 :: deviceNode { + policy = 0; + priority = 55; + permission = 0644; + moduleName = "linux_regulator_adapter"; + deviceMatchAttr = "linux_regulator_adapter"; + } + } } } - } - } } ``` - regulator\_config.hcsé…ç½®å‚考 - ``` + ```c root { platform { regulator_config { @@ -198,16 +196,24 @@ Regulator模å—适é…包å«ä»¥ä¸‹å››ä¸ªæ¥éª¤ï¼š } ``` + 需è¦æ³¨æ„的是,新增regulator_config.hcsé…置文件åŽï¼Œå¿…须在hdf.hcs文件ä¸å°†å…¶åŒ…å«ï¼Œå¦åˆ™é…ç½®æ–‡ä»¶æ— æ³•ç”Ÿæ•ˆã€‚ + + 例如:本例ä¸regulator_config.hcs所在路径为device/soc/hisilicon/hi3516dv300/sdk_liteos/hdf_config/regulator/regulator_config.hcs,则必须在产å“对应的hdf.hcsä¸æ·»åŠ 如下è¯å¥ï¼š + + ```c + #include "../../../../device/soc/hisilicon/hi3516dv300/sdk_liteos/hdf_config/regulator/regulator_config.hcs" // é…置文件相对路径 + ``` + 3. å®žä¾‹åŒ–æ ¸å¿ƒå±‚æŽ¥å£å‡½æ•°ï¼š - - 完æˆé©±åŠ¨å…¥å£æ³¨å†Œä¹‹åŽï¼Œä¸‹ä¸€æ¥å°±æ˜¯å¯¹æ ¸å¿ƒå±‚RegulatorNode对象的åˆå§‹åŒ–ï¼ŒåŒ…æ‹¬åŽ‚å•†è‡ªå®šä¹‰ç»“æž„ä½“ï¼ˆä¼ é€’å‚数和数æ®ï¼‰ï¼Œå®žä¾‹åŒ–RegulatorNodeæˆå‘˜RegulatorMethod(让用户å¯ä»¥é€šè¿‡æŽ¥å£æ¥è°ƒç”¨é©±åŠ¨åº•å±‚函数),实现HdfDriverEntryæˆå‘˜å‡½æ•°ï¼ˆBindã€Initã€Release)。 + 完æˆé©±åŠ¨å…¥å£æ³¨å†Œä¹‹åŽï¼Œä¸‹ä¸€æ¥å°±æ˜¯å¯¹æ ¸å¿ƒå±‚RegulatorNode对象的åˆå§‹åŒ–,包括驱动适é…è€…è‡ªå®šä¹‰ç»“æž„ä½“ï¼ˆä¼ é€’å‚数和数æ®ï¼‰ï¼Œå®žä¾‹åŒ–RegulatorNodeæˆå‘˜RegulatorMethod(让用户å¯ä»¥é€šè¿‡æŽ¥å£æ¥è°ƒç”¨é©±åŠ¨åº•å±‚函数),实现HdfDriverEntryæˆå‘˜å‡½æ•°ï¼ˆBindã€Initã€Release)。 - 自定义结构体å‚考。 从驱动的角度看,RegulatorNode结构体是å‚数和数æ®çš„载体,HDF框架通过DeviceResourceIfaceå°†regulator\_config.hcs文件ä¸çš„数值读入其ä¸ã€‚ - ``` - // RegulatorNodeæ˜¯æ ¸å¿ƒå±‚æŽ§åˆ¶å™¨ç»“æž„ä½“ï¼Œå…¶ä¸çš„æˆå‘˜åœ¨Init函数ä¸ä¼šè¢«èµ‹å€¼ã€‚ + ```c + /* RegulatorNodeæ˜¯æ ¸å¿ƒå±‚æŽ§åˆ¶å™¨ç»“æž„ä½“ï¼Œå…¶ä¸çš„æˆå‘˜åœ¨Init函数ä¸ä¼šè¢«èµ‹å€¼ã€‚ */ struct RegulatorNode { struct RegulatorDesc regulatorInfo; struct DListHead node; @@ -217,35 +223,33 @@ Regulator模å—适é…包å«ä»¥ä¸‹å››ä¸ªæ¥éª¤ï¼š }; struct RegulatorDesc { - const char *name; /* regulatorå称 */ - const char *parentName; /* regulator父节点å称 */ - struct RegulatorConstraints constraints; /* regulator约æŸä¿¡æ¯ */ - uint32_t minUv; /* 最å°è¾“出电压值 */ - uint32_t maxUv; /* 最大输出电压值 */ - uint32_t minUa; /* 最å°è¾“出电æµå€¼ */ - uint32_t maxUa; /* 最大输出电æµå€¼ */ - uint32_t status; /* regulator的状æ€ï¼Œå¼€æˆ–关。*/ + const char *name; // regulatorå称 + const char *parentName; // regulator父节点å称 + struct RegulatorConstraints constraints; // regulator约æŸä¿¡æ¯ + uint32_t minUv; // 最å°è¾“出电压值 + uint32_t maxUv; // 最大输出电压值 + uint32_t minUa; // 最å°è¾“出电æµå€¼ + uint32_t maxUa; // 最大输出电æµå€¼ + uint32_t status; // regulator的状æ€ï¼Œå¼€æˆ–关。 int useCount; - int consumerRegNums; /* regulatorç”¨æˆ·æ•°é‡ */ - RegulatorStatusChangecb cb; /* 当regulator状æ€æ”¹å˜æ—¶ï¼Œå¯é€šè¿‡æ¤å˜é‡é€šçŸ¥ã€‚*/ + int consumerRegNums; // regulatorç”¨æˆ·æ•°é‡ + RegulatorStatusChangecb cb; // 当regulator状æ€æ”¹å˜æ—¶ï¼Œå¯é€šè¿‡æ¤å˜é‡é€šçŸ¥ã€‚ }; struct RegulatorConstraints { - uint8_t alwaysOn; /* regulator是å¦å¸¸å¼€ */ - uint8_t mode; /* 模å¼ï¼šç”µåŽ‹æˆ–è€…ç”µæµ */ - uint32_t minUv; /* 最å°å¯è®¾ç½®è¾“出电压 */ - uint32_t maxUv; /* 最大å¯è®¾ç½®è¾“出电压 */ - uint32_t minUa; /* 最å°å¯è®¾ç½®è¾“å‡ºç”µæµ */ - uint32_t maxUa; /* 最大å¯è®¾ç½®è¾“å‡ºç”µæµ */ + uint8_t alwaysOn; // regulator是å¦å¸¸å¼€ + uint8_t mode; // 模å¼ï¼šç”µåŽ‹æˆ–è€…ç”µæµ + uint32_t minUv; // 最å°å¯è®¾ç½®è¾“出电压 + uint32_t maxUv; // 最大å¯è®¾ç½®è¾“出电压 + uint32_t minUa; // 最å°å¯è®¾ç½®è¾“å‡ºç”µæµ + uint32_t maxUa; // 最大å¯è®¾ç½®è¾“å‡ºç”µæµ }; ``` - - - + - 实例化RegulatorNodeæˆå‘˜RegulatorMethod,其他æˆå‘˜åœ¨Init函数ä¸åˆå§‹åŒ–。 ```c - // regulator_virtual.cä¸çš„示例:钩å函数的填充 + /* regulator_virtual.cä¸çš„示例:钩å函数的填充 */ static struct RegulatorMethod g_method = { .enable = VirtualRegulatorEnable, .disable = VirtualRegulatorDisable, @@ -256,18 +260,16 @@ Regulator模å—适é…包å«ä»¥ä¸‹å››ä¸ªæ¥éª¤ï¼š .getStatus = VirtualRegulatorGetStatus, }; ``` - - - - - Init函数å‚考 + + - Init函数开å‘å‚考 å…¥å‚: - HdfDeviceObject是整个驱动对外暴露的接å£å‚数,具备HCSé…置文件的信æ¯ã€‚ + HdfDeviceObject是整个驱动对外æ供的接å£å‚数,具备HCSé…置文件的信æ¯ã€‚ 返回值: - HDF\_STATUS相关状æ€ï¼ˆä¸‹è¡¨ä¸ºéƒ¨åˆ†å±•ç¤ºï¼Œå¦‚需使用其他状æ€ï¼Œå¯è§//drivers/framework/include/utils/hdf\_base.hä¸HDF\_STATUS定义)。 + HDF\_STATUS相关状æ€ï¼ˆä¸‹è¡¨ä¸ºéƒ¨åˆ†å±•ç¤ºï¼Œå¦‚需使用其他状æ€ï¼Œå¯è§//drivers/hdf\_core/framework/include/utils/hdf\_base.hä¸HDF\_STATUS定义)。 **表 2** HDF\_STATUSç›¸å…³çŠ¶æ€ @@ -283,44 +285,43 @@ Regulator模å—适é…包å«ä»¥ä¸‹å››ä¸ªæ¥éª¤ï¼š 函数说明: åˆå§‹åŒ–自定义结构体和RegulatorNodeæˆå‘˜ï¼Œå¹¶é€šè¿‡è°ƒç”¨æ ¸å¿ƒå±‚RegulatorNodeAdd函数挂载Regulator控制器。 - - ```c - static int32_t VirtualRegulatorInit(struct HdfDeviceObject *device) - { - int32_t ret; - const struct DeviceResourceNode *childNode = NULL; - ... - DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) { - ret = VirtualRegulatorParseAndInit(device, childNode);// ã€å¿…è¦ã€‘实现è§ä¸‹ - ... - } - ... - } - - static int32_t VirtualRegulatorParseAndInit(struct HdfDeviceObject *device, const struct DeviceResourceNode *node) - { - int32_t ret; - struct RegulatorNode *regNode = NULL; - (void)device; - - regNode = (struct RegulatorNode *)OsalMemCalloc(sizeof(*regNode));//åŠ è½½HCS文件 - ... - ret = VirtualRegulatorReadHcs(regNode, node); // 读å–HCSæ–‡ä»¶ä¿¡æ¯ - ... - regNode->priv = (void *)node; // 实例化节点 - regNode->ops = &g_method; // 实例化ops - - ret = RegulatorNodeAdd(regNode); // 挂载节点 - ... - } - ``` - - - Release 函数å‚考 + ```c + static int32_t VirtualRegulatorInit(struct HdfDeviceObject *device) + { + int32_t ret; + const struct DeviceResourceNode *childNode = NULL; + ... + DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) { + ret = VirtualRegulatorParseAndInit(device, childNode); // ã€å¿…è¦ã€‘实现è§ä¸‹ + ... + } + ... + } + + static int32_t VirtualRegulatorParseAndInit(struct HdfDeviceObject *device, const struct DeviceResourceNode *node) + { + int32_t ret; + struct RegulatorNode *regNode = NULL; + (void)device; + + regNode = (struct RegulatorNode *)OsalMemCalloc(sizeof(*regNode)); //åŠ è½½HCS文件 + ... + ret = VirtualRegulatorReadHcs(regNode, node); // 读å–HCSæ–‡ä»¶ä¿¡æ¯ + ... + regNode->priv = (void *)node; // 实例化节点 + regNode->ops = &g_method; // 实例化ops + + ret = RegulatorNodeAdd(regNode); // 挂载节点 + ... + } + ``` + + - Release函数开å‘å‚考 å…¥å‚: - HdfDeviceObject是整个驱动对外暴露的接å£å‚数,其包å«äº†HCSé…置文件ä¸çš„相关é…置信æ¯ã€‚ + HdfDeviceObject是整个驱动对外æ供的接å£å‚数,其包å«äº†HCSé…置文件ä¸çš„相关é…置信æ¯ã€‚ 返回值: @@ -334,12 +335,10 @@ Regulator模å—适é…包å«ä»¥ä¸‹å››ä¸ªæ¥éª¤ï¼š static void VirtualRegulatorRelease(struct HdfDeviceObject *device) { ... - RegulatorNodeRemoveAll();// ã€å¿…è¦ã€‘è°ƒç”¨æ ¸å¿ƒå±‚å‡½æ•°ï¼Œé‡Šæ”¾RegulatorNode的设备和æœåŠ¡ + RegulatorNodeRemoveAll(); // ã€å¿…è¦ã€‘è°ƒç”¨æ ¸å¿ƒå±‚å‡½æ•°ï¼Œé‡Šæ”¾RegulatorNode的设备和æœåŠ¡ } ``` - + 4. 驱动调试: ã€å¯é€‰ã€‘针对新增驱动程åºï¼Œå»ºè®®éªŒè¯é©±åŠ¨åŸºæœ¬åŠŸèƒ½ï¼Œä¾‹å¦‚挂载åŽçš„测试用例是å¦æˆåŠŸç‰ã€‚ - - diff --git a/zh-cn/device-dev/driver/driver-platform-rtc-des.md b/zh-cn/device-dev/driver/driver-platform-rtc-des.md index d1be53836624a326e3b79d65c4cb859a349607a9..de7a4a2ce02486f883ca3074cfcfc7738fe286f2 100644 --- a/zh-cn/device-dev/driver/driver-platform-rtc-des.md +++ b/zh-cn/device-dev/driver/driver-platform-rtc-des.md @@ -1,49 +1,61 @@ # RTC - ## 概述 +### 功能简介 + RTC(real-time clock)为æ“作系统ä¸çš„实时时钟设备,为æ“作系统æ供精准的实时时间和定时报è¦åŠŸèƒ½ã€‚当设备下电åŽï¼Œé€šè¿‡å¤–ç½®ç”µæ± ä¾›ç”µï¼ŒRTC继ç»è®°å½•æ“作系统时间;设备上电åŽï¼ŒRTCæ供实时时钟给æ“作系统,确ä¿æ–电åŽç³»ç»Ÿæ—¶é—´çš„è¿žç»æ€§ã€‚ +### è¿ä½œæœºåˆ¶ -## 接å£è¯´æ˜Ž +在HDF框架ä¸ï¼ŒRTC模å—采用独立æœåŠ¡æ¨¡å¼ï¼Œåœ¨è¿™ç§æ¨¡å¼ä¸‹ï¼Œæ¯ä¸€ä¸ªè®¾å¤‡å¯¹è±¡ä¼šç‹¬ç«‹å‘布一个设备æœåŠ¡æ¥å¤„ç†å¤–部访问,设备管ç†å™¨æ”¶åˆ°API的访问请求之åŽï¼Œé€šè¿‡æå–该请求的å‚数,达到调用实际设备对象的相应内部方法的目的。独立æœåŠ¡æ¨¡å¼å¯ä»¥ç›´æŽ¥å€ŸåŠ©HDFDeviceManagerçš„æœåŠ¡ç®¡ç†èƒ½åŠ›ï¼Œä½†éœ€è¦ä¸ºæ¯ä¸ªè®¾å¤‡å•ç‹¬é…ç½®è®¾å¤‡èŠ‚ç‚¹ï¼Œè‹¥è®¾å¤‡è¿‡å¤šä¼šå¢žåŠ å†…å˜å 用。通常,一个硬件系统ä¸åªéœ€è¦ä¸€ä¸ªRTCè®¾å¤‡ï¼Œå› æ¤RTC模å—采用独立æœåŠ¡æ¨¡å¼è¾ƒä¸ºåˆé€‚。 - **表1** RTC设备API接å£åŠŸèƒ½ä»‹ç» +## 使用指导 -| 功能分类 | 接å£æè¿° | -| -------- | -------- | -| RTCå¥æŸ„æ“作 | RtcOpen:获å–RTC设备驱动å¥æŸ„<br/>RtcClose:释放RTC设备驱动å¥æŸ„ | -| RTC时间æ“ä½œæŽ¥å£ | RtcReadTime:读RTC时间信æ¯ï¼ŒåŒ…括年ã€æœˆã€æ˜ŸæœŸã€æ—¥ã€æ—¶ã€åˆ†ã€ç§’ã€æ¯«ç§’<br/>RtcWriteTime:写RTC时间信æ¯ï¼ŒåŒ…括年ã€æœˆã€æ˜ŸæœŸã€æ—¥ã€æ—¶ã€åˆ†ã€ç§’ã€æ¯«ç§’ | -| RTC报è¦æ“ä½œæŽ¥å£ | RtcReadAlarm:读RTC报è¦æ—¶é—´ä¿¡æ¯<br/>RtcWriteAlarm:写RTC报è¦æ—¶é—´ä¿¡æ¯<br/>RtcRegisterAlarmCallback:注册报è¦è¶…时回调函数<br/>RtcAlarmInterruptEnable:使能/去使能RTC报è¦ä¸æ– | -| RTCé…ç½®æ“作 | RtcGetFreq:读RTC外接晶振频率<br/>RtcSetFreq:é…ç½®RTC外接晶振频率<br/>RtcReset:RTCå¤ä½ | -| 读写用户定义寄å˜å™¨ | RtcReadReg:读用户自定义寄å˜å™¨<br/>RtcWriteReg:写用户自定义寄å˜å™¨ | +### åœºæ™¯ä»‹ç» ->  **说明:**<br> -> 本文涉åŠçš„所有接å£ï¼Œä»…é™å†…æ ¸æ€ä½¿ç”¨ï¼Œä¸æ”¯æŒåœ¨ç”¨æˆ·æ€ä½¿ç”¨ã€‚ +RTC主è¦ç”¨äºŽæ供实时时间和定时报è¦åŠŸèƒ½ã€‚ +### 接å£è¯´æ˜Ž -## 使用指导 +RTC模å—æ供的主è¦æŽ¥å£å¦‚表1所示,具体API详è§//drivers/hdf_core/framework/include/platform/rtc_if.h。 +**表1** RTC设备API接å£åŠŸèƒ½ä»‹ç» -### 使用æµç¨‹ +| 接å£å | 接å£æè¿° | +| -------- | -------- | +| DevHandle RtcOpen(void) | 获å–RTC设备驱动å¥æŸ„ | +| void RtcClose(DevHandle handle) | 释放RTC设备驱动å¥æŸ„ | +| int32_t RtcReadTime(DevHandle handle, struct RtcTime \*time) | 读RTCæ—¶é—´ä¿¡æ¯ | +| int32_t RtcWriteTime(DevHandle handle, const struct RtcTime \*time) | 写RTC时间信æ¯ï¼ŒåŒ…括年ã€æœˆã€æ˜ŸæœŸã€æ—¥ã€æ—¶ã€åˆ†ã€ç§’ã€æ¯«ç§’ | +| int32_t RtcReadAlarm(DevHandle handle, enum RtcAlarmIndex alarmIndex, struct RtcTime \*time) | 读RTC报è¦æ—¶é—´ä¿¡æ¯ | +| int32_t RtcWriteAlarm(DevHandle handle, enum RtcAlarmIndex alarmIndex, const struct RtcTime \*time) | 写RTC报è¦æ—¶é—´ä¿¡æ¯ | +| int32_t RtcRegisterAlarmCallback(DevHandle handle, enum RtcAlarmIndex alarmIndex, RtcAlarmCallback cb) | 注册报è¦è¶…时回调函数 | +| int32_t RtcAlarmInterruptEnable(DevHandle handle, enum RtcAlarmIndex alarmIndex, uint8_t enable) | 使能/去使能RTC报è¦ä¸æ– | +| int32_t RtcGetFreq(DevHandle handle, uint32_t \*freq) | 读RTC外接晶振频率 | +| int32_t RtcSetFreq(DevHandle handle, uint32_t freq) | é…ç½®RTC外接晶振频率 | +| int32_t RtcReset(DevHandle handle) | RTCå¤ä½ | +| int32_t RtcReadReg(DevHandle handle, uint8_t usrDefIndex, uint8_t \*value) | 读用户自定义寄å˜å™¨ | +| int32_t RtcWriteReg(DevHandle handle, uint8_t usrDefIndex, uint8_t value) | 写用户自定义寄å˜å™¨ | -在æ“作系统å¯åŠ¨è¿‡ç¨‹ä¸ï¼Œé©±åŠ¨ç®¡ç†æ¨¡å—æ ¹æ®é…ç½®æ–‡ä»¶åŠ è½½RTC驱动,RTC驱动会检测RTC器件并åˆå§‹åŒ–驱动。 +### 使用æµç¨‹ 使用RTC设备的一般æµç¨‹å¦‚下图所示。 - **图1** RTC设备使用æµç¨‹å›¾ - -  +**图1** RTC设备使用æµç¨‹å›¾ + -### 创建RTC设备å¥æŸ„ +#### 创建RTC设备å¥æŸ„ RTCé©±åŠ¨åŠ è½½æˆåŠŸåŽï¼Œä½¿ç”¨é©±åŠ¨æ¡†æž¶æ供的查询接å£å¹¶è°ƒç”¨RTC设备驱动接å£ã€‚ >  **说明:**<br> -> 当å‰æ“作系统支æŒä¸€ä¸ªRTC设备。 +> 当å‰æ“作系统仅支æŒä¸€ä¸ªRTC设备。 +```c DevHandle RtcOpen(void); +``` **表2** RtcOpenå‚数和返回值æè¿° @@ -55,7 +67,7 @@ DevHandle RtcOpen(void); | NULL | æ“作失败 | -``` +```c DevHandle handle = NULL; /* 获å–RTCå¥æŸ„ */ @@ -65,33 +77,15 @@ if (handle == NULL) { } ``` - -### 销æ¯RTC设备å¥æŸ„ - -销æ¯RTC设备å¥æŸ„,系统释放对应的资æºã€‚ - -void RtcClose(DevHandle handle); - - **表3** RtcCloseå‚æ•°æè¿° - -| **å‚æ•°** | **æè¿°** | -| -------- | -------- | -| handle | RTC设备å¥æŸ„ | - - -``` -/* 销æ¯RTCå¥æŸ„ */ -RtcClose(handle); -``` - - -### 注册RTC定时报è¦å›žè°ƒå‡½æ•° +#### 注册RTC定时报è¦å›žè°ƒå‡½æ•° 系统å¯åŠ¨åŽéœ€è¦æ³¨å†ŒRTC定时报è¦å›žè°ƒå‡½æ•°ï¼ŒæŠ¥è¦è¶…æ—¶åŽè§¦å‘回调函数。 +```c int32_t RtcRegisterAlarmCallback(DevHandle handle, enum RtcAlarmIndex alarmIndex, RtcAlarmCallback cb); +``` - **表4** RtcRegisterAlarmCallbackå‚数和返回值æè¿° + **表3** RtcRegisterAlarmCallbackå‚数和返回值æè¿° | **å‚æ•°** | **æè¿°** | | -------- | -------- | @@ -104,7 +98,7 @@ int32_t RtcRegisterAlarmCallback(DevHandle handle, enum RtcAlarmIndex alarmIndex 注册RTC_ALARM_INDEX_A的定时报è¦å¤„ç†å‡½æ•°ï¼Œ 示例如下: -``` +```c /* 用户注册RTC定时报è¦å›žè°ƒå‡½æ•°çš„方法 */ int32_t RtcAlarmACallback(enum RtcAlarmIndex alarmIndex) { @@ -126,318 +120,346 @@ if (ret != 0) { ``` -### æ“作RTC +#### æ“作RTC - 读å–RTC时间。 -系统从RTC读å–时间信æ¯ï¼ŒåŒ…括年ã€æœˆã€æ˜ŸæœŸã€æ—¥ã€æ—¶ã€åˆ†ã€ç§’ã€æ¯«ç§’,则å¯ä»¥é€šè¿‡ä»¥ä¸‹å‡½æ•°å®Œæˆï¼š + 系统从RTC读å–时间信æ¯ï¼ŒåŒ…括年ã€æœˆã€æ˜ŸæœŸã€æ—¥ã€æ—¶ã€åˆ†ã€ç§’ã€æ¯«ç§’,则å¯ä»¥é€šè¿‡ä»¥ä¸‹å‡½æ•°å®Œæˆï¼š -int32_t RtcReadTime(DevHandle handle, struct RtcTime \*time); + ```c + int32_t RtcReadTime(DevHandle handle, struct RtcTime \*time); + ``` - **表5** RtcReadTimeå‚数和返回值æè¿° + **表4** RtcReadTimeå‚数和返回值æè¿° -| **å‚æ•°** | **æè¿°** | -| -------- | -------- | -| handle | RTC设备å¥æŸ„ | -| time | RTC读å–时间信æ¯ï¼ŒåŒ…括年ã€æœˆã€æ˜ŸæœŸã€æ—¥ã€æ—¶ã€åˆ†ã€ç§’ã€æ¯«ç§’ | -| **返回值** | **æè¿°** | -| 0 | æ“作æˆåŠŸ | -| è´Ÿæ•° | æ“作失败 | - - -``` -int32_t ret; -struct RtcTime tm; + | **å‚æ•°** | **æè¿°** | + | -------- | -------- | + | handle | RTC设备å¥æŸ„ | + | time | RTC读å–时间信æ¯ï¼ŒåŒ…括年ã€æœˆã€æ˜ŸæœŸã€æ—¥ã€æ—¶ã€åˆ†ã€ç§’ã€æ¯«ç§’ | + | **返回值** | **æè¿°** | + | 0 | æ“作æˆåŠŸ | + | è´Ÿæ•° | æ“作失败 | -/* 系统从RTC读å–æ—¶é—´ä¿¡æ¯ */ -ret = RtcReadTime(handle, &tm); -if (ret != 0) { - /* é”™è¯¯å¤„ç† */ -} -``` + ```c + int32_t ret; + struct RtcTime tm; + + /* 系统从RTC读å–æ—¶é—´ä¿¡æ¯ */ + ret = RtcReadTime(handle, &tm); + if (ret != 0) { + /* é”™è¯¯å¤„ç† */ + } + ``` - 设置RTC时间 -设置RTC时间,则å¯ä»¥é€šè¿‡ä»¥ä¸‹å‡½æ•°å®Œæˆ: - -int32_t RtcWriteTime(DevHandle handle, struct RtcTime \*time); + 设置RTC时间,则å¯ä»¥é€šè¿‡ä»¥ä¸‹å‡½æ•°å®Œæˆ: - **表6** RtcWriteTimeå‚数和返回值æè¿° + ```c + int32_t RtcWriteTime(DevHandle handle, struct RtcTime \*time); + ``` -| **å‚æ•°** | **æè¿°** | -| -------- | -------- | -| handle | RTC设备å¥æŸ„ | -| time | 写RTC时间信æ¯ï¼ŒåŒ…括年ã€æœˆã€æ˜ŸæœŸã€æ—¥ã€æ—¶ã€åˆ†ã€ç§’ã€æ¯«ç§’ | -| **返回值** | **æè¿°** | -| 0 | æ“作æˆåŠŸ | -| è´Ÿæ•° | æ“作失败 | + **表5** RtcWriteTimeå‚数和返回值æè¿° ->  **说明:**<br> -> RTC起始时间为UTC 1970/01/01 Thursday 00:00:00,年的最大å–值按照用户器件手册è¦æ±‚计算é…置,星期ä¸ç”¨é…置。 + | **å‚æ•°** | **æè¿°** | + | -------- | -------- | + | handle | RTC设备å¥æŸ„ | + | time | 写RTC时间信æ¯ï¼ŒåŒ…括年ã€æœˆã€æ˜ŸæœŸã€æ—¥ã€æ—¶ã€åˆ†ã€ç§’ã€æ¯«ç§’ | + | **返回值** | **æè¿°** | + | 0 | æ“作æˆåŠŸ | + | è´Ÿæ•° | æ“作失败 | + >  **说明:**<br> + > RTC起始时间为UTC 1970/01/01 Thursday 00:00:00,年的最大å–值按照用户器件手册è¦æ±‚计算é…置,星期ä¸ç”¨é…置。 -``` -int32_t ret; -struct RtcTime tm; - -/* 设置RTC时间为 UTC 2020/01/01 00:59:00 .000 */ -tm.year = 2020; -tm.month = 01; -tm.day = 01; -tm.hour= 00; -tm.minute = 59; -tm.second = 00; -tm.millisecond = 0; -/* 写RTCæ—¶é—´ä¿¡æ¯ */ -ret = RtcWriteTime(handle, &tm); -if (ret != 0) { - /* é”™è¯¯å¤„ç† */ -} -``` + ```c + int32_t ret; + struct RtcTime tm; + + /* 设置RTC时间为 UTC 2020/01/01 00:59:00 .000 */ + tm.year = 2020; + tm.month = 01; + tm.day = 01; + tm.hour= 00; + tm.minute = 59; + tm.second = 00; + tm.millisecond = 0; + /* 写RTCæ—¶é—´ä¿¡æ¯ */ + ret = RtcWriteTime(handle, &tm); + if (ret != 0) { + /* é”™è¯¯å¤„ç† */ + } + ``` - 读å–RTC报è¦æ—¶é—´ -如果需è¦è¯»å–定时报è¦æ—¶é—´ï¼Œåˆ™å¯ä»¥é€šè¿‡ä»¥ä¸‹å‡½æ•°å®Œæˆï¼š + 如果需è¦è¯»å–定时报è¦æ—¶é—´ï¼Œåˆ™å¯ä»¥é€šè¿‡ä»¥ä¸‹å‡½æ•°å®Œæˆï¼š -int32_t RtcReadAlarm(DevHandle handle, enum RtcAlarmIndex alarmIndex, struct RtcTime \*time); + ```c + int32_t RtcReadAlarm(DevHandle handle, enum RtcAlarmIndex alarmIndex, struct RtcTime \*time); + ``` - **表7** RtcReadAlarmå‚数和返回值æè¿° + **表6** RtcReadAlarmå‚数和返回值æè¿° -| **å‚æ•°** | **æè¿°** | -| -------- | -------- | -| handle | RTC设备å¥æŸ„ | -| alarmIndex | 报è¦ç´¢å¼• | -| time | RTC报è¦æ—¶é—´ä¿¡æ¯ï¼ŒåŒ…括年ã€æœˆã€æ˜ŸæœŸã€æ—¥ã€æ—¶ã€åˆ†ã€ç§’ã€æ¯«ç§’ | -| **返回值** | **æè¿°** | -| 0 | æ“作æˆåŠŸ | -| è´Ÿæ•° | æ“作失败 | - - -``` -int32_t ret; -struct RtcTime alarmTime; + | **å‚æ•°** | **æè¿°** | + | -------- | -------- | + | handle | RTC设备å¥æŸ„ | + | alarmIndex | 报è¦ç´¢å¼• | + | time | RTC报è¦æ—¶é—´ä¿¡æ¯ï¼ŒåŒ…括年ã€æœˆã€æ˜ŸæœŸã€æ—¥ã€æ—¶ã€åˆ†ã€ç§’ã€æ¯«ç§’ | + | **返回值** | **æè¿°** | + | 0 | æ“作æˆåŠŸ | + | è´Ÿæ•° | æ“作失败 | -/* 读RTC_ALARM_INDEX_A索引的RTC定时报è¦æ—¶é—´ä¿¡æ¯ */ -ret = RtcReadAlarm(handle, RTC_ALARM_INDEX_A, &alarmTime); -if (ret != 0) { - /* é”™è¯¯å¤„ç† */ -} -``` + ```c + int32_t ret; + struct RtcTime alarmTime; + + /* 读RTC_ALARM_INDEX_A索引的RTC定时报è¦æ—¶é—´ä¿¡æ¯ */ + ret = RtcReadAlarm(handle, RTC_ALARM_INDEX_A, &alarmTime); + if (ret != 0) { + /* é”™è¯¯å¤„ç† */ + } + ``` - 设置RTC报è¦æ—¶é—´ -æ ¹æ®æŠ¥è¦ç´¢å¼•è®¾ç½®RTC报è¦æ—¶é—´ï¼Œé€šè¿‡ä»¥ä¸‹å‡½æ•°å®Œæˆï¼š - -int32_t RtcWriteAlarm(DevHandle handle, enum RtcAlarmIndex alarmIndex, struct RtcTime \*time); + æ ¹æ®æŠ¥è¦ç´¢å¼•è®¾ç½®RTC报è¦æ—¶é—´ï¼Œé€šè¿‡ä»¥ä¸‹å‡½æ•°å®Œæˆï¼š - **表8** RtcWriteAlarmå‚数和返回值æè¿° + ```c + int32_t RtcWriteAlarm(DevHandle handle, enum RtcAlarmIndex alarmIndex, struct RtcTime \*time); + ``` -| **å‚æ•°** | **æè¿°** | -| -------- | -------- | -| handle | RTC设备å¥æŸ„ | -| alarmIndex | 报è¦ç´¢å¼• | -| time | RTC报è¦æ—¶é—´ä¿¡æ¯ï¼ŒåŒ…括年ã€æœˆã€æ˜ŸæœŸã€æ—¥ã€æ—¶ã€åˆ†ã€ç§’ã€æ¯«ç§’ | -| **返回值** | **æè¿°** | -| 0 | æ“作æˆåŠŸ | -| è´Ÿæ•° | æ“作失败 | + **表7** RtcWriteAlarmå‚数和返回值æè¿° ->  **说明:**</br> -> RTC起始时间为UTC 1970/01/01 Thursday 00:00:00,年的最大å–值按照用户器件手册è¦æ±‚计算é…置,星期ä¸ç”¨é…置。 + | **å‚æ•°** | **æè¿°** | + | -------- | -------- | + | handle | RTC设备å¥æŸ„ | + | alarmIndex | 报è¦ç´¢å¼• | + | time | RTC报è¦æ—¶é—´ä¿¡æ¯ï¼ŒåŒ…括年ã€æœˆã€æ˜ŸæœŸã€æ—¥ã€æ—¶ã€åˆ†ã€ç§’ã€æ¯«ç§’ | + | **返回值** | **æè¿°** | + | 0 | æ“作æˆåŠŸ | + | è´Ÿæ•° | æ“作失败 | + >  **说明:**</br> + > RTC起始时间为UTC 1970/01/01 Thursday 00:00:00,年的最大å–值按照用户器件手册è¦æ±‚计算é…置,星期ä¸ç”¨é…置。 -``` -int32_t ret; -struct RtcTime alarmTime; - -/* 设置RTC报è¦æ—¶é—´ä¸º2020/01/01 00:59:59 .000 */ -alarmTime.year = 2020; -alarmTime.month = 01; -alarmTime.day = 01; -alarmTime.hour = 00; -alarmTime.minute = 59; -alarmTime.second = 59; -alarmTime.millisecond = 0; -/* 设置RTC_ALARM_INDEX_A索引的定时报è¦æ—¶é—´ */ -ret = RtcWriteAlarm(handle, RTC_ALARM_INDEX_A, &alarmTime); -if (ret != 0) { - /* é”™è¯¯å¤„ç† */ -} -``` + ```c + int32_t ret; + struct RtcTime alarmTime; + + /* 设置RTC报è¦æ—¶é—´ä¸º2020/01/01 00:59:59 .000 */ + alarmTime.year = 2020; + alarmTime.month = 01; + alarmTime.day = 01; + alarmTime.hour = 00; + alarmTime.minute = 59; + alarmTime.second = 59; + alarmTime.millisecond = 0; + /* 设置RTC_ALARM_INDEX_A索引的定时报è¦æ—¶é—´ */ + ret = RtcWriteAlarm(handle, RTC_ALARM_INDEX_A, &alarmTime); + if (ret != 0) { + /* é”™è¯¯å¤„ç† */ + } + ``` - 设置定时报è¦ä¸æ–使能或去使能 -在å¯åŠ¨æŠ¥è¦æ“作å‰ï¼Œéœ€è¦å…ˆè®¾ç½®æŠ¥è¦ä¸æ–使能,报è¦è¶…æ—¶åŽä¼šè§¦å‘å‘Šè¦å›žè°ƒå‡½æ•°ï¼Œå¯ä»¥é€šè¿‡ä»¥ä¸‹å‡½æ•°å®Œæˆï¼š - -int32_t RtcAlarmInterruptEnable(DevHandle handle, enum RtcAlarmIndex alarmIndex, uint8_t enable); + 在å¯åŠ¨æŠ¥è¦æ“作å‰ï¼Œéœ€è¦å…ˆè®¾ç½®æŠ¥è¦ä¸æ–使能,报è¦è¶…æ—¶åŽä¼šè§¦å‘å‘Šè¦å›žè°ƒå‡½æ•°ï¼Œå¯ä»¥é€šè¿‡ä»¥ä¸‹å‡½æ•°å®Œæˆï¼š - **表9** RtcAlarmInterruptEnableå‚数和返回值æè¿° + ```c + int32_t RtcAlarmInterruptEnable(DevHandle handle, enum RtcAlarmIndex alarmIndex, uint8_t enable); + ``` -| **å‚æ•°** | **æè¿°** | -| -------- | -------- | -| handle | RTC设备å¥æŸ„ | -| alarmIndex | 报è¦ç´¢å¼• | -| enable | RTC报è¦ä¸æ–é…置,1:使能,0:去使能 | -| **返回值** | **æè¿°** | -| 0 | æ“作æˆåŠŸ | -| è´Ÿæ•° | æ“作失败 | + **表8** RtcAlarmInterruptEnableå‚数和返回值æè¿° + | **å‚æ•°** | **æè¿°** | + | -------- | -------- | + | handle | RTC设备å¥æŸ„ | + | alarmIndex | 报è¦ç´¢å¼• | + | enable | RTC报è¦ä¸æ–é…置,1:使能,0:去使能 | + | **返回值** | **æè¿°** | + | 0 | æ“作æˆåŠŸ | + | è´Ÿæ•° | æ“作失败 | -``` -int32_t ret; - -/* 设置RTC报è¦ä¸æ–使能 */ -ret = RtcAlarmInterruptEnable(handle, RTC_ALARM_INDEX_A, 1); -if (ret != 0) { - /* é”™è¯¯å¤„ç† */ -} -``` + ```c + int32_t ret; + + /* 设置RTC报è¦ä¸æ–使能 */ + ret = RtcAlarmInterruptEnable(handle, RTC_ALARM_INDEX_A, 1); + if (ret != 0) { + /* é”™è¯¯å¤„ç† */ + } + ``` - 读å–RTC外频 -读å–RTC外接晶体振è¡é¢‘率,å¯ä»¥é€šè¿‡ä»¥ä¸‹å‡½æ•°å®Œæˆï¼š + 读å–RTC外接晶体振è¡é¢‘率,å¯ä»¥é€šè¿‡ä»¥ä¸‹å‡½æ•°å®Œæˆï¼š -int32_t RtcGetFreq(DevHandle handle, uint32_t \*freq); - - **表10** RtcGetFreqå‚数和返回值æè¿° - -| **å‚æ•°** | **æè¿°** | -| -------- | -------- | -| handle | RTC设备å¥æŸ„ | -| freq | RTC的外接晶体振è¡é¢‘率,å•ä½ï¼ˆHZ) | -| **返回值** | **æè¿°** | -| 0 | æ“作æˆåŠŸ | -| è´Ÿæ•° | æ“作失败 | + ```c + int32_t RtcGetFreq(DevHandle handle, uint32_t \*freq); + ``` + **表9** RtcGetFreqå‚数和返回值æè¿° -``` -int32_t ret; -uint32_t freq = 0; + | **å‚æ•°** | **æè¿°** | + | -------- | -------- | + | handle | RTC设备å¥æŸ„ | + | freq | RTC的外接晶体振è¡é¢‘率,å•ä½ï¼ˆHZ) | + | **返回值** | **æè¿°** | + | 0 | æ“作æˆåŠŸ | + | è´Ÿæ•° | æ“作失败 | -/* 读å–RTC外接晶体振è¡é¢‘率 */ -ret = RtcGetFreq(handle, &freq); -if (ret != 0) { - /* é”™è¯¯å¤„ç† */ -} -``` + ```c + int32_t ret; + uint32_t freq = 0; + + /* 读å–RTC外接晶体振è¡é¢‘率 */ + ret = RtcGetFreq(handle, &freq); + if (ret != 0) { + /* é”™è¯¯å¤„ç† */ + } + ``` - é…ç½®RTC外频 -é…ç½®RTC外接晶体振è¡é¢‘率,å¯ä»¥é€šè¿‡ä»¥ä¸‹å‡½æ•°å®Œæˆï¼š + é…ç½®RTC外接晶体振è¡é¢‘率,å¯ä»¥é€šè¿‡ä»¥ä¸‹å‡½æ•°å®Œæˆï¼š -int32_t RtcSetFreq(DevHandle handle, uint32_t freq); + ```c + int32_t RtcSetFreq(DevHandle handle, uint32_t freq); + ``` - **表11** RtcSetFreqå‚数和返回值æè¿° + **表10** RtcSetFreqå‚数和返回值æè¿° -| **å‚æ•°** | **æè¿°** | -| -------- | -------- | -| handle | RTC设备å¥æŸ„ | -| freq | RTC的外接晶体振è¡é¢‘率,å•ä½ï¼ˆHZ) | -| **返回值** | **æè¿°** | -| 0 | æ“作æˆåŠŸ | -| è´Ÿæ•° | æ“作失败 | + | **å‚æ•°** | **æè¿°** | + | -------- | -------- | + | handle | RTC设备å¥æŸ„ | + | freq | RTC的外接晶体振è¡é¢‘率,å•ä½ï¼ˆHZ) | + | **返回值** | **æè¿°** | + | 0 | æ“作æˆåŠŸ | + | è´Ÿæ•° | æ“作失败 | + ```c + int32_t ret; + uint32_t freq = 32768; /* 32768 Hz */ + + /* 设置RTC外接晶体振è¡é¢‘率,注æ„按照器件手册è¦æ±‚é…ç½®RTC外频 */ + ret = RtcSetFreq(handle, freq); + if (ret != 0) { + /* é”™è¯¯å¤„ç† */ + } + ``` -``` -int32_t ret; -uint32_t freq = 32768; /* 32768 Hz */ +- å¤ä½RTC -/* 设置RTC外接晶体振è¡é¢‘率,注æ„按照器件手册è¦æ±‚é…ç½®RTC外频 */ -ret = RtcSetFreq(handle, freq); -if (ret != 0) { - /* é”™è¯¯å¤„ç† */ -} -``` + å¤ä½RTC,å¤ä½RTCåŽå„é…置寄å˜å™¨æ¢å¤é»˜è®¤å€¼ï¼Œå¯ä»¥é€šè¿‡ä»¥ä¸‹å‡½æ•°å®Œæˆï¼š -- å¤ä½RTC + ```c + int32_t RtcReset(DevHandle handle); + ``` -å¤ä½RTC,å¤ä½RTCåŽå„é…置寄å˜å™¨æ¢å¤é»˜è®¤å€¼ï¼Œå¯ä»¥é€šè¿‡ä»¥ä¸‹å‡½æ•°å®Œæˆï¼š + **表11** RtcResetå‚数和返回值æè¿° -int32_t RtcReset(DevHandle handle); + | **å‚æ•°** | **æè¿°** | + | -------- | -------- | + | handle | RTC设备å¥æŸ„ | + | **返回值** | **æè¿°** | + | 0 | æ“作æˆåŠŸ | + | è´Ÿæ•° | æ“作失败 | - **表12** RtcResetå‚数和返回值æè¿° + ```c + int32_t ret; + + /* å¤ä½RTC,å„é…置寄å˜å™¨æ¢å¤é»˜è®¤å€¼ */ + ret = RtcReset(handle); + if (ret != 0) { + /* é”™è¯¯å¤„ç† */ + } + ``` -| **å‚æ•°** | **æè¿°** | -| -------- | -------- | -| handle | RTC设备å¥æŸ„ | -| **返回值** | **æè¿°** | -| 0 | æ“作æˆåŠŸ | -| è´Ÿæ•° | æ“作失败 | +- 读å–RTC自定义寄å˜å™¨é…ç½® + 按照用户定义的寄å˜å™¨ç´¢å¼•ï¼Œè¯»å–对应的寄å˜å™¨é…置,一个索引对应一å—节的é…置值,通过以下函数完æˆï¼š -``` -int32_t ret; + ```c + int32_t RtcReadReg(DevHandle handle, uint8_t usrDefIndex, uint8_t \*value); + ``` -/* å¤ä½RTC,å„é…置寄å˜å™¨æ¢å¤é»˜è®¤å€¼ */ -ret = RtcReset(handle); -if (ret != 0) { - /* é”™è¯¯å¤„ç† */ -} -``` + **表12** RtcReadRegå‚数和返回值æè¿° -- 读å–RTC自定义寄å˜å™¨é…ç½® + | **å‚æ•°** | **æè¿°** | + | -------- | -------- | + | handle | RTC设备å¥æŸ„ | + | usrDefIndex | 用户定义的寄å˜å™¨å¯¹åº”索引 | + | value | 寄å˜å™¨å€¼ | + | **返回值** | **æè¿°** | + | 0 | æ“作æˆåŠŸ | + | è´Ÿæ•° | æ“作失败 | -按照用户定义的寄å˜å™¨ç´¢å¼•ï¼Œè¯»å–对应的寄å˜å™¨é…置,一个索引对应一å—节的é…置值,通过以下函数完æˆï¼š + ```c + int32_t ret; + uint8_t usrDefIndex = 0; /* 定义0索引对应用户定义的第一个寄å˜å™¨*/ + uint8_t value = 0; + + /* 按照用户定义的寄å˜å™¨ç´¢å¼•ï¼Œè¯»å–对应的寄å˜å™¨é…置,一个索引对应一å—节的é…置值 */ + ret = RtcReadReg(handle, usrDefIndex, &value); + if (ret != 0) { + /* é”™è¯¯å¤„ç† */ + } + ``` -int32_t RtcReadReg(DevHandle handle, uint8_t usrDefIndex, uint8_t \*value); +- 设置RTC自定义寄å˜å™¨é…ç½® - **表13** RtcReadRegå‚数和返回值æè¿° + 按照用户定义的寄å˜å™¨ç´¢å¼•ï¼Œè®¾ç½®å¯¹åº”的寄å˜å™¨é…置,一个索引对应一å—节的é…置值,通过以下函数完æˆï¼š -| **å‚æ•°** | **æè¿°** | -| -------- | -------- | -| handle | RTC设备å¥æŸ„ | -| usrDefIndex | 用户定义的寄å˜å™¨å¯¹åº”索引 | -| value | 寄å˜å™¨å€¼ | -| **返回值** | **æè¿°** | -| 0 | æ“作æˆåŠŸ | -| è´Ÿæ•° | æ“作失败 | + ```c + int32_t RtcWriteReg(DevHandle handle, uint8_t usrDefIndex, uint8_t value); + ``` + **表13** RtcWriteRegå‚数和返回值æè¿° -``` -int32_t ret; -uint8_t usrDefIndex = 0; /* 定义0索引对应用户定义的第一个寄å˜å™¨*/ -uint8_t value = 0; + | **å‚æ•°** | **æè¿°** | + | -------- | -------- | + | handle | RTC设备å¥æŸ„ | + | usrDefIndex | 用户定义的寄å˜å™¨å¯¹åº”索引 | + | value | 寄å˜å™¨å€¼ | + | **返回值** | **æè¿°** | + | 0 | æ“作æˆåŠŸ | + | è´Ÿæ•° | æ“作失败 | -/* 按照用户定义的寄å˜å™¨ç´¢å¼•ï¼Œè¯»å–对应的寄å˜å™¨é…置,一个索引对应一å—节的é…置值 */ -ret = RtcReadReg(handle, usrDefIndex, &value); -if (ret != 0) { - /* é”™è¯¯å¤„ç† */ -} -``` + ```c + int32_t ret; + uint8_t usrDefIndex = 0; /* 定义0索引对应用户定义第一个寄å˜å™¨*/ + uint8_t value = 0x10; + + /* 按照用户的定义的寄å˜å™¨ç´¢å¼•ï¼Œè®¾ç½®å¯¹åº”的寄å˜å™¨é…置,一个索引对应一å—节的é…置值 */ + ret = RtcWriteReg(handle, usrDefIndex, value); + if (ret != 0) { + /* é”™è¯¯å¤„ç† */ + } + ``` -- 设置RTC自定义寄å˜å™¨é…ç½® +#### 销æ¯RTC设备å¥æŸ„ -按照用户定义的寄å˜å™¨ç´¢å¼•ï¼Œè®¾ç½®å¯¹åº”的寄å˜å™¨é…置,一个索引对应一å—节的é…置值,通过以下函数完æˆï¼š +销æ¯RTC设备å¥æŸ„,系统释放对应的资æºã€‚ -int32_t RtcWriteReg(DevHandle handle, uint8_t usrDefIndex, uint8_t value); +```c +void RtcClose(DevHandle handle); +``` - **表14** RtcWriteRegå‚数和返回值æè¿° + **表14** RtcCloseå‚æ•°æè¿° | **å‚æ•°** | **æè¿°** | | -------- | -------- | | handle | RTC设备å¥æŸ„ | -| usrDefIndex | 用户定义的寄å˜å™¨å¯¹åº”索引 | -| value | 寄å˜å™¨å€¼ | -| **返回值** | **æè¿°** | -| 0 | æ“作æˆåŠŸ | -| è´Ÿæ•° | æ“作失败 | - +```c +/* 销æ¯RTCå¥æŸ„ */ +RtcClose(handle); ``` -int32_t ret; -uint8_t usrDefIndex = 0; /* 定义0索引对应用户定义第一个寄å˜å™¨*/ -uint8_t value = 0x10; - -/* 按照用户的定义的寄å˜å™¨ç´¢å¼•ï¼Œè®¾ç½®å¯¹åº”的寄å˜å™¨é…置,一个索引对应一å—节的é…置值 */ -ret = RtcWriteReg(handle, usrDefIndex, value); -if (ret != 0) { - /* é”™è¯¯å¤„ç† */ -} -``` - -## 使用实例 +### 使用实例 -本实例æä¾›RTC接å£çš„完整使用æµç¨‹ï¼š +本例基于Hi3516DV300å¼€å‘æ¿ï¼Œæä¾›RTC接å£çš„完整使用æµç¨‹ï¼š 1. 系统å¯åŠ¨ï¼Œé©±åŠ¨ç®¡ç†æ¨¡å—会识别系统当å‰çš„RTC器件; @@ -449,9 +471,9 @@ if (ret != 0) { 示例如下: - -``` +```c #include "rtc_if.h" + int32_t RtcAlarmACallback(enum RtcAlarmIndex alarmIndex) { if (alarmIndex == RTC_ALARM_INDEX_A) { diff --git a/zh-cn/device-dev/driver/driver-platform-rtc-develop.md b/zh-cn/device-dev/driver/driver-platform-rtc-develop.md index e94f517b89392ef3e256833ad0ded234bbbe9e56..16eeb076e3ead1bf7096f48b9073db5e0c0d6148 100755 --- a/zh-cn/device-dev/driver/driver-platform-rtc-develop.md +++ b/zh-cn/device-dev/driver/driver-platform-rtc-develop.md @@ -1,21 +1,37 @@ # RTC - ## 概述 -RTC(Real-time Clock)为æ“作系统ä¸çš„实时时钟设备。在HDF框架ä¸ï¼ŒRTC的接å£é€‚é…模å¼é‡‡ç”¨ç‹¬ç«‹æœåŠ¡æ¨¡å¼ï¼Œåœ¨è¿™ç§æ¨¡å¼ä¸‹ï¼Œæ¯ä¸€ä¸ªè®¾å¤‡å¯¹è±¡ä¼šç‹¬ç«‹å‘布一个设备æœåŠ¡æ¥å¤„ç†å¤–部访问,设备管ç†å™¨æ”¶åˆ°API的访问请求之åŽï¼Œé€šè¿‡æå–该请求的å‚数,达到调用实际设备对象的相应内部方法的目的。独立æœåŠ¡æ¨¡å¼å¯ä»¥ç›´æŽ¥å€ŸåŠ©HDFDeviceManagerçš„æœåŠ¡ç®¡ç†èƒ½åŠ›ï¼Œä½†éœ€è¦ä¸ºæ¯ä¸ªè®¾å¤‡å•ç‹¬é…ç½®è®¾å¤‡èŠ‚ç‚¹ï¼Œå¢žåŠ å†…å˜å 用。 +### 功能简介 + +RTC(real-time clock)为æ“作系统ä¸çš„实时时钟设备,为æ“作系统æ供精准的实时时间和定时报è¦åŠŸèƒ½ã€‚当设备下电åŽï¼Œé€šè¿‡å¤–ç½®ç”µæ± ä¾›ç”µï¼ŒRTC继ç»è®°å½•æ“作系统时间;设备上电åŽï¼ŒRTCæ供实时时钟给æ“作系统,确ä¿æ–电åŽç³»ç»Ÿæ—¶é—´çš„è¿žç»æ€§ã€‚ + +### è¿ä½œæœºåˆ¶ + +在HDF框架ä¸ï¼ŒRTC的接å£é€‚é…模å¼é‡‡ç”¨ç‹¬ç«‹æœåŠ¡æ¨¡å¼ï¼Œåœ¨è¿™ç§æ¨¡å¼ä¸‹ï¼Œæ¯ä¸€ä¸ªè®¾å¤‡å¯¹è±¡ä¼šç‹¬ç«‹å‘布一个设备æœåŠ¡æ¥å¤„ç†å¤–部访问,设备管ç†å™¨æ”¶åˆ°API的访问请求之åŽï¼Œé€šè¿‡æå–该请求的å‚数,达到调用实际设备对象的相应内部方法的目的。独立æœåŠ¡æ¨¡å¼å¯ä»¥ç›´æŽ¥å€ŸåŠ©HDFDeviceManagerçš„æœåŠ¡ç®¡ç†èƒ½åŠ›ï¼Œä½†éœ€è¦ä¸ºæ¯ä¸ªè®¾å¤‡å•ç‹¬é…ç½®è®¾å¤‡èŠ‚ç‚¹ï¼Œå¢žåŠ å†…å˜å 用。 + +独立æœåŠ¡æ¨¡å¼ä¸‹ï¼Œæ ¸å¿ƒå±‚ä¸ä¼šç»Ÿä¸€å‘布一个æœåŠ¡ä¾›ä¸Šå±‚ä½¿ç”¨ï¼Œå› æ¤è¿™ç§æ¨¡å¼ä¸‹é©±åŠ¨è¦ä¸ºæ¯ä¸ªæŽ§åˆ¶å™¨å‘布一个æœåŠ¡ï¼Œå…·ä½“表现为: + +- 驱动适é…者需è¦å®žçŽ°HdfDriverEntryçš„Bindé’©å函数以绑定æœåŠ¡ã€‚ +- device_info.hcs文件ä¸deviceNodeçš„policyå—段为1或2,ä¸èƒ½ä¸º0。 + +**图1** RTC独立æœåŠ¡æ¨¡å¼ç»“构图<a name="fig1"></a> + + + +## å¼€å‘指导 - **图1** RTC独立æœåŠ¡æ¨¡å¼ç»“构图 +### åœºæ™¯ä»‹ç» -  +RTC主è¦ç”¨äºŽæ供实时时间和定时报è¦åŠŸèƒ½ã€‚当驱动开å‘者需è¦å°†RTC设备适é…到OpenHarmony时,需è¦è¿›è¡ŒRTC驱动适é…,下文将介ç»å¦‚何进行RTC驱动适é…。 +### 接å£è¯´æ˜Ž -## 接å£è¯´æ˜Ž +为了ä¿è¯ä¸Šå±‚在调用RTC接å£æ—¶èƒ½å¤Ÿæ£ç¡®çš„æ“ä½œç¡¬ä»¶ï¼Œæ ¸å¿ƒå±‚åœ¨//drivers/hdf_core/framework/support/platform/include/rtc/rtc_core.hä¸å®šä¹‰äº†ä»¥ä¸‹é’©å函数。驱动适é…者需è¦åœ¨é€‚é…层实现这些函数的具体功能,并与这些钩å函数挂接,从而完æˆæŽ¥å£å±‚ä¸Žæ ¸å¿ƒå±‚çš„äº¤äº’ã€‚ RtcMethod定义: - -``` +```c struct RtcMethod { int32_t (*ReadTime)(struct RtcHost *host, struct RtcTime *time); int32_t (*WriteTime)(struct RtcHost *host, const struct RtcTime *time); @@ -31,7 +47,7 @@ struct RtcMethod { }; ``` - **表1** RtcMethod结构体æˆå‘˜çš„回调函数功能说明 + **表1** RtcMethod结构体æˆå‘˜çš„é’©å函数功能说明 | 函数 | å…¥å‚ | å‡ºå‚ | 返回值 | 功能 | | -------- | -------- | -------- | -------- | -------- | @@ -48,7 +64,7 @@ struct RtcMethod { | WriteReg | hostï¼šç»“æž„ä½“æŒ‡é’ˆï¼Œæ ¸å¿ƒå±‚RTC控制器<br>usrDefIndex:结构体,用户自定义寄å˜å™¨ç´¢å¼•<br>value:uint8_t,寄å˜å™¨ä¼ 入值 | æ— | HDF_STATUSç›¸å…³çŠ¶æ€ | 按照用户定义的寄å˜å™¨ç´¢å¼•ï¼Œè®¾ç½®å¯¹åº”的寄å˜å™¨é…置,一个索引对应一å—节的é…置值 | -## å¼€å‘æ¥éª¤ +### å¼€å‘æ¥éª¤ RTC模å—适é…HDF框架的三个必选环节是实例化驱动入å£ï¼Œé…置属性文件,以åŠå¡«å……æ ¸å¿ƒå±‚æŽ¥å£å‡½æ•°ã€‚ @@ -71,9 +87,9 @@ RTC模å—适é…HDF框架的三个必选环节是实例化驱动入å£ï¼Œé…ç½® ã€å¯é€‰ã€‘针对新增驱动程åºï¼Œå»ºè®®éªŒè¯é©±åŠ¨åŸºæœ¬åŠŸèƒ½ï¼Œä¾‹å¦‚RTC控制状æ€ï¼Œä¸æ–å“应情况ç‰ã€‚ -## å¼€å‘实例 +### å¼€å‘实例 -下方将以rtc_hi35xx.c为示例,展示需è¦åŽ‚商æ供哪些内容æ¥å®Œæ•´å®žçŽ°è®¾å¤‡åŠŸèƒ½ã€‚ +下方将以Hi3516DV300的驱动//device/soc/hisilicon/common/platform/rtc/rtc_hi35xx.c为示例,展示驱动适é…者需è¦æ供哪些内容æ¥å®Œæ•´å®žçŽ°è®¾å¤‡åŠŸèƒ½ã€‚ 1. 驱动开å‘首先需è¦å®žä¾‹åŒ–驱动入å£ã€‚ @@ -85,94 +101,101 @@ RTC模å—适é…HDF框架的三个必选环节是实例化驱动入å£ï¼Œé…ç½® RTC驱动入å£å‚考: - ``` + ```c struct HdfDriverEntry g_rtcDriverEntry = { .moduleVersion = 1, - .Bind = HiRtcBind, // è§Bindå‚考 - .Init = HiRtcInit, // è§Initå‚考 - .Release = HiRtcRelease, // è§Releaseå‚考 + .Bind = HiRtcBind, // è§Bindå¼€å‘å‚考 + .Init = HiRtcInit, // è§Initå¼€å‘å‚考 + .Release = HiRtcRelease, // è§Releaseå¼€å‘å‚考 .moduleName = "HDF_PLATFORM_RTC",// ã€å¿…è¦ã€‘且与HCS里é¢çš„åå—åŒ¹é… }; - //调用HDF_INIT将驱动入å£æ³¨å†Œåˆ°HDFæ¡†æž¶ä¸ + /* 调用HDF_INIT将驱动入å£æ³¨å†Œåˆ°HDFæ¡†æž¶ä¸ */ HDF_INIT(g_rtcDriverEntry); ``` -2. 完æˆé©±åŠ¨å…¥å£æ³¨å†Œä¹‹åŽï¼Œä¸‹ä¸€æ¥è¯·åœ¨device_info.hcs文件ä¸æ·»åŠ deviceNodeä¿¡æ¯ï¼Œå¹¶åœ¨rtc_config.hcsä¸é…置器件属性。 +2. 完æˆé©±åŠ¨å…¥å£æ³¨å†Œä¹‹åŽï¼Œä¸‹ä¸€æ¥è¯·åœ¨//vendor/hisilicon/hispark_taurus/hdf_config/device_info/device_info.hcs文件ä¸æ·»åŠ deviceNodeä¿¡æ¯ï¼Œå¹¶åœ¨rtc_config.hcsä¸é…置器件属性。 deviceNodeä¿¡æ¯ä¸Žé©±åŠ¨å…¥å£æ³¨å†Œç›¸å…³ï¼Œå™¨ä»¶å±žæ€§å€¼ä¸Žæ ¸å¿ƒå±‚RtcHostæˆå‘˜çš„默认值或é™åˆ¶èŒƒå›´æœ‰å¯†åˆ‡å…³ç³»ã€‚ - 本例åªæœ‰ä¸€ä¸ªRTC控制器,如有多个器件信æ¯ï¼Œåˆ™éœ€è¦åœ¨device_infoæ–‡ä»¶å¢žåŠ deviceNodeä¿¡æ¯ï¼Œä»¥åŠåœ¨rtc_config文件ä¸å¢žåŠ 对应的器件属性。 + 本例åªæœ‰ä¸€ä¸ªRTC控制器,如有多个器件信æ¯ï¼Œåˆ™éœ€è¦åœ¨device_info.hcsæ–‡ä»¶å¢žåŠ deviceNodeä¿¡æ¯ï¼Œä»¥åŠåœ¨rtc_config文件ä¸å¢žåŠ 对应的器件属性。 - device_info.hcsé…ç½®å‚考 - ``` + ```c root { - device_info { - platform :: host { - device_rtc :: device { - device0 :: deviceNode { - policy = 1; // 2:用户æ€å¯è§ï¼›1ï¼šå†…æ ¸æ€å¯è§ï¼›0:ä¸éœ€è¦å‘布æœåŠ¡ã€‚ - priority = 30; // 值越å°ï¼Œä¼˜å…ˆçº§è¶Šé«˜ã€‚ - permission = 0644; // 驱动创建设备节点æƒé™ - moduleName = "HDF_PLATFORM_RTC"; // ã€å¿…è¦ã€‘用于指定驱动å称,需è¦ä¸Žé©±åŠ¨Entryä¸çš„moduleName一致。 - serviceName = "HDF_PLATFORM_RTC"; // ã€å¿…è¦ã€‘驱动对外å‘布æœåŠ¡çš„å称,必须唯一。 - deviceMatchAttr = "hisilicon_hi35xx_rtc";// ã€å¿…è¦ã€‘需è¦ä¸Žè®¾å¤‡hcs文件ä¸çš„match_attr匹é…。 + device_info { + platform :: host { + device_rtc :: device { + device0 :: deviceNode { + policy = 1; // 2:用户æ€å¯è§ï¼›1ï¼šå†…æ ¸æ€å¯è§ï¼›0:ä¸éœ€è¦å‘布æœåŠ¡ã€‚ + priority = 30; // 值越å°ï¼Œä¼˜å…ˆçº§è¶Šé«˜ã€‚ + permission = 0644; // 驱动创建设备节点æƒé™ + moduleName = "HDF_PLATFORM_RTC"; // ã€å¿…è¦ã€‘用于指定驱动å称,需è¦ä¸Žé©±åŠ¨Entryä¸çš„moduleName一致。 + serviceName = "HDF_PLATFORM_RTC"; // ã€å¿…è¦ã€‘驱动对外å‘布æœåŠ¡çš„å称,必须唯一。 + deviceMatchAttr = "hisilicon_hi35xx_rtc"; // ã€å¿…è¦ã€‘需è¦ä¸Žè®¾å¤‡hcs文件ä¸çš„match_attr匹é…。 + } + } } - } } - } } ``` - rtc_config.hcsé…ç½®å‚考 - ``` + ```c root { - platform { - rtc_config { - controller_0x12080000 { - match_attr = "hisilicon_hi35xx_rtc";// ã€å¿…è¦ã€‘需è¦å’Œdevice_info.hcsä¸çš„deviceMatchAttr值一致 - rtcSpiBaseAddr = 0x12080000; // 地å€æ˜ 射相关 - regAddrLength = 0x100; // 地å€æ˜ 射相关 - irq = 37; // ä¸æ–å· - supportAnaCtrl = false; - supportLock = false; - anaCtrlAddr = 0xff; - lock0Addr = 0xff; - lock1Addr = 0xff; - lock2Addr = 0xff; - lock3Addr = 0xff; - } + platform { + rtc_config { + controller_0x12080000 { + match_attr = "hisilicon_hi35xx_rtc"; // ã€å¿…è¦ã€‘需è¦å’Œdevice_info.hcsä¸çš„deviceMatchAttr值一致 + rtcSpiBaseAddr = 0x12080000; // 地å€æ˜ 射相关 + regAddrLength = 0x100; // 地å€æ˜ 射相关 + irq = 37; // ä¸æ–å· + supportAnaCtrl = false; + supportLock = false; + anaCtrlAddr = 0xff; + lock0Addr = 0xff; + lock1Addr = 0xff; + lock2Addr = 0xff; + lock3Addr = 0xff; + } + } } - } } ``` -3. 完æˆå±žæ€§æ–‡ä»¶é…置之åŽï¼Œä¸‹ä¸€æ¥å°±æ˜¯ä»¥æ ¸å¿ƒå±‚RtcHost对象的åˆå§‹åŒ–ä¸ºæ ¸å¿ƒï¼ŒåŒ…æ‹¬åŽ‚å•†è‡ªå®šä¹‰ç»“æž„ä½“ï¼ˆä¼ é€’å‚数和数æ®ï¼‰ï¼Œå®žä¾‹åŒ–RtcHostæˆå‘˜RtcMethod(让用户å¯ä»¥é€šè¿‡æŽ¥å£æ¥è°ƒç”¨é©±åŠ¨åº•å±‚函数),实现HdfDriverEntryæˆå‘˜å‡½æ•°ï¼ˆBindã€Initã€Release)。 + 需è¦æ³¨æ„的是,新增rtc_config.hcsé…置文件åŽï¼Œå¿…须在hdf.hcs文件ä¸å°†å…¶åŒ…å«ï¼Œå¦åˆ™é…ç½®æ–‡ä»¶æ— æ³•ç”Ÿæ•ˆã€‚ + + 例如:本例ä¸rtc_config.hcs所在路径为device/soc/hisilicon/hi3516dv300/sdk_liteos/hdf_config/rtc/rtc_config.hcs,则必须在产å“对应的hdf.hcsä¸æ·»åŠ 如下è¯å¥ï¼š + + ```c + #include "../../../../device/soc/hisilicon/hi3516dv300/sdk_liteos/hdf_config/rtc/rtc_config.hcs" // é…置文件相对路径 + ``` + +3. 完æˆå±žæ€§æ–‡ä»¶é…置之åŽï¼Œä¸‹ä¸€æ¥å°±æ˜¯ä»¥æ ¸å¿ƒå±‚RtcHost对象的åˆå§‹åŒ–ä¸ºæ ¸å¿ƒï¼ŒåŒ…æ‹¬é©±åŠ¨é€‚é…è€…è‡ªå®šä¹‰ç»“æž„ä½“ï¼ˆä¼ é€’å‚数和数æ®ï¼‰ï¼Œå®žä¾‹åŒ–RtcHostæˆå‘˜RtcMethod(让用户å¯ä»¥é€šè¿‡æŽ¥å£æ¥è°ƒç”¨é©±åŠ¨åº•å±‚函数),实现HdfDriverEntryæˆå‘˜å‡½æ•°ï¼ˆBindã€Initã€Release)。 - 自定义结构体å‚考。 从驱动的角度看,自定义结构体是å‚数和数æ®çš„载体,而且rtc_config.hcs文件ä¸çš„数值会被HDF读入并通过DeviceResourceIfaceæ¥åˆå§‹åŒ–结构体æˆå‘˜ã€‚ - - ``` + ```c struct RtcConfigInfo { - uint32_t spiBaseAddr; // 地å€æ˜ 射相关 - volatile void *remapBaseAddr; // 地å€æ˜ 射相关 - uint16_t regAddrLength; // 地å€æ˜ 射相关 - uint8_t supportAnaCtrl; // 是å¦æ”¯æŒanactrl - uint8_t supportLock; // 是å¦æ”¯æŒé” - uint8_t irq; // ä¸æ–å· - uint8_t alarmIndex; // 闹钟索引 - uint8_t anaCtrlAddr; // anactrlåœ°å€ - struct RtcLockAddr lockAddr; // é”åœ°å€ - RtcAlarmCallback cb; // 回调函数 - struct OsalMutex mutex; // äº’æ–¥é” + uint32_t spiBaseAddr; // 地å€æ˜ 射相关 + volatile void *remapBaseAddr; // 地å€æ˜ 射相关 + uint16_t regAddrLength; // 地å€æ˜ 射相关 + uint8_t supportAnaCtrl; // 是å¦æ”¯æŒanactrl + uint8_t supportLock; // 是å¦æ”¯æŒé” + uint8_t irq; // ä¸æ–å· + uint8_t alarmIndex; // 闹钟索引 + uint8_t anaCtrlAddr; // anactrlåœ°å€ + struct RtcLockAddr lockAddr; // é”åœ°å€ + RtcAlarmCallback cb; // 回调函数 + struct OsalMutex mutex; // äº’æ–¥é” }; - // RtcHostæ˜¯æ ¸å¿ƒå±‚æŽ§åˆ¶å™¨ç»“æž„ä½“ï¼Œå…¶ä¸çš„æˆå‘˜åœ¨Init函数ä¸ä¼šè¢«èµ‹å€¼ã€‚ + /* RtcHostæ˜¯æ ¸å¿ƒå±‚æŽ§åˆ¶å™¨ç»“æž„ä½“ï¼Œå…¶ä¸çš„æˆå‘˜åœ¨Init函数ä¸ä¼šè¢«èµ‹å€¼ã€‚ */ struct RtcHost { struct IDeviceIoService service; struct HdfDeviceObject *device; @@ -180,35 +203,35 @@ RTC模å—适é…HDF框架的三个必选环节是实例化驱动入å£ï¼Œé…ç½® void *data; }; ``` - - RtcHostæˆå‘˜å›žè°ƒå‡½æ•°ç»“构体RtcMethod的实例化,其他æˆå‘˜åœ¨Init函数ä¸åˆå§‹åŒ–。 - - ``` - // rtc_hi35xx.cä¸çš„示例:钩å函数的填充 + - RtcHostæˆå‘˜é’©å函数结构体RtcMethod的实例化,其他æˆå‘˜åœ¨Init函数ä¸åˆå§‹åŒ–。 + + ```c + /* rtc_hi35xx.cä¸çš„示例:钩å函数的填充 */ static struct RtcMethod g_method = { - .ReadTime = HiRtcReadTime, - .WriteTime = HiRtcWriteTime, - .ReadAlarm = HiReadAlarm, + .ReadTime = HiRtcReadTime, + .WriteTime = HiRtcWriteTime, + .ReadAlarm = HiReadAlarm, .WriteAlarm = HiWriteAlarm, - .RegisterAlarmCallback = HiRegisterAlarmCallback, - .AlarmInterruptEnable = HiAlarmInterruptEnable, - .GetFreq = HiGetFreq, - .SetFreq = HiSetFreq, - .Reset = HiReset, - .ReadReg = HiReadReg, + .RegisterAlarmCallback = HiRegisterAlarmCallback, + .AlarmInterruptEnable = HiAlarmInterruptEnable, + .GetFreq = HiGetFreq, + .SetFreq = HiSetFreq, + .Reset = HiReset, + .ReadReg = HiReadReg, .WriteReg = HiWriteReg, }; ``` - - Bind 函数å‚考 + - Bind函数开å‘å‚考 å…¥å‚: - HdfDeviceObject是整个驱动对外暴露的接å£å‚数,具备HCSé…置文件的信æ¯ã€‚ + HdfDeviceObject是整个驱动对外æ供的接å£å‚数,具备HCSé…置文件的信æ¯ã€‚ 返回值: - HDF_STATUS相关状æ€ï¼ˆä¸‹è¡¨ä¸ºéƒ¨åˆ†å±•ç¤ºï¼Œå¦‚需使用其他状æ€ï¼Œå¯è§//drivers/framework/include/utils/hdf_base.hä¸HDF_STATUS定义)。 + HDF_STATUS相关状æ€ï¼ˆä¸‹è¡¨ä¸ºéƒ¨åˆ†å±•ç¤ºï¼Œå¦‚需使用其他状æ€ï¼Œå¯è§//drivers/hdf_core/framework/include/utils/hdf_base.hä¸HDF_STATUS定义)。 **表2** HDF_STATUS返回值æè¿° @@ -225,25 +248,24 @@ RTC模å—适é…HDF框架的三个必选环节是实例化驱动入å£ï¼Œé…ç½® å…³è”HdfDeviceObject对象和RtcHost。 - - ``` + ```c static int32_t HiRtcBind(struct HdfDeviceObject *device) { - struct RtcHost *host = NULL; - host = RtcHostCreate(device); // 实际是申请内å˜å¹¶æŒ‚接device: host->device = device - // 使HdfDeviceObject与RtcHostå¯ä»¥ç›¸äº’转化的å‰æ - ... - device->service = &host->service;// 使HdfDeviceObject与RtcHostå¯ä»¥ç›¸äº’转化的å‰æ - // 方便åŽç»é€šè¿‡è°ƒç”¨RtcHostFromDevice实现全局性质的host - return HDF_SUCCESS; + struct RtcHost *host = NULL; + host = RtcHostCreate(device); // 实际是申请内å˜å¹¶æŒ‚接device: host->device = device + // 使HdfDeviceObject与RtcHostå¯ä»¥ç›¸äº’转化的å‰æ + ... + device->service = &host->service; // 使HdfDeviceObject与RtcHostå¯ä»¥ç›¸äº’转化的å‰æ + // 方便åŽç»é€šè¿‡è°ƒç”¨RtcHostFromDevice实现全局性质的host + return HDF_SUCCESS; } ``` - - Init函数å‚考 + - Init函数开å‘å‚考 å…¥å‚: - HdfDeviceObject是整个驱动对外暴露的接å£å‚数,具备HCSé…置文件的信æ¯ã€‚ + HdfDeviceObject是整个驱动对外æ供的接å£å‚数,具备HCSé…置文件的信æ¯ã€‚ 返回值: @@ -253,39 +275,39 @@ RTC模å—适é…HDF框架的三个必选环节是实例化驱动入å£ï¼Œé…ç½® åˆå§‹åŒ–自定义结构体对象,åˆå§‹åŒ–RtcHostæˆå‘˜ã€‚ - - ``` + ```c static int32_t HiRtcInit(struct HdfDeviceObject *device) { - struct RtcHost *host = NULL; - struct RtcConfigInfo *rtcInfo = NULL; - ... - host = RtcHostFromDevice(device);// 这里是HdfDeviceObject到RtcHost的强制转化 - rtcInfo = OsalMemCalloc(sizeof(*rtcInfo)); - ... - // HiRtcConfigData会从设备é…ç½®æ ‘ä¸è¯»å–属性填充rtcInfoçš„supportAnaCtrlã€supportLockã€spiBaseAddrã€regAddrLengthã€irq, - // 为HiRtcSwInitå’ŒHiRtcSwInitæä¾›å‚数,当函数HiRtcSwInitå’ŒHiRtcSwInit内部执行失败åŽè¿›è¡Œå†…å˜é‡Šæ”¾ç‰æ“作。 - if (HiRtcConfigData(rtcInfo, device->property) != 0) { - ... - } - if (HiRtcSwInit(rtcInfo) != 0) {// 地å€æ˜ 射以åŠä¸æ–注册相关 + struct RtcHost *host = NULL; + struct RtcConfigInfo *rtcInfo = NULL; ... - } - if (HiRtcHwInit(rtcInfo) != 0) {// åˆå§‹åŒ–anaCtrlå’ŒlockAddr相关内容 + host = RtcHostFromDevice(device); // 这里是HdfDeviceObject到RtcHostçš„å¼ºåˆ¶è½¬æ¢ + rtcInfo = OsalMemCalloc(sizeof(*rtcInfo)); ... - } + /* HiRtcConfigData会从设备é…ç½®æ ‘ä¸è¯»å–属性填充rtcInfoçš„supportAnaCtrlã€supportLockã€spiBaseAddrã€regAddrLengthã€irq, + * 为HiRtcSwInitå’ŒHiRtcSwInitæä¾›å‚数,当函数HiRtcSwInitå’ŒHiRtcSwInit内部执行失败åŽè¿›è¡Œå†…å˜é‡Šæ”¾ç‰æ“作。 + */ + if (HiRtcConfigData(rtcInfo, device->property) != 0) { + ... + } + if (HiRtcSwInit(rtcInfo) != 0) { // 地å€æ˜ 射以åŠä¸æ–注册相关 + ... + } + if (HiRtcHwInit(rtcInfo) != 0) { // åˆå§‹åŒ–anaCtrlå’ŒlockAddr相关内容 + ... + } - host->method = &g_method;// RtcMethod的实例化对象的挂载 - host->data = rtcInfo; // 使RtcConfigInfo与RtcHostå¯ä»¥ç›¸äº’转化的å‰æ - HDF_LOGI("Hdf dev service:%s init success!", HdfDeviceGetServiceName(device)); - return HDF_SUCCESS; + host->method = &g_method; // RtcMethod的实例化对象的挂载 + host->data = rtcInfo; // 使RtcConfigInfo与RtcHostå¯ä»¥ç›¸äº’转化的å‰æ + HDF_LOGI("Hdf dev service:%s init success!", HdfDeviceGetServiceName(device)); + return HDF_SUCCESS; } ``` - - Release 函数å‚考 + - Release函数开å‘å‚考 å…¥å‚: - HdfDeviceObject是整个驱动对外暴露的接å£å‚数,具备HCSé…置文件的信æ¯ã€‚ + HdfDeviceObject是整个驱动对外æ供的接å£å‚数,具备HCSé…置文件的信æ¯ã€‚ 返回值: @@ -299,19 +321,19 @@ RTC模å—适é…HDF框架的三个必选环节是实例化驱动入å£ï¼Œé…ç½® > 所有强制转æ¢èŽ·å–相应对象的æ“作å‰æ是在Init或Bind函数ä¸å…·å¤‡å¯¹åº”赋值的æ“作。 - ``` + ```c static void HiRtcRelease(struct HdfDeviceObject *device) { struct RtcHost *host = NULL; struct RtcConfigInfo *rtcInfo = NULL; ... - host = RtcHostFromDevice(device); // 这里是HdfDeviceObject到RtcHost的强制转化 - rtcInfo = (struct RtcConfigInfo *)host->data;// 这里是RtcHost到RtcConfigInfo的强制转化 + host = RtcHostFromDevice(device); // 这里是HdfDeviceObject到RtcHostçš„å¼ºåˆ¶è½¬æ¢ + rtcInfo = (struct RtcConfigInfo *)host->data; // 这里是RtcHost到RtcConfigInfoçš„å¼ºåˆ¶è½¬æ¢ if (rtcInfo != NULL) { HiRtcSwExit(rtcInfo); - OsalMemFree(rtcInfo); // 释放RtcConfigInfo + OsalMemFree(rtcInfo); // 释放RtcConfigInfo host->data = NULL; } - RtcHostDestroy(host); // 释放RtcHost + RtcHostDestroy(host); // 释放RtcHost } ``` diff --git a/zh-cn/device-dev/driver/driver-platform-sdio-des.md b/zh-cn/device-dev/driver/driver-platform-sdio-des.md index bd0330af218ae12ba632f155e4cca10d151d52da..c43d88eecd9d918c5298ad7ef9317e42d81a8ce2 100644 --- a/zh-cn/device-dev/driver/driver-platform-sdio-des.md +++ b/zh-cn/device-dev/driver/driver-platform-sdio-des.md @@ -1,11 +1,21 @@ # SDIO - ## 概述 -SDIO是安全数å—输入输出接å£ï¼ˆSecure Digital Input and Output)的缩写,是从SD内å˜å¡æŽ¥å£çš„基础上演化出æ¥çš„一ç§å¤–设接å£ã€‚SDIO接å£å…¼å®¹ä»¥å‰çš„SD内å˜å¡ï¼Œå¹¶ä¸”å¯ä»¥è¿žæŽ¥æ”¯æŒSDIO接å£çš„设备。 +### 功能简介 -SDIO的应用比较广泛,目å‰ï¼Œæœ‰è®¸å¤šæ‰‹æœºéƒ½æ”¯æŒSDIO功能,并且很多SDIO外设也被开å‘出æ¥ï¼Œä½¿å¾—æ‰‹æœºå¤–æŽ¥å¤–è®¾æ›´åŠ å®¹æ˜“ã€‚å¸¸è§çš„SDIO外设有WLANã€GPSã€CAMERAã€è“牙ç‰ã€‚ +SDIO是安全数å—输入输出接å£ï¼ˆSecure Digital Input and Output)的缩写,是从SD内å˜å¡æŽ¥å£çš„基础上演化出æ¥çš„一ç§å¤–设接å£ã€‚SDIO接å£å…¼å®¹ä»¥å‰çš„SDå¡ï¼Œå¹¶ä¸”å¯ä»¥è¿žæŽ¥æ”¯æŒSDIO接å£çš„其他设备。 + +SDIO接å£å®šä¹‰äº†æ“作SDIO的通用方法集åˆï¼ŒåŒ…括: +- 打开/å…³é—SDIO控制器 +- 独å /释放HOST +- 使能/去使能设备 +- 申请/释放ä¸æ– +- 读写ã€èŽ·å–/è®¾ç½®å…¬å…±ä¿¡æ¯ + +### è¿ä½œæœºåˆ¶ + +在HDF框架ä¸ï¼ŒSDIO的接å£é€‚é…模å¼é‡‡ç”¨ç‹¬ç«‹æœåŠ¡æ¨¡å¼ã€‚在这ç§æ¨¡å¼ä¸‹ï¼Œæ¯ä¸€ä¸ªè®¾å¤‡å¯¹è±¡ä¼šç‹¬ç«‹å‘布一个设备æœåŠ¡æ¥å¤„ç†å¤–部访问,设备管ç†å™¨æ”¶åˆ°API的访问请求之åŽï¼Œé€šè¿‡æå–该请求的å‚数,达到调用实际设备对象的相应内部方法的目的。独立æœåŠ¡æ¨¡å¼å¯ä»¥ç›´æŽ¥å€ŸåŠ©HDFDeviceManagerçš„æœåŠ¡ç®¡ç†èƒ½åŠ›ï¼Œä½†éœ€è¦ä¸ºæ¯ä¸ªè®¾å¤‡å•ç‹¬é…置设备节点,若设备过多å¯èƒ½å¢žåŠ 内å˜å 用。 SDIO总线有两端,其ä¸ä¸€ç«¯æ˜¯ä¸»æœºç«¯ï¼ˆHOST),å¦ä¸€ç«¯æ˜¯è®¾å¤‡ç«¯ï¼ˆDEVICE)。所有的通信都是由HOST端å‘出命令开始的,在DEVICE端åªè¦èƒ½è§£æžHOST的命令,就å¯ä»¥åŒHOST进行通信了。SDIOçš„HOSTå¯ä»¥è¿žæŽ¥å¤šä¸ªDEVICE,如下图所示: - CLKä¿¡å·ï¼šHOSTç»™DEVICE的时钟信å·ã€‚ @@ -18,30 +28,42 @@ SDIO总线有两端,其ä¸ä¸€ç«¯æ˜¯ä¸»æœºç«¯ï¼ˆHOST),å¦ä¸€ç«¯æ˜¯è®¾å¤‡ç«¯  -SDIO接å£å®šä¹‰äº†æ“作SDIO的通用方法集åˆï¼ŒåŒ…括打开/å…³é—SDIO控制器ã€ç‹¬å /释放HOSTã€ä½¿èƒ½/去使能设备ã€ç”³è¯·/释放ä¸æ–ã€è¯»å†™ã€èŽ·å–/设置公共信æ¯ç‰ã€‚ +### 约æŸä¸Žé™åˆ¶ +SDIO模å—API当å‰ä»…支æŒå†…æ ¸æ€è°ƒç”¨ã€‚ -## 接å£è¯´æ˜Ž +## 使用指导 - **表1** SDIO驱动API接å£åŠŸèƒ½ä»‹ç» +### åœºæ™¯ä»‹ç» -| 功能分类 | 接å£æè¿° | -| -------- | -------- | -| SDIO设备打开/å…³é—æŽ¥å£ | - SdioOpen:打开指定总线å·çš„SDIO控制器<br/>- SdioClose:关é—SDIO控制器 | -| SDIOè¯»å†™æŽ¥å£ | - SdioReadBytes:从指定地å€å¼€å§‹ï¼Œå¢žé‡è¯»å–指定长度的数æ®<br/>- SdioWriteBytes:从指定地å€å¼€å§‹ï¼Œå¢žé‡å†™å…¥æŒ‡å®šé•¿åº¦çš„æ•°æ®<br/>- SdioReadBytesFromFixedAddr:从固定地å€è¯»å–指定长度的数æ®<br/>- SdioWriteBytesToFixedAddr:å‘固定地å€å†™å…¥æŒ‡å®šé•¿åº¦çš„æ•°æ®<br/>- SdioReadBytesFromFunc0:从SDIO function 0的指定地å€ç©ºé—´è¯»å–指定长度的数æ®<br/>- SdioWriteBytesToFunc0:å‘SDIO function 0的指定地å€ç©ºé—´å†™å…¥æŒ‡å®šé•¿åº¦çš„æ•°æ® | -| SDIO设置å—大å°æŽ¥å£ | SdioSetBlockSize:设置å—çš„å¤§å° | -| SDIO获å–/设置公共信æ¯æŽ¥å£ | - SdioGetCommonInfo:获å–公共信æ¯<br/>- SdioSetCommonInfoï¼šè®¾ç½®å…¬å…±ä¿¡æ¯ | -| SDIO刷新数æ®æŽ¥å£ | SdioFlushDataï¼šåˆ·æ–°æ•°æ® | -| SDIO独å /释放HOSTæŽ¥å£ | - SdioClaimHost:独å Host<br/>- SdioReleaseHost:释放Host | -| SDIO使能/åŽ»ä½¿èƒ½åŠŸèƒ½è®¾å¤‡æŽ¥å£ | - SdioEnableFunc:使能SDIO功能设备<br/>- SdioDisableFunc:去使能SDIO功能设备 | -| SDIO申请/释放ä¸æ–æŽ¥å£ | - SdioClaimIrq:申请ä¸æ–<br/>- SdioReleaseIrq:释放ä¸æ– | +SDIO的应用比较广泛,目å‰ï¼Œæœ‰è®¸å¤šæ‰‹æœºéƒ½æ”¯æŒSDIO功能,并且很多SDIO外设也被开å‘出æ¥ï¼Œä½¿å¾—æ‰‹æœºå¤–æŽ¥å¤–è®¾æ›´åŠ å®¹æ˜“ã€‚å¸¸è§çš„SDIO外设有WLANã€GPSã€CAMERAã€è“牙ç‰ã€‚ ->  **说明:**<br> -> 本文涉åŠçš„所有接å£ï¼Œç›®å‰åªæ”¯æŒåœ¨å†…æ ¸æ€ä½¿ç”¨ï¼Œä¸æ”¯æŒåœ¨ç”¨æˆ·æ€ä½¿ç”¨ã€‚ +### 接å£è¯´æ˜Ž +SDIO模å—æ供的主è¦æŽ¥å£å¦‚表1所示,具体API详è§//drivers/hdf_core/framework/include/platform/sdio_if.h。 -## 使用指导 +**表1** SDIO驱动API接å£åŠŸèƒ½ä»‹ç» +| 接å£å | 接å£æè¿° | +| -------- | -------- | +| DevHandle SdioOpen(int16_t mmcBusNum, struct SdioFunctionConfig \*config) | 打开指定总线å·çš„SDIO控制器 | +| void SdioClose(DevHandle handle) | å…³é—SDIO控制器 | +| int32_t SdioReadBytes(DevHandle handle, uint8_t \*data, uint32_t addr, uint32_t size) | 从指定地å€å¼€å§‹ï¼Œå¢žé‡è¯»å–æŒ‡å®šé•¿åº¦çš„æ•°æ® | +| int32_t SdioWriteBytes(DevHandle handle, uint8_t \*data, uint32_t addr, uint32_t size) | 从指定地å€å¼€å§‹ï¼Œå¢žé‡å†™å…¥æŒ‡å®šé•¿åº¦çš„æ•°æ® | +| int32_t SdioReadBytesFromFixedAddr(DevHandle handle, uint8_t \*data, uint32_t addr, uint32_t size, uint32_t scatterLen) | 从固定地å€è¯»å–æŒ‡å®šé•¿åº¦çš„æ•°æ® | +| int32_t SdioWriteBytesToFixedAddr(DevHandle handle, uint8_t \*data, uint32_t addr, uint32_t size, uint32_t scatterLen) | å‘固定地å€å†™å…¥æŒ‡å®šé•¿åº¦çš„æ•°æ® | +| int32_t SdioReadBytesFromFunc0(DevHandle handle, uint8_t \*data, uint32_t addr, uint32_t size) | 从SDIO function 0的指定地å€ç©ºé—´è¯»å–æŒ‡å®šé•¿åº¦çš„æ•°æ® | +| int32_t SdioWriteBytesToFunc0(DevHandle handle, uint8_t \*data, uint32_t addr, uint32_t size) | å‘SDIO function 0的指定地å€ç©ºé—´å†™å…¥æŒ‡å®šé•¿åº¦çš„æ•°æ® | +| int32_t SdioSetBlockSize(DevHandle handle, uint32_t blockSize) | 设置å—çš„å¤§å° | +| int32_t SdioGetCommonInfo(DevHandle handle, SdioCommonInfo \*info, SdioCommonInfoType infoType) | 获å–å…¬å…±ä¿¡æ¯ | +| int32_t SdioSetCommonInfo(DevHandle handle, SdioCommonInfo \*info, SdioCommonInfoType infoType) | è®¾ç½®å…¬å…±ä¿¡æ¯ | +| int32_t SdioFlushData(DevHandle handle) | åˆ·æ–°æ•°æ® | +| void SdioClaimHost(DevHandle handle) | 独å Host | +| void SdioReleaseHost(DevHandle handle) | 释放Host | +| int32_t SdioEnableFunc(DevHandle handle) | 使能SDIO功能设备 | +| int32_t SdioDisableFunc(DevHandle handle) | 去使能SDIO功能设备 | +| int32_t SdioClaimIrq(DevHandle handle, SdioIrqHandler \*irqHandler) | 申请ä¸æ– | +| int32_t SdioReleaseIrq(DevHandle handle) | 释放ä¸æ– | ### 使用æµç¨‹ @@ -51,13 +73,11 @@ SDIO接å£å®šä¹‰äº†æ“作SDIO的通用方法集åˆï¼ŒåŒ…括打开/å…³é—SDIO控  - -### 打开SDIO控制器 +#### 打开SDIO控制器 在使用SDIO进行通信å‰ï¼Œé¦–å…ˆè¦è°ƒç”¨SdioOpen获å–SDIO控制器的设备å¥æŸ„,该函数会返回指定总线å·çš„SDIO控制器的设备å¥æŸ„。 - -``` +```c DevHandle SdioOpen(int16_t mmcBusNum, struct SdioFunctionConfig *config); ``` @@ -72,8 +92,8 @@ DevHandle SdioOpen(int16_t mmcBusNum, struct SdioFunctionConfig *config); | 设备å¥æŸ„ | SDIO控制器的设备å¥æŸ„ | 打开SDIO控制器的示例如下: - -``` + +```c DevHandle handle = NULL; struct SdioFunctionConfig config; config.funcNr = 1; @@ -86,13 +106,11 @@ if (handle == NULL) { } ``` - -### 独å HOST +#### 独å HOST 获å–到SDIO控制器的设备å¥æŸ„之åŽï¼Œéœ€è¦å…ˆç‹¬å HOSTæ‰èƒ½è¿›è¡ŒSDIOåŽç»çš„一系列æ“作,独å HOST函数如下所示: - -``` +```c void SdioClaimHost(DevHandle handle); ``` @@ -104,18 +122,15 @@ void SdioClaimHost(DevHandle handle); 独å HOST示例如下: - -``` +```c SdioClaimHost(handle); /* 独å HOST */ ``` - -### 使能SDIO设备 +#### 使能SDIO设备 在访问寄å˜å™¨ä¹‹å‰ï¼Œéœ€è¦å…ˆä½¿èƒ½SDIO设备,使能SDIO设备的函数如下所示: - -``` +```c int32_t SdioEnableFunc(DevHandle handle); ``` @@ -130,8 +145,7 @@ int32_t SdioEnableFunc(DevHandle handle); 使能SDIO设备的示例如下: - -``` +```c int32_t ret; /* 使能SDIO设备 */ ret = SdioEnableFunc(handle); @@ -140,13 +154,11 @@ if (ret != 0) { } ``` - -### 注册SDIOä¸æ– +#### 注册SDIOä¸æ– 在通信之å‰ï¼Œè¿˜éœ€è¦æ³¨å†ŒSDIOä¸æ–,注册SDIOä¸æ–函数如下图所示: - -``` +```c int32_t SdioClaimIrq(DevHandle handle, SdioIrqHandler *handler); ``` @@ -161,8 +173,8 @@ int32_t SdioClaimIrq(DevHandle handle, SdioIrqHandler *handler); | è´Ÿæ•° | 注册ä¸æ–失败 | 注册SDIOä¸çš„示例如下: - -``` + +```c /* ä¸æ–æœåŠ¡å‡½æ•°éœ€è¦æ ¹æ®å„自平å°çš„情况去实现 */ static void SdioIrqFunc(void *data) { @@ -181,15 +193,13 @@ if (ret != 0) { } ``` - -### 进行SDIO通信 +#### 进行SDIO通信 - å‘SDIO设备增é‡å†™å…¥æŒ‡å®šé•¿åº¦çš„æ•°æ® å¯¹åº”çš„æŽ¥å£å‡½æ•°å¦‚下所示: - - ``` + ```c int32_t SdioWriteBytes(DevHandle handle, uint8_t *data, uint32_t addr, uint32_t size); ``` @@ -207,8 +217,7 @@ if (ret != 0) { å‘SDIO设备增é‡å†™å…¥æŒ‡å®šé•¿åº¦çš„æ•°æ®çš„示例如下: - - ``` + ```c int32_t ret; uint8_t wbuff[] = {1,2,3,4,5}; uint32_t addr = 0x100 + 0x09; @@ -223,8 +232,7 @@ if (ret != 0) { 对应的接å£å‡½æ•°å¦‚下所示: - - ``` + ```c int32_t SdioReadBytes(DevHandle handle, uint8_t *data, uint32_t addr, uint32_t size); ``` @@ -242,8 +250,7 @@ if (ret != 0) { 从SDIO设备增é‡è¯»å–指定长度的数æ®çš„示例如下: - - ``` + ```c int32_t ret; uint8_t rbuff[5] = {0}; uint32_t addr = 0x100 + 0x09; @@ -255,10 +262,10 @@ if (ret != 0) { ``` - å‘SDIO设备的固定地å€å†™å…¥æŒ‡å®šé•¿åº¦çš„æ•°æ® + 对应的接å£å‡½æ•°å¦‚下所示: - - ``` + ```c int32_t SdioWriteBytesToFixedAddr(DevHandle handle, uint8_t *data, uint32_t addr, uint32_t size, uint32_t scatterLen); ``` @@ -277,8 +284,7 @@ if (ret != 0) { å‘SDIO设备的固定地å€å†™å…¥æŒ‡å®šé•¿åº¦çš„æ•°æ®çš„示例如下: - - ``` + ```c int32_t ret; uint8_t wbuff[] = {1,2,3,4,5}; uint32_t addr = 0x100 + 0x09; @@ -290,10 +296,10 @@ if (ret != 0) { ``` - 从SDIO设备的固定地å€è¯»å–æŒ‡å®šé•¿åº¦çš„æ•°æ® + 对应的接å£å‡½æ•°å¦‚下所示: - - ``` + ```c int32_t SdioReadBytesFromFixedAddr(DevHandle handle, uint8_t *data, uint32_t addr, uint32_t size, uint32_t scatterLen); ``` @@ -312,8 +318,7 @@ if (ret != 0) { 从SDIO设备的固定地å€è¯»å–指定长度的数æ®çš„示例如下: - - ``` + ```c int32_t ret; uint8_t rbuff[5] = {0}; uint32_t addr = 0x100 + 0x09; @@ -328,8 +333,7 @@ if (ret != 0) { 当å‰åªæ”¯æŒå†™å…¥ä¸€ä¸ªå—节的数æ®ï¼Œå¯¹åº”的接å£å‡½æ•°å¦‚下所示: - - ``` + ```c int32_t SdioWriteBytesToFunc0(DevHandle handle, uint8_t *data, uint32_t addr, uint32_t size); ``` @@ -347,8 +351,7 @@ if (ret != 0) { å‘SDIO function 0的指定地å€ç©ºé—´å†™å…¥æŒ‡å®šé•¿åº¦çš„æ•°æ®çš„示例如下: - - ``` + ```c int32_t ret; uint8_t wbuff = 1; /* å‘SDIO function 0地å€0x2ä¸å†™å…¥1å—èŠ‚çš„æ•°æ® */ @@ -362,8 +365,7 @@ if (ret != 0) { 当å‰åªæ”¯æŒè¯»å–一个å—节的数æ®ï¼Œå¯¹åº”的接å£å‡½æ•°å¦‚下所示: - - ``` + ```c int32_t SdioReadBytesFromFunc0(DevHandle handle, uint8_t *data, uint32_t addr, uint32_t size); ``` @@ -381,8 +383,7 @@ if (ret != 0) { 从SDIO function 0的指定地å€ç©ºé—´è¯»å–指定长度的数æ®çš„示例如下: - - ``` + ```c int32_t ret; uint8_t rbuff; /* 从SDIO function 0设备地å€0x2ä¸è¯»å–1å—èŠ‚çš„æ•°æ® */ @@ -392,8 +393,7 @@ if (ret != 0) { } ``` - -### 释放SDIOä¸æ– +#### 释放SDIOä¸æ– 通信完æˆä¹‹åŽï¼Œéœ€è¦é‡Šæ”¾SDIOä¸æ–,函数如下所示: @@ -410,8 +410,7 @@ int32_t SdioReleaseIrq(DevHandle handle); 释放SDIOä¸æ–的示例如下: - -``` +```c int32_t ret; /* 释放SDIOä¸æ– */ ret = SdioReleaseIrq(handle); @@ -420,8 +419,7 @@ if (ret != 0) { } ``` - -### 去使能SDIO设备 +#### 去使能SDIO设备 通信完æˆä¹‹åŽï¼Œè¿˜éœ€è¦åŽ»ä½¿èƒ½SDIO设备,函数如下所示: @@ -438,8 +436,7 @@ int32_t SdioDisableFunc(DevHandle handle); 去使能SDIO设备的示例如下: - -``` +```c int32_t ret; /* 去使能SDIO设备 */ ret = SdioDisableFunc(handle); @@ -448,13 +445,11 @@ if (ret != 0) { } ``` - -### 释放HOST +#### 释放HOST 通信完æˆä¹‹åŽï¼Œè¿˜éœ€è¦é‡Šæ”¾åŽ»HOST,函数如下所示: - -``` +```c void SdioReleaseHost(DevHandle handle); ``` @@ -466,18 +461,15 @@ void SdioReleaseHost(DevHandle handle); 释放HOST的示例如下: - -``` +```c SdioReleaseHost(handle); /* 释放HOST */ ``` - -### å…³é—SDIO控制器 +#### å…³é—SDIO控制器 SDIO通信完æˆä¹‹åŽï¼Œæœ€åŽéœ€è¦å…³é—SDIO控制器,函数如下所示: - -``` +```c void SdioClose(DevHandle handle); ``` @@ -491,17 +483,17 @@ void SdioClose(DevHandle handle); å…³é—SDIO控制器的示例如下: - -``` +```c SdioClose(handle); /* å…³é—SDIO控制器 */ ``` +### 使用实例 -## 使用实例 +本例拟对Hi3516DV300å¼€å‘æ¿ä¸ŠSDIO设备进行æ“作。 - SDIO设备完整的使用示例如下所示,首先打开总线å·ä¸º1çš„SDIO控制器,然åŽç‹¬å HOSTã€ä½¿èƒ½è®¾å¤‡ã€æ³¨å†Œä¸æ–,接ç€è¿›è¡ŒSDIO通信(读写ç‰ï¼‰ï¼Œé€šä¿¡å®Œæˆä¹‹åŽï¼Œé‡Šæ”¾ä¸æ–ã€åŽ»ä½¿èƒ½è®¾å¤‡ã€é‡Šæ”¾HOST,最åŽå…³é—SDIO控制器。 +SDIO设备完整的使用示例如下所示,首先打开总线å·ä¸º1çš„SDIO控制器,然åŽç‹¬å HOSTã€ä½¿èƒ½è®¾å¤‡ã€æ³¨å†Œä¸æ–,接ç€è¿›è¡ŒSDIO通信(读写ç‰ï¼‰ï¼Œé€šä¿¡å®Œæˆä¹‹åŽï¼Œé‡Šæ”¾ä¸æ–ã€åŽ»ä½¿èƒ½è®¾å¤‡ã€é‡Šæ”¾HOST,最åŽå…³é—SDIO控制器。 -``` +```c #include "hdf_log.h" #include "sdio_if.h" @@ -529,7 +521,7 @@ void SdioTestSample(void) struct SdioFunctionConfig config = {1, 0x123, 0x456}; uint8_t val; uint32_t addr; - + /* 打开总线å·ä¸º1çš„SDIO设备 */ handle = SdioOpen(1, &config); if (handle == NULL) { diff --git a/zh-cn/device-dev/driver/driver-platform-sdio-develop.md b/zh-cn/device-dev/driver/driver-platform-sdio-develop.md index bd8a24365c64192e6abc03906022c298eb0df433..b5d7e6205a959a27f5be0d71202e9435a4604043 100755 --- a/zh-cn/device-dev/driver/driver-platform-sdio-develop.md +++ b/zh-cn/device-dev/driver/driver-platform-sdio-develop.md @@ -1,44 +1,64 @@ # SDIO - ## 概述 -SDIO(Secure Digital Input and Output)由SDå¡å‘展而æ¥ï¼Œè¢«ç»Ÿç§°ä¸ºMMC(MultiMediaCard),相关技术差别ä¸å¤§ã€‚在HDF框架ä¸ï¼ŒSDIO的接å£é€‚é…模å¼é‡‡ç”¨ç‹¬ç«‹æœåŠ¡æ¨¡å¼ã€‚在这ç§æ¨¡å¼ä¸‹ï¼Œæ¯ä¸€ä¸ªè®¾å¤‡å¯¹è±¡ä¼šç‹¬ç«‹å‘布一个设备æœåŠ¡æ¥å¤„ç†å¤–部访问,设备管ç†å™¨æ”¶åˆ°API的访问请求之åŽï¼Œé€šè¿‡æå–该请求的å‚数,达到调用实际设备对象的相应内部方法的目的。独立æœåŠ¡æ¨¡å¼å¯ä»¥ç›´æŽ¥å€ŸåŠ©HDFDeviceManagerçš„æœåŠ¡ç®¡ç†èƒ½åŠ›ï¼Œä½†éœ€è¦ä¸ºæ¯ä¸ªè®¾å¤‡å•ç‹¬é…ç½®è®¾å¤‡èŠ‚ç‚¹ï¼Œå¢žåŠ å†…å˜å 用。 +### 功能简介 + +SDIO(Secure Digital Input and Output)由SDå¡å‘展而æ¥ï¼Œä¸ŽSDå¡ç»Ÿç§°ä¸ºMMC(MultiMediaCard),二者使用相åŒçš„通信å议。SDIO接å£å…¼å®¹ä»¥å‰çš„SDå¡ï¼Œå¹¶ä¸”å¯ä»¥è¿žæŽ¥æ”¯æŒSDIO接å£çš„其他设备。 + +### è¿ä½œæœºåˆ¶ + +在HDF框架ä¸ï¼ŒSDIO的接å£é€‚é…模å¼é‡‡ç”¨ç‹¬ç«‹æœåŠ¡æ¨¡å¼ï¼ˆå¦‚图1)。在这ç§æ¨¡å¼ä¸‹ï¼Œæ¯ä¸€ä¸ªè®¾å¤‡å¯¹è±¡ä¼šç‹¬ç«‹å‘布一个设备æœåŠ¡æ¥å¤„ç†å¤–部访问,设备管ç†å™¨æ”¶åˆ°API的访问请求之åŽï¼Œé€šè¿‡æå–该请求的å‚数,达到调用实际设备对象的相应内部方法的目的。独立æœåŠ¡æ¨¡å¼å¯ä»¥ç›´æŽ¥å€ŸåŠ©HDFDeviceManagerçš„æœåŠ¡ç®¡ç†èƒ½åŠ›ï¼Œä½†éœ€è¦ä¸ºæ¯ä¸ªè®¾å¤‡å•ç‹¬é…置设备节点,若设备过多å¯èƒ½å¢žåŠ 内å˜å 用。 + +独立æœåŠ¡æ¨¡å¼ä¸‹ï¼Œæ ¸å¿ƒå±‚ä¸ä¼šç»Ÿä¸€å‘布一个æœåŠ¡ä¾›ä¸Šå±‚ä½¿ç”¨ï¼Œå› æ¤è¿™ç§æ¨¡å¼ä¸‹é©±åŠ¨è¦ä¸ºæ¯ä¸ªæŽ§åˆ¶å™¨å‘布一个æœåŠ¡ï¼Œå…·ä½“表现为: + +- 驱动适é…者需è¦å®žçŽ°HdfDriverEntryçš„Bindé’©å函数以绑定æœåŠ¡ã€‚ +- device_info.hcs文件ä¸deviceNodeçš„policyå—段为1或2,ä¸èƒ½ä¸º0。 + +**图1** SDIO独立æœåŠ¡æ¨¡å¼ç»“构图<a name="fig1"></a> + + + +### 约æŸä¸Žé™åˆ¶ - **图1** SDIO独立æœåŠ¡æ¨¡å¼ç»“构图 +SDIO模å—API当å‰ä»…支æŒå†…æ ¸æ€è°ƒç”¨ã€‚ -  +## å¼€å‘指导 +### åœºæ™¯ä»‹ç» -## 接å£è¯´æ˜Ž +SDIO的应用比较广泛,目å‰ï¼Œæœ‰è®¸å¤šæ‰‹æœºéƒ½æ”¯æŒSDIO功能,并且很多SDIO外设也被开å‘出æ¥ï¼Œä½¿å¾—æ‰‹æœºå¤–æŽ¥å¤–è®¾æ›´åŠ å®¹æ˜“ã€‚å¸¸è§çš„SDIO外设有WLANã€GPSã€CAMERAã€è“牙ç‰ã€‚当驱动开å‘者需è¦å°†SDIO设备适é…到OpenHarmony时,需è¦è¿›è¡ŒSDIO驱动适é…,下文将介ç»å¦‚何进行SDIO驱动适é…。 + +### 接å£è¯´æ˜Ž + +为了ä¿è¯ä¸Šå±‚在调用SDIO接å£æ—¶èƒ½å¤Ÿæ£ç¡®çš„æ“ä½œç¡¬ä»¶ï¼Œæ ¸å¿ƒå±‚åœ¨//drivers/hdf_core/framework/model/storage/include/mmc//mmc_sdio.hä¸å®šä¹‰äº†ä»¥ä¸‹é’©å函数。驱动适é…者需è¦åœ¨é€‚é…层实现这些函数的具体功能,并与这些钩å函数挂接,从而完æˆæŽ¥å£å±‚ä¸Žæ ¸å¿ƒå±‚çš„äº¤äº’ã€‚ SdioDeviceOps定义: - -``` -// å‡½æ•°æ¨¡æ¿ +```c +/* å‡½æ•°æ¨¡æ¿ */ struct SdioDeviceOps { - int32_t (*incrAddrReadBytes)(struct SdioDevice *dev, uint8_t *data, uint32_t addr, uint32_t size); - int32_t (*incrAddrWriteBytes)(struct SdioDevice *dev, uint8_t *data, uint32_t addr, uint32_t size); - int32_t (*fixedAddrReadBytes)(struct SdioDevice *dev, uint8_t *data, uint32_t addr, uint32_t size, uint32_t scatterLen); - int32_t (*fixedAddrWriteBytes)(struct SdioDevice *dev, uint8_t *data, uint32_t addr, uint32_t size, uint32_t scatterLen); - int32_t (*func0ReadBytes)(struct SdioDevice *dev, uint8_t *data, uint32_t addr, uint32_t size); - int32_t (*func0WriteBytes)(struct SdioDevice *dev, uint8_t *data, uint32_t addr, uint32_t size); - int32_t (*setBlockSize)(struct SdioDevice *dev, uint32_t blockSize); - int32_t (*getCommonInfo)(struct SdioDevice *dev, SdioCommonInfo *info, uint32_t infoType); - int32_t (*setCommonInfo)(struct SdioDevice *dev, SdioCommonInfo *info, uint32_t infoType); - int32_t (*flushData)(struct SdioDevice *dev); - int32_t (*enableFunc)(struct SdioDevice *dev); - int32_t (*disableFunc)(struct SdioDevice *dev); - int32_t (*claimIrq)(struct SdioDevice *dev, SdioIrqHandler *irqHandler); - int32_t (*releaseIrq)(struct SdioDevice *dev); - int32_t (*findFunc)(struct SdioDevice *dev, struct SdioFunctionConfig *configData); - int32_t (*claimHost)(struct SdioDevice *dev); - int32_t (*releaseHost)(struct SdioDevice *dev); + int32_t (*incrAddrReadBytes)(struct SdioDevice *dev, uint8_t *data, uint32_t addr, uint32_t size); + int32_t (*incrAddrWriteBytes)(struct SdioDevice *dev, uint8_t *data, uint32_t addr, uint32_t size); + int32_t (*fixedAddrReadBytes)(struct SdioDevice *dev, uint8_t *data, uint32_t addr, uint32_t size, uint32_t scatterLen); + int32_t (*fixedAddrWriteBytes)(struct SdioDevice *dev, uint8_t *data, uint32_t addr, uint32_t size, uint32_t scatterLen); + int32_t (*func0ReadBytes)(struct SdioDevice *dev, uint8_t *data, uint32_t addr, uint32_t size); + int32_t (*func0WriteBytes)(struct SdioDevice *dev, uint8_t *data, uint32_t addr, uint32_t size); + int32_t (*setBlockSize)(struct SdioDevice *dev, uint32_t blockSize); + int32_t (*getCommonInfo)(struct SdioDevice *dev, SdioCommonInfo *info, uint32_t infoType); + int32_t (*setCommonInfo)(struct SdioDevice *dev, SdioCommonInfo *info, uint32_t infoType); + int32_t (*flushData)(struct SdioDevice *dev); + int32_t (*enableFunc)(struct SdioDevice *dev); + int32_t (*disableFunc)(struct SdioDevice *dev); + int32_t (*claimIrq)(struct SdioDevice *dev, SdioIrqHandler *irqHandler); + int32_t (*releaseIrq)(struct SdioDevice *dev); + int32_t (*findFunc)(struct SdioDevice *dev, struct SdioFunctionConfig *configData); + int32_t (*claimHost)(struct SdioDevice *dev); + int32_t (*releaseHost)(struct SdioDevice *dev); }; ``` - **表1** SdioDeviceOps结构体æˆå‘˜çš„回调函数功能说明 + **表1** SdioDeviceOps结构体æˆå‘˜çš„é’©å函数功能说明 | 函数 | å…¥å‚ | å‡ºå‚ | 返回值 | 功能 | | -------- | -------- | -------- | -------- | -------- | @@ -65,9 +85,9 @@ struct SdioDeviceOps { > CommonInfo包括maxBlockNum(å•ä¸ªrequestä¸æœ€å¤§block数)ã€maxBlockSize(å•ä¸ªblock最大å—节数)ã€maxRequestSize(å•ä¸ªRequest最大å—节数)ã€enTimeout(最大超时时间,毫秒)ã€funcNum(功能编å·1~7)ã€irqCap(IRQ capabilities)ã€(void \*)data。 -## å¼€å‘æ¥éª¤ +### å¼€å‘æ¥éª¤ -SDIO模å—适é…HDF框架的三个必选环节是实例化驱动入å£ï¼Œé…置属性文件,以åŠå¡«å……æ ¸å¿ƒå±‚æŽ¥å£å‡½æ•°ã€‚ +SDIO模å—适é…HDF框架的三个必选环节是实例化驱动入å£ï¼Œé…置属性文件,以åŠå®žä¾‹åŒ–SDIO控制器对象。 1. å®žä¾‹åŒ–é©±åŠ¨å…¥å£ - 实例化HdfDriverEntry结构体æˆå‘˜ã€‚ @@ -87,10 +107,9 @@ SDIO模å—适é…HDF框架的三个必选环节是实例化驱动入å£ï¼Œé…ç½® ã€å¯é€‰ã€‘针对新增驱动程åºï¼Œå»ºè®®éªŒè¯é©±åŠ¨åŸºæœ¬åŠŸèƒ½ï¼Œä¾‹å¦‚SDIO控制状æ€ï¼Œä¸æ–å“应情况ç‰ã€‚ +### å¼€å‘实例 -## å¼€å‘实例 - -下方将以sdio_adapter.c为示例,展示需è¦åŽ‚商æ供哪些内容æ¥å®Œæ•´å®žçŽ°è®¾å¤‡åŠŸèƒ½ã€‚ +下方将以sdio_adapter.c为示例,展示需è¦é©±åŠ¨é€‚é…者æ供哪些内容æ¥å®Œæ•´å®žçŽ°è®¾å¤‡åŠŸèƒ½ã€‚ 1. 驱动开å‘首先需è¦å®žä¾‹åŒ–驱动入å£ã€‚ @@ -101,77 +120,83 @@ SDIO模å—适é…HDF框架的三个必选环节是实例化驱动入å£ï¼Œé…ç½® ä¸€èˆ¬åœ¨åŠ è½½é©±åŠ¨æ—¶HDF会先调用Bind函数,å†è°ƒç”¨Initå‡½æ•°åŠ è½½è¯¥é©±åŠ¨ã€‚å½“Init调用异常时,HDF框架会调用Release释放驱动资æºå¹¶é€€å‡ºã€‚ SDIO 驱动入å£å‚考: - - ``` + + ```c struct HdfDriverEntry g_sdioDriverEntry = { .moduleVersion = 1, - .Bind = Hi35xxLinuxSdioBind, // è§Bindå‚考 - .Init = Hi35xxLinuxSdioInit, // è§Initå‚考 - .Release = Hi35xxLinuxSdioRelease,// è§Releaseå‚考 - .moduleName = "HDF_PLATFORM_SDIO",// ã€å¿…è¦ä¸”与HCS文件ä¸é‡Œé¢çš„moduleName匹é…】 + .Bind = Hi35xxLinuxSdioBind, // è§Bindå¼€å‘å‚考 + .Init = Hi35xxLinuxSdioInit, // è§Initå¼€å‘å‚考 + .Release = Hi35xxLinuxSdioRelease, // è§Releaseå¼€å‘å‚考 + .moduleName = "HDF_PLATFORM_SDIO", // ã€å¿…è¦ä¸”与HCS文件ä¸é‡Œé¢çš„moduleName匹é…】 }; - // 调用HDF_INIT将驱动入å£æ³¨å†Œåˆ°HDFæ¡†æž¶ä¸ + /* 调用HDF_INIT将驱动入å£æ³¨å†Œåˆ°HDFæ¡†æž¶ä¸ */ HDF_INIT(g_sdioDriverEntry); ``` -2. 完æˆé©±åŠ¨å…¥å£æ³¨å†Œä¹‹åŽï¼Œä¸‹ä¸€æ¥è¯·åœ¨device_info.hcs文件ä¸æ·»åŠ deviceNodeä¿¡æ¯ï¼Œå¹¶åœ¨sdio_config.hcsä¸é…置器件属性。 +2. 完æˆé©±åŠ¨å…¥å£æ³¨å†Œä¹‹åŽï¼Œä¸‹ä¸€æ¥è¯·åœ¨//vendor/hisilicon/hispark_taurus/hdf_config/device_info/device_info.hcs文件ä¸æ·»åŠ deviceNodeä¿¡æ¯ï¼Œå¹¶åœ¨sdio_config.hcsä¸é…置器件属性。 deviceNodeä¿¡æ¯ä¸Žé©±åŠ¨å…¥å£æ³¨å†Œç›¸å…³ï¼Œå™¨ä»¶å±žæ€§å€¼ä¸Žæ ¸å¿ƒå±‚SdioDeviceæˆå‘˜çš„默认值或é™åˆ¶èŒƒå›´æœ‰å¯†åˆ‡å…³ç³»ã€‚ - 本例åªæœ‰ä¸€ä¸ªSDIO控制器,如有多个器件信æ¯ï¼Œåˆ™éœ€è¦åœ¨device_infoæ–‡ä»¶å¢žåŠ deviceNodeä¿¡æ¯ï¼Œä»¥åŠåœ¨sdio_config文件ä¸å¢žåŠ 对应的器件属性。 + 本例åªæœ‰ä¸€ä¸ªSDIO控制器,如有多个器件信æ¯ï¼Œåˆ™éœ€è¦åœ¨device_info.hcsæ–‡ä»¶å¢žåŠ deviceNodeä¿¡æ¯ï¼Œä»¥åŠåœ¨sdio_config文件ä¸å¢žåŠ 对应的器件属性。 - device_info.hcs é…ç½®å‚考: - - - ``` + + ```c root { - device_info { - match_attr = "hdf_manager"; - platform :: host { - hostName = "platform_host"; - priority = 50; - device_sdio :: device { - device0 :: deviceNode { - policy = 1; - priority = 70; - permission = 0644; - moduleName = "HDF_PLATFORM_SDIO"; // ã€å¿…è¦ã€‘用于指定驱动å称,需è¦ä¸Žé©±åŠ¨Entryä¸çš„moduleName一致。 - serviceName = "HDF_PLATFORM_MMC_2"; // ã€å¿…è¦ã€‘驱动对外å‘布æœåŠ¡çš„å称,必须唯一。 - deviceMatchAttr = "hisilicon_hi35xx_sdio_0";// ã€å¿…è¦ã€‘用于é…置控制器ç§æœ‰æ•°æ®ï¼Œè¦ä¸Žsdio_config.hcsä¸å¯¹åº”控制器ä¿æŒä¸€è‡´ã€‚ + device_info { + match_attr = "hdf_manager"; + platform :: host { + hostName = "platform_host"; + priority = 50; + device_sdio :: device { + device0 :: deviceNode { + policy = 1; + priority = 70; + permission = 0644; + moduleName = "HDF_PLATFORM_SDIO"; // ã€å¿…è¦ã€‘用于指定驱动å称,需è¦ä¸Žé©±åŠ¨Entryä¸çš„moduleName一致。 + serviceName = "HDF_PLATFORM_MMC_2"; // ã€å¿…è¦ã€‘驱动对外å‘布æœåŠ¡çš„å称,必须唯一。 + deviceMatchAttr = "hisilicon_hi35xx_sdio_0"; // ã€å¿…è¦ã€‘用于é…置控制器ç§æœ‰æ•°æ®ï¼Œè¦ä¸Žsdio_config.hcsä¸å¯¹åº”控制器ä¿æŒä¸€è‡´ã€‚ + } + } } - } } - } } ``` - + - sdio_config.hcs é…ç½®å‚考: - ``` + ```c root { - platform { - sdio_config { - template sdio_controller { - match_attr = ""; - hostId = 2; // ã€å¿…è¦ã€‘模å¼å›ºå®šä¸º2,在mmc_config.hcs有介ç»ã€‚ - devType = 2; // ã€å¿…è¦ã€‘模å¼å›ºå®šä¸º2,在mmc_config.hcs有介ç»ã€‚ - } - controller_0x2dd1 :: sdio_controller { - match_attr = "hisilicon_hi35xx_sdio_0";// ã€å¿…è¦ã€‘需è¦å’Œdevice_info.hcsä¸çš„deviceMatchAttr值一致。 + platform { + sdio_config { + template sdio_controller { + match_attr = ""; + hostId = 2; // ã€å¿…è¦ã€‘模å¼å›ºå®šä¸º2,在mmc_config.hcs有介ç»ã€‚ + devType = 2; // ã€å¿…è¦ã€‘模å¼å›ºå®šä¸º2,在mmc_config.hcs有介ç»ã€‚ + } + controller_0x2dd1 :: sdio_controller { + match_attr = "hisilicon_hi35xx_sdio_0"; // ã€å¿…è¦ã€‘需è¦å’Œdevice_info.hcsä¸çš„deviceMatchAttr值一致。 + } } - } } ``` -3. 完æˆå±žæ€§æ–‡ä»¶é…置之åŽï¼Œä¸‹ä¸€æ¥å°±æ˜¯ä»¥æ ¸å¿ƒå±‚SdioDevice对象的åˆå§‹åŒ–ä¸ºæ ¸å¿ƒï¼ŒåŒ…æ‹¬åŽ‚å•†è‡ªå®šä¹‰ç»“æž„ä½“ï¼ˆä¼ é€’å‚数和数æ®ï¼‰ï¼Œå®žä¾‹åŒ–SdioDeviceæˆå‘˜SdioDeviceOps(让用户å¯ä»¥é€šè¿‡æŽ¥å£æ¥è°ƒç”¨é©±åŠ¨åº•å±‚函数),实现HdfDriverEntryæˆå‘˜å‡½æ•°ï¼ˆBindã€Initã€Release)。 + 需è¦æ³¨æ„的是,新增sdio_config.hcsé…置文件åŽï¼Œå¿…须在hdf.hcs文件ä¸å°†å…¶åŒ…å«ï¼Œå¦åˆ™é…ç½®æ–‡ä»¶æ— æ³•ç”Ÿæ•ˆã€‚ + + 例如:本例ä¸sdio_config.hcs所在路径为device/soc/hisilicon/hi3516dv300/sdk_liteos/hdf_config/sdio/sdio_config.hcs,则必须在产å“对应的hdf.hcsä¸æ·»åŠ 如下è¯å¥ï¼š + + ```c + #include "../../../../device/soc/hisilicon/hi3516dv300/sdk_liteos/hdf_config/sdio/sdio_config.hcs" // é…置文件相对路径 + ``` + +3. 完æˆå±žæ€§æ–‡ä»¶é…置之åŽï¼Œä¸‹ä¸€æ¥å°±æ˜¯ä»¥æ ¸å¿ƒå±‚SdioDevice对象的åˆå§‹åŒ–ä¸ºæ ¸å¿ƒï¼ŒåŒ…æ‹¬é©±åŠ¨é€‚é…è€…è‡ªå®šä¹‰ç»“æž„ä½“ï¼ˆä¼ é€’å‚数和数æ®ï¼‰ï¼Œå®žä¾‹åŒ–SdioDeviceæˆå‘˜SdioDeviceOps(让用户å¯ä»¥é€šè¿‡æŽ¥å£æ¥è°ƒç”¨é©±åŠ¨åº•å±‚函数),实现HdfDriverEntryæˆå‘˜å‡½æ•°ï¼ˆBindã€Initã€Release)。 - 自定义结构体å‚考: 从驱动的角度看,自定义结构体是å‚数和数æ®çš„载体,而且sdio_config.hcs文件ä¸çš„数值会被HDF读入并通过DeviceResourceIfaceæ¥åˆå§‹åŒ–结构体æˆå‘˜ï¼Œä¸€äº›é‡è¦æ•°å€¼ä¹Ÿä¼šä¼ é€’ç»™æ ¸å¿ƒå±‚å¯¹è±¡ã€‚ - - ``` + ```c typedef struct { uint32_t maxBlockNum; // å•ä¸ªrequest最大的block个数 uint32_t maxBlockSize; // å•ä¸ªblock最大的å—节数1~2048 @@ -182,7 +207,7 @@ SDIO模å—适é…HDF框架的三个必选环节是实例化驱动入å£ï¼Œé…ç½® void *data; // ç§æœ‰æ•°æ® } SdioFuncInfo; - // SdioDeviceæ˜¯æ ¸å¿ƒå±‚æŽ§åˆ¶å™¨ç»“æž„ä½“ï¼Œå…¶ä¸çš„æˆå‘˜åœ¨Bind函数ä¸ä¼šè¢«èµ‹å€¼ã€‚ + /* SdioDeviceæ˜¯æ ¸å¿ƒå±‚æŽ§åˆ¶å™¨ç»“æž„ä½“ï¼Œå…¶ä¸çš„æˆå‘˜åœ¨Bind函数ä¸ä¼šè¢«èµ‹å€¼ã€‚ */ struct SdioDevice { struct SdDevice sd; struct SdioDeviceOps *sdioOps; @@ -190,17 +215,16 @@ SDIO模å—适é…HDF框架的三个必选环节是实例化驱动入å£ï¼Œé…ç½® uint32_t functions; struct SdioFunction *sdioFunc[SDIO_MAX_FUNCTION_NUMBER]; struct SdioFunction *curFunction; - struct OsalThread thread; /* irq thread */ + struct OsalThread thread; // ä¸æ–线程 struct OsalSem sem; bool irqPending; bool threadRunning; }; ``` - - SdioDeviceæˆå‘˜å›žè°ƒå‡½æ•°ç»“构体SdioDeviceOps的实例化,其他æˆå‘˜åœ¨Init函数ä¸åˆå§‹åŒ–。 + - SdioDeviceæˆå‘˜é’©å函数结构体SdioDeviceOps的实例化,其他æˆå‘˜åœ¨Init函数ä¸åˆå§‹åŒ–。 - - ``` + ```c static struct SdioDeviceOps g_sdioDeviceOps = { .incrAddrReadBytes = Hi35xxLinuxSdioIncrAddrReadBytes, .incrAddrWriteBytes = Hi35xxLinuxSdioIncrAddrWriteBytes, @@ -221,15 +245,16 @@ SDIO模å—适é…HDF框架的三个必选环节是实例化驱动入å£ï¼Œé…ç½® .releaseHost = Hi35xxLinuxSdioReleaseHost, }; ``` - - Bind函数å‚考 + + - Bind函数开å‘å‚考 å…¥å‚: - HdfDeviceObject是整个驱动对外暴露的接å£å‚数,具备HCSé…置文件的信æ¯ã€‚ + HdfDeviceObject是整个驱动对外æ供的接å£å‚数,具备HCSé…置文件的信æ¯ã€‚ 返回值: - HDF_STATUS相关状æ€ï¼ˆä¸‹è¡¨ä¸ºéƒ¨åˆ†å±•ç¤ºï¼Œå¦‚需使用其他状æ€ï¼Œå¯è§//drivers/framework/include/utils/hdf_base.hä¸HDF_STATUS 定义)。 + HDF_STATUS相关状æ€ï¼ˆä¸‹è¡¨ä¸ºéƒ¨åˆ†å±•ç¤ºï¼Œå¦‚需使用其他状æ€ï¼Œå¯è§//drivers/hdf_core/framework/include/utils/hdf_base.hä¸HDF_STATUS 定义)。 **表2** Bind函数入å‚åŠè¿”回值 @@ -244,10 +269,10 @@ SDIO模å—适é…HDF框架的三个必选环节是实例化驱动入å£ï¼Œé…ç½® 函数说明: - åˆå§‹åŒ–自定义结构体对象,åˆå§‹åŒ–SdioCntlræˆå‘˜ï¼Œè°ƒç”¨æ ¸å¿ƒå±‚SdioCntlrAdd函数,以åŠå…¶ä»–厂商自定义åˆå§‹åŒ–æ“作。 + åˆå§‹åŒ–自定义结构体对象,åˆå§‹åŒ–SdioCntlræˆå‘˜ï¼Œè°ƒç”¨æ ¸å¿ƒå±‚SdioCntlrAdd函数,以åŠå…¶ä»–驱动适é…者自定义åˆå§‹åŒ–æ“作。 - ``` + ```c static int32_t Hi35xxLinuxSdioBind(struct HdfDeviceObject *obj) { struct MmcCntlr *cntlr = NULL; @@ -277,11 +302,11 @@ SDIO模å—适é…HDF框架的三个必选环节是实例化驱动入å£ï¼Œé…ç½® } ``` - - Init函数å‚考 + - Init函数开å‘å‚考 å…¥å‚: - HdfDeviceObject是整个驱动对外暴露的接å£å‚数,具备HCSé…置文件的信æ¯ã€‚ + HdfDeviceObject是整个驱动对外æ供的接å£å‚数,具备HCSé…置文件的信æ¯ã€‚ 返回值: @@ -289,22 +314,22 @@ SDIO模å—适é…HDF框架的三个必选环节是实例化驱动入å£ï¼Œé…ç½® 函数说明: - æ— æ“作,å¯æ ¹æ®åŽ‚商需è¦æ·»åŠ 。 + æ— æ“作,å¯æ ¹æ®é©±åŠ¨é€‚é…者需è¦æ·»åŠ 。 - ``` + ```c static int32_t Hi35xxLinuxSdioInit(struct HdfDeviceObject *obj) { - (void)obj;// æ— æ“作,å¯æ ¹æ®åŽ‚商需è¦æ·»åŠ + (void)obj; // æ— æ“作,å¯æ ¹æ®é©±åŠ¨é€‚é…者的需è¦è¿›è¡Œæ·»åŠ HDF_LOGD("Hi35xxLinuxSdioInit: Success!"); return HDF_SUCCESS; } ``` - - Release函数å‚考 + - Release函数开å‘å‚考 å…¥å‚: - HdfDeviceObject是整个驱动对外暴露的接å£å‚数,具备HCSé…置文件的信æ¯ã€‚ + HdfDeviceObject是整个驱动对外æ供的接å£å‚数,具备HCSé…置文件的信æ¯ã€‚ 返回值: @@ -317,12 +342,12 @@ SDIO模å—适é…HDF框架的三个必选环节是实例化驱动入å£ï¼Œé…ç½® >  **说明:**<br> > 所有强制转æ¢èŽ·å–相应对象的æ“作å‰æ是在Bind函数ä¸å…·å¤‡å¯¹åº”赋值的æ“作。 - ``` + ```c static void Hi35xxLinuxSdioRelease(struct HdfDeviceObject *obj) { if (obj == NULL) { return; } - Hi35xxLinuxSdioDeleteCntlr((struct MmcCntlr *)obj->service);// ã€å¿…è¦ã€‘自定义的内å˜é‡Šæ”¾å‡½æ•°ï¼Œè¿™é‡Œæœ‰HdfDeviceObject到MmcCntlr的强制转化 + Hi35xxLinuxSdioDeleteCntlr((struct MmcCntlr *)obj->service); // ã€å¿…è¦ã€‘自定义的内å˜é‡Šæ”¾å‡½æ•°ï¼Œè¿™é‡Œæœ‰HdfDeviceObject到MmcCntlrçš„å¼ºåˆ¶è½¬æ¢ } ``` \ No newline at end of file diff --git a/zh-cn/device-dev/driver/driver-platform-spi-des.md b/zh-cn/device-dev/driver/driver-platform-spi-des.md index 79787c85ae86460d349cb0ea0cb55d33729ff6e3..0f5f1f7432a2b3e7d4ad4ab6963ee4bc1a845ee2 100644 --- a/zh-cn/device-dev/driver/driver-platform-spi-des.md +++ b/zh-cn/device-dev/driver/driver-platform-spi-des.md @@ -1,9 +1,20 @@ # SPI - ## 概述 -SPI指串行外设接å£ï¼ˆSerial Peripheral Interface),是一ç§é«˜é€Ÿçš„,全åŒå·¥ï¼ŒåŒæ¥çš„通信总线。SPI是由Motorolaå…¬å¸å¼€å‘,用于在主设备和从设备之间进行通信,常用于与闪å˜ã€å®žæ—¶æ—¶é’Ÿã€ä¼ 感器以åŠæ¨¡æ•°è½¬æ¢å™¨ç‰è¿›è¡Œé€šä¿¡ã€‚ +### 功能简介 + +SPI指串行外设接å£ï¼ˆSerial Peripheral Interface),是一ç§é«˜é€Ÿçš„,全åŒå·¥ï¼ŒåŒæ¥çš„通信总线。SPI是由Motorolaå…¬å¸å¼€å‘,用于在主设备和从设备之间进行通信。 + +SPI接å£å®šä¹‰äº†æ“作SPI设备的通用方法集åˆï¼ŒåŒ…括: + - SPI设备å¥æŸ„获å–和释放。 + - SPI读写:从SPI设备读å–或写入指定长度数æ®ã€‚ + - SPIè‡ªå®šä¹‰ä¼ è¾“ï¼šé€šè¿‡æ¶ˆæ¯ä¼ 输结构体执行任æ„读写组åˆè¿‡ç¨‹ã€‚ + - SPI设备é…置:获å–和设置SPI设备属性。 + +### è¿ä½œæœºåˆ¶ + +在HDF框架ä¸ï¼ŒSPI的接å£é€‚é…模å¼é‡‡ç”¨ç‹¬ç«‹æœåŠ¡æ¨¡å¼ï¼Œåœ¨è¿™ç§æ¨¡å¼ä¸‹ï¼Œæ¯ä¸€ä¸ªè®¾å¤‡å¯¹è±¡ä¼šç‹¬ç«‹å‘布一个设备æœåŠ¡æ¥å¤„ç†å¤–部访问,设备管ç†å™¨æ”¶åˆ°API的访问请求之åŽï¼Œé€šè¿‡æå–该请求的å‚数,达到调用实际设备对象的相应内部方法的目的。独立æœåŠ¡æ¨¡å¼å¯ä»¥ç›´æŽ¥å€ŸåŠ©HDFDeviceManagerçš„æœåŠ¡ç®¡ç†èƒ½åŠ›ï¼Œä½†éœ€è¦ä¸ºæ¯ä¸ªè®¾å¤‡å•ç‹¬é…置设备节点,若设备过多å¯èƒ½å¢žåŠ 内å˜å 用。 SPI以主从方å¼å·¥ä½œï¼Œé€šå¸¸æœ‰ä¸€ä¸ªä¸»è®¾å¤‡å’Œä¸€ä¸ªæˆ–者多个从设备。主设备和从设备之间一般用4æ ¹çº¿ç›¸è¿žï¼Œå®ƒä»¬åˆ†åˆ«æ˜¯ï¼š - SCLK:时钟信å·ï¼Œç”±ä¸»è®¾å¤‡äº§ç”Ÿï¼› @@ -13,9 +24,9 @@ SPI以主从方å¼å·¥ä½œï¼Œé€šå¸¸æœ‰ä¸€ä¸ªä¸»è®¾å¤‡å’Œä¸€ä¸ªæˆ–者多个从设 一个主设备和两个从设备的连接示æ„图如下所示,Device Aå’ŒDevice B共享主设备的SCLKã€MISOå’ŒMOSIä¸‰æ ¹å¼•è„šï¼ŒDevice A的片选CS0连接主设备的CS0,Device B的片选CS1连接主设备的CS1。 - **图1** SPI主从设备连接示æ„图 +**图1** SPI主从设备连接示æ„图 -  + - SPI通信通常由主设备å‘起,通过以下æ¥éª¤å®Œæˆä¸€æ¬¡é€šä¿¡ï¼š 1. 通过CS选ä¸è¦é€šä¿¡çš„从设备,在任æ„时刻,一个主设备上最多åªèƒ½æœ‰ä¸€ä¸ªä»Žè®¾å¤‡è¢«é€‰ä¸ã€‚ @@ -28,36 +39,31 @@ SPI以主从方å¼å·¥ä½œï¼Œé€šå¸¸æœ‰ä¸€ä¸ªä¸»è®¾å¤‡å’Œä¸€ä¸ªæˆ–者多个从设 - CPOL=1,CPHA=0 时钟信å·idle状æ€ä¸ºé«˜ç”µå¹³ï¼Œç¬¬ä¸€ä¸ªæ—¶é’Ÿè¾¹æ²¿é‡‡æ ·æ•°æ®ã€‚ - CPOL=1,CPHA=1 时钟信å·idle状æ€ä¸ºé«˜ç”µå¹³ï¼Œç¬¬äºŒä¸ªæ—¶é’Ÿè¾¹æ²¿é‡‡æ ·æ•°æ®ã€‚ -- SPI接å£å®šä¹‰äº†æ“作SPI设备的通用方法集åˆï¼ŒåŒ…括: - - SPI设备å¥æŸ„获å–和释放。 - - SPI读写: 从SPI设备读å–或写入指定长度数æ®ã€‚ - - SPIè‡ªå®šä¹‰ä¼ è¾“ï¼šé€šè¿‡æ¶ˆæ¯ä¼ 输结构体执行任æ„读写组åˆè¿‡ç¨‹ã€‚ - - SPI设备é…置:获å–和设置SPI设备属性。 +### 约æŸä¸Žé™åˆ¶ ->  **说明:**<br> -> 当å‰åªæ”¯æŒä¸»æœºæ¨¡å¼ï¼Œä¸æ”¯æŒä»Žæœºæ¨¡å¼ã€‚ +SPI模å—当å‰åªæ”¯æŒä¸»æœºæ¨¡å¼ï¼Œä¸æ”¯æŒä»Žæœºæ¨¡å¼ã€‚ +## 使用指导 -## 接å£è¯´æ˜Ž +### åœºæ™¯ä»‹ç» - **表1** SPI驱动API接å£åŠŸèƒ½ä»‹ç» +SPI通常用于与闪å˜ã€å®žæ—¶æ—¶é’Ÿã€ä¼ 感器以åŠæ¨¡æ•°/数模转æ¢å™¨ç‰æ”¯æŒSPIå议的设备进行通信。 -| 接å£å | 接å£æè¿° | -| -------- | -------- | -| SpiOpen | 获å–SPI设备å¥æŸ„ | -| SpiClose | 释放SPI设备å¥æŸ„ | -| SpiRead | 读å–æŒ‡å®šé•¿åº¦çš„æ•°æ® | -| SpiWrite | å†™å…¥æŒ‡å®šé•¿åº¦çš„æ•°æ® | -| SpiTransfer | SPIæ•°æ®ä¼ è¾“æŽ¥å£ | -| SpiSetCfg | æ ¹æ®æŒ‡å®šå‚数,é…ç½®SPI设备 | -| SpiGetCfg | 获å–SPI设备é…ç½®å‚æ•° | +### 接å£è¯´æ˜Ž ->  **说明:**<br> -> 本文涉åŠçš„所有接å£ï¼Œä»…é™å†…æ ¸æ€ä½¿ç”¨ï¼Œä¸æ”¯æŒåœ¨ç”¨æˆ·æ€ä½¿ç”¨ã€‚ +SPI模å—æ供的主è¦æŽ¥å£å¦‚表1所示,具体API详è§//drivers/hdf_core/framework/include/platform/spi_if.h。 +**表1** SPI驱动API接å£åŠŸèƒ½ä»‹ç» -## 使用指导 - +| 接å£å | 接å£æè¿° | +| -------- | -------- | +| DevHandle SpiOpen(const struct SpiDevInfo \*info) | 获å–SPI设备å¥æŸ„ | +| void SpiClose(DevHandle handle) | 释放SPI设备å¥æŸ„ | +| int32_t SpiRead(DevHandle handle, uint8_t \*buf, uint32_t len) | 读å–æŒ‡å®šé•¿åº¦çš„æ•°æ® | +| int32_t SpiWrite(DevHandle handle, uint8_t \*buf, uint32_t len) | å†™å…¥æŒ‡å®šé•¿åº¦çš„æ•°æ® | +| int32_t SpiTransfer(DevHandle handle, struct SpiMsg \*msgs, uint32_t count) | SPIæ•°æ®ä¼ è¾“æŽ¥å£ | +| int32_t SpiSetCfg(DevHandle handle, struct SpiCfg \*cfg) | æ ¹æ®æŒ‡å®šå‚数,é…ç½®SPI设备 | +| int32_t SpiGetCfg(DevHandle handle, struct SpiCfg \*cfg) | 获å–SPI设备é…ç½®å‚æ•° | ### 使用æµç¨‹ @@ -67,13 +73,11 @@ SPI以主从方å¼å·¥ä½œï¼Œé€šå¸¸æœ‰ä¸€ä¸ªä¸»è®¾å¤‡å’Œä¸€ä¸ªæˆ–者多个从设  - -### 获å–SPI设备å¥æŸ„ +#### 获å–SPI设备å¥æŸ„ 在使用SPI进行通信时,首先è¦è°ƒç”¨SpiOpen获å–SPI设备å¥æŸ„,该函数会返回指定总线å·å’Œç‰‡é€‰å·çš„SPI设备å¥æŸ„。 - -``` +```c DevHandle SpiOpen(const struct SpiDevInfo *info); ``` @@ -88,8 +92,7 @@ DevHandle SpiOpen(const struct SpiDevInfo *info); å‡è®¾ç³»ç»Ÿä¸çš„SPI设备总线å·ä¸º0,片选å·ä¸º0,获å–该SPI设备å¥æŸ„的示例如下: - -``` +```c struct SpiDevInfo spiDevinfo; /* SPI设备æ述符 */ DevHandle spiHandle = NULL; /* SPI设备å¥æŸ„ */ spiDevinfo.busNum = 0; /* SPIè®¾å¤‡æ€»çº¿å· */ @@ -103,13 +106,11 @@ if (spiHandle == NULL) { } ``` - -### 获å–SPI设备属性 +#### 获å–SPI设备属性 在获å–到SPI设备å¥æŸ„之åŽï¼Œéœ€è¦é…ç½®SPI设备属性。é…ç½®SPI设备属性之å‰ï¼Œå¯ä»¥å…ˆèŽ·å–SPI设备属性,获å–SPI设备属性的函数如下所示: - -``` +```c int32_t SpiGetCfg(DevHandle handle, struct SpiCfg *cfg); ``` @@ -123,8 +124,7 @@ int32_t SpiGetCfg(DevHandle handle, struct SpiCfg *cfg); | 0 | 获å–é…ç½®æˆåŠŸ | | è´Ÿæ•° | 获å–é…置失败 | - -``` +```c int32_t ret; struct SpiCfg cfg = {0}; /* SPIé…置信æ¯*/ ret = SpiGetCfg(spiHandle, &cfg); /* 获å–SPI设备属性 */ @@ -133,13 +133,11 @@ if (ret != 0) { } ``` - -### é…ç½®SPI设备属性 +#### é…ç½®SPI设备属性 在获å–到SPI设备å¥æŸ„之åŽï¼Œéœ€è¦é…ç½®SPI设备属性,é…ç½®SPI设备属性的函数如下所示: - -``` +```c int32_t SpiSetCfg(DevHandle handle, struct SpiCfg *cfg); ``` @@ -153,29 +151,26 @@ int32_t SpiSetCfg(DevHandle handle, struct SpiCfg *cfg); | 0 | é…ç½®æˆåŠŸ | | è´Ÿæ•° | é…置失败 | - -``` +```c int32_t ret; struct SpiCfg cfg = {0}; /* SPIé…置信æ¯*/ cfg.mode = SPI_MODE_LOOP; /* 以回环模å¼è¿›è¡Œé€šä¿¡ */ cfg.transferMode = PAL_SPI_POLLING_TRANSFER; /* 以轮询的方å¼è¿›è¡Œé€šä¿¡ */ cfg.maxSpeedHz = 115200; /* æœ€å¤§ä¼ è¾“é¢‘çŽ‡ */ -cfg.bitsPerWord = 8; /* 读写ä½å®½ä¸º8个比特 */ +cfg.bitsPerWord = 8; /* 读写ä½å®½ä¸º8比特 */ ret = SpiSetCfg(spiHandle, &cfg); /* é…ç½®SPI设备属性 */ if (ret != 0) { HDF_LOGE("SpiSetCfg: failed, ret %d\n", ret); } ``` - -### 进行SPI通信 +#### 进行SPI通信 - å‘SPIè®¾å¤‡å†™å…¥æŒ‡å®šé•¿åº¦çš„æ•°æ® å¦‚æžœåªå‘SPI设备写一次数æ®ï¼Œåˆ™å¯ä»¥é€šè¿‡ä»¥ä¸‹å‡½æ•°å®Œæˆï¼š - - ``` + ```c int32_t SpiWrite(DevHandle handle, uint8_t *buf, uint32_t len); ``` @@ -190,8 +185,7 @@ if (ret != 0) { | 0 | 写入æˆåŠŸ | | è´Ÿæ•° | 写入失败 | - - ``` + ```c int32_t ret; uint8_t wbuff[4] = {0x12, 0x34, 0x56, 0x78}; /* å‘SPIè®¾å¤‡å†™å…¥æŒ‡å®šé•¿åº¦çš„æ•°æ® */ @@ -205,8 +199,7 @@ if (ret != 0) { 如果åªè¯»å–一次数æ®ï¼Œåˆ™å¯ä»¥é€šè¿‡ä»¥ä¸‹å‡½æ•°å®Œæˆï¼š - - ``` + ```c int32_t SpiRead(DevHandle handle, uint8_t *buf, uint32_t len); ``` @@ -221,8 +214,7 @@ if (ret != 0) { | 0 | 读å–æˆåŠŸ | | è´Ÿæ•° | 读å–失败 | - - ``` + ```c int32_t ret; uint8_t rbuff[4] = {0}; /* 从SPI设备读å–æŒ‡å®šé•¿åº¦çš„æ•°æ® */ @@ -236,8 +228,7 @@ if (ret != 0) { 如果需è¦å‘èµ·ä¸€æ¬¡è‡ªå®šä¹‰ä¼ è¾“ï¼Œåˆ™å¯ä»¥é€šè¿‡ä»¥ä¸‹å‡½æ•°å®Œæˆï¼š - - ``` + ```c int32_t SpiTransfer(DevHandle handle, struct SpiMsg *msgs, uint32_t count); ``` @@ -252,8 +243,7 @@ if (ret != 0) { | 0 | 执行æˆåŠŸ | | è´Ÿæ•° | 执行失败 | - - ``` + ```c int32_t ret; uint8_t wbuff[1] = {0x12}; uint8_t rbuff[1] = {0}; @@ -271,13 +261,11 @@ if (ret != 0) { } ``` - -### 销æ¯SPI设备å¥æŸ„ +#### 销æ¯SPI设备å¥æŸ„ SPI通信完æˆä¹‹åŽï¼Œéœ€è¦é”€æ¯SPI设备å¥æŸ„,销æ¯SPI设备å¥æŸ„的函数如下所示: - -``` +```c void SpiClose(DevHandle handle); ``` @@ -289,17 +277,17 @@ void SpiClose(DevHandle handle); | -------- | -------- | | handle | SPI设备å¥æŸ„ | - -``` +```c SpiClose(spiHandle); /* 销æ¯SPI设备å¥æŸ„ */ ``` +### 使用实例 -## 使用实例 +本例拟对Hi3516DV300å¼€å‘æ¿ä¸ŠSPI设备进行æ“作。 - SPI设备完整的使用示例如下所示,首先获å–SPI设备å¥æŸ„,然åŽé…ç½®SPI设备属性,接ç€è°ƒç”¨è¯»å†™æŽ¥å£è¿›è¡Œæ•°æ®ä¼ 输,最åŽé”€æ¯SPI设备å¥æŸ„。 +SPI设备完整的使用示例如下所示,首先获å–SPI设备å¥æŸ„,然åŽé…ç½®SPI设备属性,接ç€è°ƒç”¨è¯»å†™æŽ¥å£è¿›è¡Œæ•°æ®ä¼ 输,最åŽé”€æ¯SPI设备å¥æŸ„。 -``` +```c #include "hdf_log.h" #include "spi_if.h" diff --git a/zh-cn/device-dev/driver/driver-platform-spi-develop.md b/zh-cn/device-dev/driver/driver-platform-spi-develop.md index 5904024e4ca36b0e2babfec72ab0947ee904118c..906e067e5db54c62fc2e59d7e5629d7c6b6cc1ee 100755 --- a/zh-cn/device-dev/driver/driver-platform-spi-develop.md +++ b/zh-cn/device-dev/driver/driver-platform-spi-develop.md @@ -1,30 +1,70 @@ # SPI - ## 概述 -SPIå³ä¸²è¡Œå¤–设接å£ï¼ˆSerial Peripheral Interface)。在HDF框架ä¸ï¼ŒSPI的接å£é€‚é…模å¼é‡‡ç”¨ç‹¬ç«‹æœåŠ¡æ¨¡å¼ï¼Œåœ¨è¿™ç§æ¨¡å¼ä¸‹ï¼Œæ¯ä¸€ä¸ªè®¾å¤‡å¯¹è±¡ä¼šç‹¬ç«‹å‘布一个设备æœåŠ¡æ¥å¤„ç†å¤–部访问,设备管ç†å™¨æ”¶åˆ°API的访问请求之åŽï¼Œé€šè¿‡æå–该请求的å‚数,达到调用实际设备对象的相应内部方法的目的。独立æœåŠ¡æ¨¡å¼å¯ä»¥ç›´æŽ¥å€ŸåŠ©HDFDeviceManagerçš„æœåŠ¡ç®¡ç†èƒ½åŠ›ï¼Œä½†éœ€è¦ä¸ºæ¯ä¸ªè®¾å¤‡å•ç‹¬é…ç½®è®¾å¤‡èŠ‚ç‚¹ï¼Œå¢žåŠ å†…å˜å 用。 +### 功能简介 + +SPIå³ä¸²è¡Œå¤–设接å£ï¼ˆSerial Peripheral Interface),是一ç§é«˜é€Ÿçš„,全åŒå·¥ï¼ŒåŒæ¥çš„通信总线。SPI是由Motorolaå…¬å¸å¼€å‘,用于在主设备和从设备之间进行通信。 + +### è¿ä½œæœºåˆ¶ + +在HDF框架ä¸ï¼ŒSPI的接å£é€‚é…模å¼é‡‡ç”¨ç‹¬ç«‹æœåŠ¡æ¨¡å¼ï¼ˆå¦‚图1),在这ç§æ¨¡å¼ä¸‹ï¼Œæ¯ä¸€ä¸ªè®¾å¤‡å¯¹è±¡ä¼šç‹¬ç«‹å‘布一个设备æœåŠ¡æ¥å¤„ç†å¤–部访问,设备管ç†å™¨æ”¶åˆ°API的访问请求之åŽï¼Œé€šè¿‡æå–该请求的å‚数,达到调用实际设备对象的相应内部方法的目的。独立æœåŠ¡æ¨¡å¼å¯ä»¥ç›´æŽ¥å€ŸåŠ©HDFDeviceManagerçš„æœåŠ¡ç®¡ç†èƒ½åŠ›ï¼Œä½†éœ€è¦ä¸ºæ¯ä¸ªè®¾å¤‡å•ç‹¬é…置设备节点,若设备过多å¯èƒ½å¢žåŠ 内å˜å 用。 + +独立æœåŠ¡æ¨¡å¼ä¸‹ï¼Œæ ¸å¿ƒå±‚ä¸ä¼šç»Ÿä¸€å‘布一个æœåŠ¡ä¾›ä¸Šå±‚ä½¿ç”¨ï¼Œå› æ¤è¿™ç§æ¨¡å¼ä¸‹é©±åŠ¨è¦ä¸ºæ¯ä¸ªæŽ§åˆ¶å™¨å‘布一个æœåŠ¡ï¼Œå…·ä½“表现为: + +- 驱动适é…者需è¦å®žçŽ°HdfDriverEntryçš„Bindé’©å函数以绑定æœåŠ¡ã€‚ +- device_info.hcs文件ä¸deviceNodeçš„policyå—段为1或2,ä¸èƒ½ä¸º0。 + +**图1** SPI独立æœåŠ¡æ¨¡å¼ç»“构图<a name="fig1"></a> + + + +SPI以主从方å¼å·¥ä½œï¼Œé€šå¸¸æœ‰ä¸€ä¸ªä¸»è®¾å¤‡å’Œä¸€ä¸ªæˆ–者多个从设备。主设备和从设备之间一般用4æ ¹çº¿ç›¸è¿žï¼Œå®ƒä»¬åˆ†åˆ«æ˜¯ï¼š + - SCLK:时钟信å·ï¼Œç”±ä¸»è®¾å¤‡äº§ç”Ÿï¼› + - MOSI:主设备数æ®è¾“出,从设备数æ®è¾“入; + - MISO:主设备数æ®è¾“入,从设备数æ®è¾“出; + - CS:片选,从设备使能信å·ï¼Œç”±ä¸»è®¾å¤‡æŽ§åˆ¶ã€‚ + +一个主设备和两个从设备的连接示æ„图如下所示,Device Aå’ŒDevice B共享主设备的SCLKã€MISOå’ŒMOSIä¸‰æ ¹å¼•è„šï¼ŒDevice A的片选CS0连接主设备的CS0,Device B的片选CS1连接主设备的CS1。 + + **图2** SPI主从设备连接示æ„图<a name="fig2"></a> + +  + +- SPI通信通常由主设备å‘起,通过以下æ¥éª¤å®Œæˆä¸€æ¬¡é€šä¿¡ï¼š + 1. 通过CS选ä¸è¦é€šä¿¡çš„从设备,在任æ„时刻,一个主设备上最多åªèƒ½æœ‰ä¸€ä¸ªä»Žè®¾å¤‡è¢«é€‰ä¸ã€‚ + 2. 通过SCLK给选ä¸çš„从设备æ供时钟信å·ã€‚ + 3. 基于SCLK时钟信å·ï¼Œä¸»è®¾å¤‡æ•°æ®é€šè¿‡MOSIå‘é€ç»™ä»Žè®¾å¤‡ï¼ŒåŒæ—¶é€šè¿‡MISO接收从设备å‘é€çš„æ•°æ®ï¼Œå®Œæˆé€šä¿¡ã€‚ + +- æ ¹æ®SCLK时钟信å·çš„CPOL(Clock Polarity,时钟æžæ€§ï¼‰å’ŒCPHA(Clock Phase,时钟相ä½ï¼‰çš„ä¸åŒç»„åˆï¼ŒSPI有以下四ç§å·¥ä½œæ¨¡å¼ï¼š + - CPOL=0,CPHA=0 时钟信å·idle状æ€ä¸ºä½Žç”µå¹³ï¼Œç¬¬ä¸€ä¸ªæ—¶é’Ÿè¾¹æ²¿é‡‡æ ·æ•°æ®ã€‚ + - CPOL=0,CPHA=1 时钟信å·idle状æ€ä¸ºä½Žç”µå¹³ï¼Œç¬¬äºŒä¸ªæ—¶é’Ÿè¾¹æ²¿é‡‡æ ·æ•°æ®ã€‚ + - CPOL=1,CPHA=0 时钟信å·idle状æ€ä¸ºé«˜ç”µå¹³ï¼Œç¬¬ä¸€ä¸ªæ—¶é’Ÿè¾¹æ²¿é‡‡æ ·æ•°æ®ã€‚ + - CPOL=1,CPHA=1 时钟信å·idle状æ€ä¸ºé«˜ç”µå¹³ï¼Œç¬¬äºŒä¸ªæ—¶é’Ÿè¾¹æ²¿é‡‡æ ·æ•°æ®ã€‚ + +## å¼€å‘指导 - **图1** SPI独立æœåŠ¡æ¨¡å¼ç»“构图 +### åœºæ™¯ä»‹ç» -  +SPI通常用于与闪å˜ã€å®žæ—¶æ—¶é’Ÿã€ä¼ 感器以åŠæ¨¡æ•°/数模转æ¢å™¨ç‰æ”¯æŒSPIå议的设备进行通信。当驱动开å‘者需è¦å°†SPI设备适é…到OpenHarmony时,需è¦è¿›è¡ŒSPI驱动适é…,下文将介ç»å¦‚何进行SPI驱动适é…。 -## 接å£è¯´æ˜Ž +### 接å£è¯´æ˜Ž + +为了ä¿è¯ä¸Šå±‚在调用SPI接å£æ—¶èƒ½å¤Ÿæ£ç¡®çš„æ“ä½œç¡¬ä»¶ï¼Œæ ¸å¿ƒå±‚åœ¨//drivers/hdf_core/framework/support/platform/include/spi/spi_core.hä¸å®šä¹‰äº†ä»¥ä¸‹é’©å函数。驱动适é…者需è¦åœ¨é€‚é…层实现这些函数的具体功能,并与这些钩å函数挂接,从而完æˆæŽ¥å£å±‚ä¸Žæ ¸å¿ƒå±‚çš„äº¤äº’ã€‚ SpiCntlrMethod定义: - -``` +```c struct SpiCntlrMethod { - int32_t (*GetCfg)(struct SpiCntlr *cntlr, struct SpiCfg *cfg); - int32_t (*SetCfg)(struct SpiCntlr *cntlr, struct SpiCfg *cfg); - int32_t (*Transfer)(struct SpiCntlr *cntlr, struct SpiMsg *msg, uint32_t count); - int32_t (*Open)(struct SpiCntlr *cntlr); - int32_t (*Close)(struct SpiCntlr *cntlr); + int32_t (*GetCfg)(struct SpiCntlr *cntlr, struct SpiCfg *cfg); + int32_t (*SetCfg)(struct SpiCntlr *cntlr, struct SpiCfg *cfg); + int32_t (*Transfer)(struct SpiCntlr *cntlr, struct SpiMsg *msg, uint32_t count); + int32_t (*Open)(struct SpiCntlr *cntlr); + int32_t (*Close)(struct SpiCntlr *cntlr); }; ``` - **表1** SpiCntlrMethod结构体æˆå‘˜çš„回调函数功能说明 + **表1** SpiCntlrMethod结构体æˆå‘˜çš„é’©å函数功能说明 | æˆå‘˜å‡½æ•° | å…¥å‚ | 返回值 | 功能 | | -------- | -------- | -------- | -------- | @@ -35,7 +75,7 @@ struct SpiCntlrMethod { | Close | cntlrï¼šç»“æž„ä½“æŒ‡é’ˆï¼Œæ ¸å¿ƒå±‚SPI控制器。 | HDF_STATUSç›¸å…³çŠ¶æ€ | å…³é—SPI | -## å¼€å‘æ¥éª¤ +### å¼€å‘æ¥éª¤ SPI模å—适é…HDF框架的三个必选环节是实例化驱动入å£ï¼Œé…置属性文件,以åŠå®žä¾‹åŒ–æ ¸å¿ƒå±‚æŽ¥å£å‡½æ•°ã€‚ @@ -57,10 +97,9 @@ SPI模å—适é…HDF框架的三个必选环节是实例化驱动入å£ï¼Œé…ç½® ã€å¯é€‰ã€‘针对新增驱动程åºï¼Œå»ºè®®éªŒè¯é©±åŠ¨åŸºæœ¬åŠŸèƒ½ï¼Œä¾‹å¦‚SPI控制状æ€ï¼Œä¸æ–å“应情况ç‰ã€‚ +### å¼€å‘实例 -## å¼€å‘实例 - -下方将以spi_hi35xx.c为示例,展示需è¦åŽ‚商æ供哪些内容æ¥å®Œæ•´å®žçŽ°è®¾å¤‡åŠŸèƒ½ã€‚ +下方将以//device/soc/hisilicon/common/platform/spi/spi_hi35xx.c为示例,展示需è¦é©±åŠ¨é€‚é…者æ供哪些内容æ¥å®Œæ•´å®žçŽ°è®¾å¤‡åŠŸèƒ½ã€‚ 1. 首先需è¦å®žä¾‹åŒ–驱动入å£ã€‚ @@ -71,162 +110,169 @@ SPI模å—适é…HDF框架的三个必选环节是实例化驱动入å£ï¼Œé…ç½® ä¸€èˆ¬åœ¨åŠ è½½é©±åŠ¨æ—¶HDF会先调用Bind函数,å†è°ƒç”¨Initå‡½æ•°åŠ è½½è¯¥é©±åŠ¨ã€‚å½“Init调用异常时,HDF框架会调用Release释放驱动资æºå¹¶é€€å‡ºã€‚ SPI驱动入å£å‚考: - - ``` + + ```c struct HdfDriverEntry g_hdfSpiDevice = { .moduleVersion = 1, - .moduleName = "HDF_PLATFORM_SPI",//ã€å¿…è¦ä¸”与HCS文件ä¸é‡Œé¢çš„moduleName匹é…】 - .Bind = HdfSpiDeviceBind, //è§Bindå‚考 - .Init = HdfSpiDeviceInit, //è§Initå‚考 - .Release = HdfSpiDeviceRelease, //è§Releaseå‚考 + .moduleName = "HDF_PLATFORM_SPI", //ã€å¿…è¦ä¸”与HCS文件ä¸é‡Œé¢çš„moduleName匹é…】 + .Bind = HdfSpiDeviceBind, //è§Bindå¼€å‘å‚考 + .Init = HdfSpiDeviceInit, //è§Initå¼€å‘å‚考 + .Release = HdfSpiDeviceRelease, //è§Releaseå¼€å‘å‚考 }; - // 调用HDF_INIT将驱动入å£æ³¨å†Œåˆ°HDFæ¡†æž¶ä¸ + /* 调用HDF_INIT将驱动入å£æ³¨å†Œåˆ°HDFæ¡†æž¶ä¸ */ HDF_INIT(g_hdfSpiDevice); ``` -2. 完æˆé©±åŠ¨å…¥å£æ³¨å†Œä¹‹åŽï¼Œåœ¨device_info.hcs文件ä¸æ·»åŠ deviceNodeä¿¡æ¯ï¼Œå¹¶åœ¨spi_config.hcsä¸é…置器件属性。 +2. 完æˆé©±åŠ¨å…¥å£æ³¨å†Œä¹‹åŽï¼Œåœ¨//vendor/hisilicon/hispark_taurus/hdf_config/device_info/device_info.hcs文件ä¸æ·»åŠ deviceNodeä¿¡æ¯ï¼Œå¹¶åœ¨spi_config.hcsä¸é…置器件属性。 deviceNodeä¿¡æ¯ä¸Žé©±åŠ¨å…¥å£æ³¨å†Œç›¸å…³ï¼Œå™¨ä»¶å±žæ€§å€¼ä¸Žæ ¸å¿ƒå±‚SpiCntlræˆå‘˜çš„默认值或é™åˆ¶èŒƒå›´æœ‰å¯†åˆ‡å…³ç³»ã€‚ - 本例åªæœ‰ä¸€ä¸ªSPI控制器,如有多个器件信æ¯ï¼Œåˆ™éœ€è¦åœ¨device_infoæ–‡ä»¶å¢žåŠ deviceNodeä¿¡æ¯ï¼Œä»¥åŠåœ¨spi_config文件ä¸å¢žåŠ 对应的器件属性。 + 本例åªæœ‰ä¸€ä¸ªSPI控制器,如有多个器件信æ¯ï¼Œåˆ™éœ€è¦åœ¨device_info.hcsæ–‡ä»¶å¢žåŠ deviceNodeä¿¡æ¯ï¼Œä»¥åŠåœ¨spi_config文件ä¸å¢žåŠ 对应的器件属性。 - device_info.hcsé…ç½®å‚考 - - - ``` + + ```c root { - device_info { - match_attr = "hdf_manager"; - platform :: host { - hostName = "platform_host"; - priority = 50; - device_spi :: device { //为æ¯ä¸€ä¸ªSPI控制器é…置一个HDF设备节点 - device0 :: deviceNode { - policy = 1; - priority = 60; - permission = 0644; - moduleName = "HDF_PLATFORM_SPI"; - serviceName = "HDF_PLATFORM_SPI_0"; - deviceMatchAttr = "hisilicon_hi35xx_spi_0"; + device_info { + match_attr = "hdf_manager"; + platform :: host { + hostName = "platform_host"; + priority = 50; + device_spi :: device { //为æ¯ä¸€ä¸ªSPI控制器é…置一个HDF设备节点 + device0 :: deviceNode { + policy = 2; + priority = 60; + permission = 0644; + moduleName = "HDF_PLATFORM_SPI"; + serviceName = "HDF_PLATFORM_SPI_0"; + deviceMatchAttr = "hisilicon_hi35xx_spi_0"; + } + device1 :: deviceNode { + policy = 2; + priority = 60; + permission = 0644; + moduleName = "HDF_PLATFORM_SPI"; // ã€å¿…è¦ã€‘用于指定驱动å称,该å—段的值必须和驱动入å£ç»“æž„çš„moduleName值一致。 + serviceName = "HDF_PLATFORM_SPI_1"; // ã€å¿…è¦ä¸”唯一】驱动对外å‘布æœåŠ¡çš„å称。 + deviceMatchAttr = "hisilicon_hi35xx_spi_1"; // 需è¦ä¸Žspi_config.hcsé…置文件ä¸çš„match_attr匹é…。 + } + ... + } } - device1 :: deviceNode { - policy = 1; - priority = 60; - permission = 0644; - moduleName = "HDF_PLATFORM_SPI"; // ã€å¿…è¦ã€‘用于指定驱动å称,该å—段的值必须和驱动入å£ç»“æž„çš„moduleName值一致。 - serviceName = "HDF_PLATFORM_SPI_1"; // ã€å¿…è¦ä¸”唯一】驱动对外å‘布æœåŠ¡çš„å称。 - deviceMatchAttr = "hisilicon_hi35xx_spi_1"; // 需è¦ä¸Žè®¾å¤‡hcs文件ä¸çš„match_attr匹é…。 - } - ... - } } - } } ``` - spi_config.hcsé…ç½®å‚考 - ``` + ```c root { - platform { - spi_config { // æ¯ä¸€ä¸ªSPI控制器é…ç½®ç§æœ‰æ•°æ® - template spi_controller { // 模æ¿å…¬å…±å‚数,继承该模æ¿çš„节点如果使用模æ¿ä¸çš„默认值,则节点å—段å¯ä»¥ç¼ºçœã€‚ - serviceName = ""; - match_attr = ""; - transferMode = 0; // æ•°æ®ä¼ 输模å¼ï¼šä¸æ–ä¼ è¾“(0)ã€æµæŽ§ä¼ 输(1)ã€DMAä¼ è¾“(2) - busNum = 0; // æ€»çº¿å· - clkRate = 100000000; - bitsPerWord = 8; // ä¼ è¾“ä½å®½ - mode = 19; // SPI æ•°æ®çš„è¾“å…¥è¾“å‡ºæ¨¡å¼ - maxSpeedHz = 0; // 最大时钟频率 - minSpeedHz = 0; // 最å°æ—¶é’Ÿé¢‘率 - speed = 2000000; // 当å‰æ¶ˆæ¯ä¼ 输速度 - fifoSize = 256; // FIFOå¤§å° - numCs = 1; // ç‰‡é€‰å· - regBase = 0x120c0000; // 地å€æ˜ å°„éœ€è¦ - irqNum = 100; // ä¸æ–å· - REG_CRG_SPI = 0x120100e4; // CRG_REG_BASE(0x12010000) + 0x0e4 - CRG_SPI_CKEN = 0; - CRG_SPI_RST = 0; - REG_MISC_CTRL_SPI = 0x12030024; // MISC_REG_BASE(0x12030000) + 0x24 - MISC_CTRL_SPI_CS = 0; - MISC_CTRL_SPI_CS_SHIFT = 0; - } - controller_0x120c0000 :: spi_controller { - busNum = 0; // ã€å¿…è¦ã€‘æ€»çº¿å· - CRG_SPI_CKEN = 0x10000; // (0x1 << 16) 0:close clk, 1:open clk - CRG_SPI_RST = 0x1; // (0x1 << 0) 0:cancel reset, 1:reset - match_attr = "hisilicon_hi35xx_spi_0";// ã€å¿…è¦ã€‘需è¦å’Œdevice_info.hcsä¸çš„deviceMatchAttr值一致 - } - controller_0x120c1000 :: spi_controller { - busNum = 1; - CRG_SPI_CKEN = 0x20000; // (0x1 << 17) 0:close clk, 1:open clk - CRG_SPI_RST = 0x2; // (0x1 << 1) 0:cancel reset, 1:reset - match_attr = "hisilicon_hi35xx_spi_1"; - regBase = 0x120c1000; // ã€å¿…è¦ã€‘地å€æ˜ å°„éœ€è¦ - irqNum = 101; // ã€å¿…è¦ã€‘ä¸æ–å· - } - ... - // ã€å¯é€‰ã€‘å¯æ–°å¢žï¼Œä½†éœ€è¦åœ¨device_info.hcsæ·»åŠ å¯¹åº”çš„èŠ‚ç‚¹ã€‚ + platform { + spi_config { // æ¯ä¸€ä¸ªSPI控制器é…ç½®ç§æœ‰æ•°æ® + template spi_controller { // 模æ¿å…¬å…±å‚数,继承该模æ¿çš„节点如果使用模æ¿ä¸çš„默认值,则节点å—段å¯ä»¥ç¼ºçœã€‚ + serviceName = ""; + match_attr = ""; + transferMode = 0; // æ•°æ®ä¼ 输模å¼ï¼šä¸æ–ä¼ è¾“(0)ã€æµæŽ§ä¼ 输(1)ã€DMAä¼ è¾“(2) + busNum = 0; // æ€»çº¿å· + clkRate = 100000000; + bitsPerWord = 8; // ä¼ è¾“ä½å®½ + mode = 19; // SPI æ•°æ®çš„è¾“å…¥è¾“å‡ºæ¨¡å¼ + maxSpeedHz = 0; // 最大时钟频率 + minSpeedHz = 0; // 最å°æ—¶é’Ÿé¢‘率 + speed = 2000000; // 当å‰æ¶ˆæ¯ä¼ 输速度 + fifoSize = 256; // FIFOå¤§å° + numCs = 1; // ç‰‡é€‰å· + regBase = 0x120c0000; // 地å€æ˜ å°„éœ€è¦ + irqNum = 100; // ä¸æ–å· + REG_CRG_SPI = 0x120100e4; // CRG_REG_BASE(0x12010000) + 0x0e4 + CRG_SPI_CKEN = 0; + CRG_SPI_RST = 0; + REG_MISC_CTRL_SPI = 0x12030024; // MISC_REG_BASE(0x12030000) + 0x24 + MISC_CTRL_SPI_CS = 0; + MISC_CTRL_SPI_CS_SHIFT = 0; + } + controller_0x120c0000 :: spi_controller { + busNum = 0; // ã€å¿…è¦ã€‘æ€»çº¿å· + CRG_SPI_CKEN = 0x10000; // (0x1 << 16) 0:close clk, 1:open clk + CRG_SPI_RST = 0x1; // (0x1 << 0) 0:cancel reset, 1:reset + match_attr = "hisilicon_hi35xx_spi_0"; // ã€å¿…è¦ã€‘需è¦å’Œdevice_info.hcsä¸çš„deviceMatchAttr值一致 + } + controller_0x120c1000 :: spi_controller { + busNum = 1; + CRG_SPI_CKEN = 0x20000; // (0x1 << 17) 0:close clk, 1:open clk + CRG_SPI_RST = 0x2; // (0x1 << 1) 0:cancel reset, 1:reset + match_attr = "hisilicon_hi35xx_spi_1"; + regBase = 0x120c1000; // ã€å¿…è¦ã€‘地å€æ˜ å°„éœ€è¦ + irqNum = 101; // ã€å¿…è¦ã€‘ä¸æ–å· + } + ... + /* ã€å¯é€‰ã€‘å¯æ–°å¢žï¼Œä½†éœ€è¦åœ¨device_info.hcsæ·»åŠ å¯¹åº”çš„èŠ‚ç‚¹ã€‚ */ + } } - } } ``` -3. 完æˆå±žæ€§æ–‡ä»¶é…置之åŽï¼Œä¸‹ä¸€æ¥å°±æ˜¯ä»¥æ ¸å¿ƒå±‚SpiCntlr对象的åˆå§‹åŒ–ä¸ºæ ¸å¿ƒï¼ŒåŒ…æ‹¬åŽ‚å•†è‡ªå®šä¹‰ç»“æž„ä½“ï¼ˆä¼ é€’å‚数和数æ®ï¼‰ï¼Œå®žä¾‹åŒ–SpiCntlræˆå‘˜SpiCntlrMethod(让用户å¯ä»¥é€šè¿‡æŽ¥å£æ¥è°ƒç”¨é©±åŠ¨åº•å±‚函数),实现HdfDriverEntryæˆå‘˜å‡½æ•°ï¼ˆBindã€Initã€Release)。 + 需è¦æ³¨æ„的是,新增spi_config.hcsé…置文件åŽï¼Œå¿…须在hdf.hcs文件ä¸å°†å…¶åŒ…å«ï¼Œå¦åˆ™é…ç½®æ–‡ä»¶æ— æ³•ç”Ÿæ•ˆã€‚ + + 例如:本例ä¸spi_config.hcs所在路径为device/soc/hisilicon/hi3516dv300/sdk_liteos/hdf_config/spi/spi_config.hcs,则必须在产å“对应的hdf.hcsä¸æ·»åŠ 如下è¯å¥ï¼š + + ```c + #include "../../../../device/soc/hisilicon/hi3516dv300/sdk_liteos/hdf_config/spi/spi_config.hcs" // é…置文件相对路径 + ``` + +3. 完æˆå±žæ€§æ–‡ä»¶é…置之åŽï¼Œä¸‹ä¸€æ¥å°±æ˜¯ä»¥æ ¸å¿ƒå±‚SpiCntlr对象的åˆå§‹åŒ–ä¸ºæ ¸å¿ƒï¼ŒåŒ…æ‹¬é©±åŠ¨é€‚é…è€…è‡ªå®šä¹‰ç»“æž„ä½“ï¼ˆä¼ é€’å‚数和数æ®ï¼‰ï¼Œå®žä¾‹åŒ–SpiCntlræˆå‘˜SpiCntlrMethod(让用户å¯ä»¥é€šè¿‡æŽ¥å£æ¥è°ƒç”¨é©±åŠ¨åº•å±‚函数),实现HdfDriverEntryæˆå‘˜å‡½æ•°ï¼ˆBindã€Initã€Release)。 - 自定义结构体å‚考 从驱动的角度看,自定义结构体是å‚数和数æ®çš„载体,而且spi_config.hcs文件ä¸çš„数值会被HDF读入并通过DeviceResourceIfaceæ¥åˆå§‹åŒ–结构体æˆå‘˜ï¼Œä¸€äº›é‡è¦æ•°å€¼ä¹Ÿä¼šä¼ é€’ç»™æ ¸å¿ƒå±‚å¯¹è±¡ï¼Œä¾‹å¦‚è®¾å¤‡å·ã€æ€»çº¿å·ç‰ã€‚ - ``` - struct Pl022 {//对应于hcsä¸çš„å‚æ•° - struct SpiCntlr *cntlr; - struct DListHead deviceList; - struct OsalSem sem; - volatile unsigned char *phyBase; - volatile unsigned char *regBase; - uint32_t irqNum; - uint32_t busNum; - uint32_t numCs; - uint32_t curCs; - uint32_t speed; - uint32_t fifoSize; - uint32_t clkRate; - uint32_t maxSpeedHz; - uint32_t minSpeedHz; - uint32_t regCrg; - uint32_t clkEnBit; - uint32_t clkRstBit; - uint32_t regMiscCtrl; - uint32_t miscCtrlCsShift; - uint32_t miscCtrlCs; - uint16_t mode; - uint8_t bitsPerWord; - uint8_t transferMode; - }; - - // SpiCntlræ˜¯æ ¸å¿ƒå±‚æŽ§åˆ¶å™¨ç»“æž„ä½“ï¼Œå…¶ä¸çš„æˆå‘˜åœ¨Init函数ä¸ä¼šè¢«èµ‹å€¼ã€‚ - struct SpiCntlr { - struct IDeviceIoService service; - struct HdfDeviceObject *device; - uint32_t busNum; - uint32_t numCs; - uint32_t curCs; - struct OsalMutex lock; - struct SpiCntlrMethod *method; - struct DListHead list; - void *priv; - }; - ``` + ```c + struct Pl022 { //对应于spi_config.hcsä¸çš„å‚æ•° + struct SpiCntlr *cntlr; + struct DListHead deviceList; + struct OsalSem sem; + volatile unsigned char *phyBase; + volatile unsigned char *regBase; + uint32_t irqNum; + uint32_t busNum; + uint32_t numCs; + uint32_t curCs; + uint32_t speed; + uint32_t fifoSize; + uint32_t clkRate; + uint32_t maxSpeedHz; + uint32_t minSpeedHz; + uint32_t regCrg; + uint32_t clkEnBit; + uint32_t clkRstBit; + uint32_t regMiscCtrl; + uint32_t miscCtrlCsShift; + uint32_t miscCtrlCs; + uint16_t mode; + uint8_t bitsPerWord; + uint8_t transferMode; + }; + + /* SpiCntlræ˜¯æ ¸å¿ƒå±‚æŽ§åˆ¶å™¨ç»“æž„ä½“ï¼Œå…¶ä¸çš„æˆå‘˜åœ¨Init函数ä¸ä¼šè¢«èµ‹å€¼ã€‚ */ + struct SpiCntlr { + struct IDeviceIoService service; + struct HdfDeviceObject *device; + uint32_t busNum; + uint32_t numCs; + uint32_t curCs; + struct OsalMutex lock; + struct SpiCntlrMethod *method; + struct DListHead list; + void *priv; + }; + ``` - - SpiCntlræˆå‘˜å›žè°ƒå‡½æ•°ç»“构体SpiCntlrMethod的实例化,其他æˆå‘˜åœ¨Init函数ä¸åˆå§‹åŒ–。 + - SpiCntlræˆå‘˜é’©å函数结构体SpiCntlrMethod的实例化,其他æˆå‘˜åœ¨Init函数ä¸åˆå§‹åŒ–。 - ``` - // spi_hi35xx.cä¸çš„示例:钩å函数的实例化 + ```c + /* spi_hi35xx.cä¸çš„示例:钩å函数的实例化 */ struct SpiCntlrMethod g_method = { .Transfer = Pl022Transfer, .SetCfg = Pl022SetCfg, @@ -240,7 +286,7 @@ SPI模å—适é…HDF框架的三个必选环节是实例化驱动入å£ï¼Œé…ç½® å…¥å‚: - HdfDeviceObject是整个驱动对外暴露的接å£å‚数,具备HCSé…置文件的信æ¯ã€‚ + HdfDeviceObject是整个驱动对外æ供的接å£å‚数,具备HCSé…置文件的信æ¯ã€‚ 返回值: @@ -251,7 +297,7 @@ SPI模å—适é…HDF框架的三个必选环节是实例化驱动入å£ï¼Œé…ç½® å°†SpiCntlr对象åŒHdfDeviceObject进行了关è”。 - ``` + ```c static int32_t HdfSpiDeviceBind(struct HdfDeviceObject *device) { ... @@ -260,28 +306,28 @@ SPI模å—适é…HDF框架的三个必选环节是实例化驱动入å£ï¼Œé…ç½® struct SpiCntlr *SpiCntlrCreate(struct HdfDeviceObject *device) { - struct SpiCntlr *cntlr = NULL; // åˆ›å»ºæ ¸å¿ƒå±‚SpiCntlr对象 + struct SpiCntlr *cntlr = NULL; // åˆ›å»ºæ ¸å¿ƒå±‚SpiCntlr对象 ... - cntlr = (struct SpiCntlr *)OsalMemCalloc(sizeof(*cntlr));// 分é…å†…å˜ + cntlr = (struct SpiCntlr *)OsalMemCalloc(sizeof(*cntlr)); // 分é…å†…å˜ ... - cntlr->device = device; // 使HdfDeviceObject与SpiCntlrå¯ä»¥ç›¸äº’转化的å‰æ - device->service = &(cntlr->service); // 使HdfDeviceObject与SpiCntlrå¯ä»¥ç›¸äº’转化的å‰æ - (void)OsalMutexInit(&cntlr->lock); // é”åˆå§‹åŒ– - DListHeadInit(&cntlr->list); // æ·»åŠ å¯¹åº”çš„èŠ‚ç‚¹ + cntlr->device = device; // 使HdfDeviceObject与SpiCntlrå¯ä»¥ç›¸äº’转化的å‰æ + device->service = &(cntlr->service); // 使HdfDeviceObject与SpiCntlrå¯ä»¥ç›¸äº’转化的å‰æ + (void)OsalMutexInit(&cntlr->lock); // é”åˆå§‹åŒ– + DListHeadInit(&cntlr->list); // æ·»åŠ å¯¹åº”çš„èŠ‚ç‚¹ cntlr->priv = NULL; return cntlr; } ``` - - Init函数å‚考 + - Init函数开å‘å‚考 å…¥å‚: - HdfDeviceObject是整个驱动对外暴露的接å£å‚数,具备HCSé…置文件的信æ¯ã€‚ + HdfDeviceObject是整个驱动对外æ供的接å£å‚数,具备HCSé…置文件的信æ¯ã€‚ 返回值: - HDF_STATUS相关状æ€ï¼ˆä¸‹è¡¨ä¸ºéƒ¨åˆ†å±•ç¤ºï¼Œå¦‚需使用其他状æ€ï¼Œå¯è§//drivers/framework/include/utils/hdf_base.hä¸HDF_STATUS定义)。 + HDF_STATUS相关状æ€ï¼ˆä¸‹è¡¨ä¸ºéƒ¨åˆ†å±•ç¤ºï¼Œå¦‚需使用其他状æ€ï¼Œå¯è§//drivers/hdf_core/framework/include/utils/hdf_base.hä¸HDF_STATUS定义)。 **表2** HDF_STATUS返回值æè¿° @@ -299,55 +345,55 @@ SPI模å—适é…HDF框架的三个必选环节是实例化驱动入å£ï¼Œé…ç½® åˆå§‹åŒ–自定义结构体对象,åˆå§‹åŒ–SpiCntlræˆå‘˜ã€‚ - ``` + ```c static int32_t HdfSpiDeviceInit(struct HdfDeviceObject *device) { - int32_t ret; - struct SpiCntlr *cntlr = NULL; - ... - cntlr = SpiCntlrFromDevice(device); // 这里有HdfDeviceObject到SpiCntlr的强制转化,通过serviceæˆå‘˜ï¼Œèµ‹å€¼è§Bind函数。 - // return (device == NULL) ? NULL : (struct SpiCntlr *)device->service; - ... - ret = Pl022Init(cntlr, device); // ã€å¿…è¦ã€‘实例化厂商自定义æ“作对象,示例è§ä¸‹ã€‚ - ... - ret = Pl022Probe(cntlr->priv); - ... - return ret; + int32_t ret; + struct SpiCntlr *cntlr = NULL; + ... + cntlr = SpiCntlrFromDevice(device); // 这里有HdfDeviceObject到SpiCntlr的强制转æ¢ï¼Œé€šè¿‡serviceæˆå‘˜ï¼Œèµ‹å€¼è§Bind函数。 + // return (device == NULL) ? NULL : (struct SpiCntlr *)device->service; + ... + ret = Pl022Init(cntlr, device); // ã€å¿…è¦ã€‘实例化驱动适é…者自定义æ“作对象,示例è§ä¸‹ã€‚ + ... + ret = Pl022Probe(cntlr->priv); + ... + return ret; } static int32_t Pl022Init(struct SpiCntlr *cntlr, const struct HdfDeviceObject *device) { - int32_t ret; - struct Pl022 *pl022 = NULL; - ... - pl022 = (struct Pl022 *)OsalMemCalloc(sizeof(*pl022));// ç”³è¯·å†…å˜ - ... - ret = SpiGetBaseCfgFromHcs(pl022, device->property); // åˆå§‹åŒ–busNumã€numCsã€speedã€fifoSizeã€clkRateã€modeã€bitsPerWordã€transferModeå‚数值。 - ... - ret = SpiGetRegCfgFromHcs(pl022, device->property); // åˆå§‹åŒ–regBaseã€phyBaseã€irqNumã€regCrgã€clkEnBitã€clkRstBitã€regMiscCtrlã€regMiscCtrl〠miscCtrlCsã€miscCtrlCsShiftå‚数值。 - ... - // 计算最大ã€æœ€å°é€Ÿåº¦å¯¹åº”的频率。 - pl022->maxSpeedHz = (pl022->clkRate) / ((SCR_MIN + 1) * CPSDVSR_MIN); - pl022->minSpeedHz = (pl022->clkRate) / ((SCR_MAX + 1) * CPSDVSR_MAX); - DListHeadInit(&pl022->deviceList); // åˆå§‹åŒ–DList链表 - pl022->cntlr = cntlr; // 使Pl022与SpiCntlrå¯ä»¥ç›¸äº’转化的å‰æ - cntlr->priv = pl022; // 使Pl022与SpiCntlrå¯ä»¥ç›¸äº’转化的å‰æ - cntlr->busNum = pl022->busNum; // ç»™SpiCntlrçš„busNum赋值 - cntlr->method = &g_method; // SpiCntlrMethod的实例化对象的挂载 - ... - ret = Pl022CreatAndInitDevice(pl022); - if (ret != 0) { - Pl022Release(pl022); // åˆå§‹åŒ–失败就释放Pl022对象 - return ret; - } - return 0; - } + int32_t ret; + struct Pl022 *pl022 = NULL; + ... + pl022 = (struct Pl022 *)OsalMemCalloc(sizeof(*pl022)); // ç”³è¯·å†…å˜ + ... + ret = SpiGetBaseCfgFromHcs(pl022, device->property); // åˆå§‹åŒ–busNumã€numCsã€speedã€fifoSizeã€clkRateã€modeã€bitsPerWordã€transferModeå‚数值。 + ... + ret = SpiGetRegCfgFromHcs(pl022, device->property); // åˆå§‹åŒ–regBaseã€phyBaseã€irqNumã€regCrgã€clkEnBitã€clkRstBitã€regMiscCtrlã€regMiscCtrl〠miscCtrlCsã€miscCtrlCsShiftå‚数值。 + ... + // 计算最大ã€æœ€å°é€Ÿåº¦å¯¹åº”的频率。 + pl022->maxSpeedHz = (pl022->clkRate) / ((SCR_MIN + 1) * CPSDVSR_MIN); + pl022->minSpeedHz = (pl022->clkRate) / ((SCR_MAX + 1) * CPSDVSR_MAX); + DListHeadInit(&pl022->deviceList); // åˆå§‹åŒ–DList链表 + pl022->cntlr = cntlr; // 使Pl022与SpiCntlrå¯ä»¥ç›¸äº’转化的å‰æ + cntlr->priv = pl022; // 使Pl022与SpiCntlrå¯ä»¥ç›¸äº’转化的å‰æ + cntlr->busNum = pl022->busNum; // ç»™SpiCntlrçš„busNum赋值 + cntlr->method = &g_method; // SpiCntlrMethod的实例化对象的挂载 + ... + ret = Pl022CreatAndInitDevice(pl022); + if (ret != 0) { + Pl022Release(pl022); // åˆå§‹åŒ–失败则释放Pl022对象 + return ret; + } + return 0; + } ``` - - Release函数å‚考 + - Release函数开å‘å‚考 å…¥å‚: - HdfDeviceObject是整个驱动对外暴露的接å£å‚数,具备HCSé…置文件的信æ¯ã€‚ + HdfDeviceObject是整个驱动对外æ供的接å£å‚数,具备HCSé…置文件的信æ¯ã€‚ 返回值: @@ -360,17 +406,16 @@ SPI模å—适é…HDF框架的三个必选环节是实例化驱动入å£ï¼Œé…ç½® >  **说明:**<br> > 所有强制转æ¢èŽ·å–相应对象的æ“作å‰æ是在Init函数ä¸å…·å¤‡å¯¹åº”赋值的æ“作。 - - ``` + ```c static void HdfSpiDeviceRelease(struct HdfDeviceObject *device) { struct SpiCntlr *cntlr = NULL; ... - cntlr = SpiCntlrFromDevice(device); // 这里有HdfDeviceObject到SpiCntlr的强制转化,通过serviceæˆå‘˜ï¼Œèµ‹å€¼è§Bind函数 + cntlr = SpiCntlrFromDevice(device); // 这里有HdfDeviceObject到SpiCntlr的强制转æ¢ï¼Œé€šè¿‡serviceæˆå‘˜ï¼Œèµ‹å€¼è§Bind函数 // return (device==NULL) ?NULL:(struct SpiCntlr *)device->service; ... if (cntlr->priv != NULL) { - Pl022Remove((struct Pl022 *)cntlr->priv); // 这里有SpiCntlr到Pl022的强制转化 + Pl022Remove((struct Pl022 *)cntlr->priv); // 这里有SpiCntlr到Pl022çš„å¼ºåˆ¶è½¬æ¢ } SpiCntlrDestroy(cntlr); // 释放Pl022对象 } diff --git "a/zh-cn/device-dev/driver/figures/I3C\344\275\277\347\224\250\346\265\201\347\250\213\345\233\276.png" "b/zh-cn/device-dev/driver/figures/I3C\344\275\277\347\224\250\346\265\201\347\250\213\345\233\276.png" index 40c7088de596e771921861c727d4813f686eda40..b5ef4432398f7fe6d113774c806453def9a1f6ae 100755 Binary files "a/zh-cn/device-dev/driver/figures/I3C\344\275\277\347\224\250\346\265\201\347\250\213\345\233\276.png" and "b/zh-cn/device-dev/driver/figures/I3C\344\275\277\347\224\250\346\265\201\347\250\213\345\233\276.png" differ 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" index 1e5945dde90c375947137d8b5e9161018c0700f9..5a354fb7af51f27e5c27e6efdf2b45a09aaa0325 100755 Binary files "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" and "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" differ