diff --git a/en/device-dev/Readme-EN.md b/en/device-dev/Readme-EN.md index 63497300cba285ba9edb75014ea05cbb3001b68d..b99935770e4b2d55a87cf33f4d17da6e16c14fbb 100644 --- a/en/device-dev/Readme-EN.md +++ b/en/device-dev/Readme-EN.md @@ -76,7 +76,7 @@ In addition, OpenHarmony provides a series of optional system components that ca

Developing smart devices based on system capabilities

- +

Porting and adaptation

@@ -97,7 +97,7 @@ In addition, OpenHarmony provides a series of optional system components that ca

Referring to development specifications

- + @@ -167,7 +167,7 @@ In addition, OpenHarmony provides a series of optional system components that ca

Referring to development specifications

- + diff --git a/en/device-dev/faqs/Readme-EN.md b/en/device-dev/faqs/Readme-EN.md new file mode 100644 index 0000000000000000000000000000000000000000..192f50248a2167bb6417c69603cbb99be2ed9490 --- /dev/null +++ b/en/device-dev/faqs/Readme-EN.md @@ -0,0 +1,11 @@ +# FAQs + +- [Overview of FAQs](overview-of-faqs.md) +- [Environment Setup](environment-setup.md) +- [Compilation and Building Subsystem](compilation-and-building-subsystem.md) +- [Burning](burning.md) +- [Kernel](kernel.md) +- [Porting](porting.md) +- [Startup and Recovery](startup-and-recovery.md) +- [System Applications](system-applications.md) + diff --git a/en/device-dev/faqs/burning.md b/en/device-dev/faqs/burning.md new file mode 100644 index 0000000000000000000000000000000000000000..489443726730ba56c3df633d44c9ac090e77fe42 --- /dev/null +++ b/en/device-dev/faqs/burning.md @@ -0,0 +1,129 @@ +# Burning + +- [Mini and Small Systems](#section278314413530) + - ["Error: Opening COMxx: Access denied" Is Displayed After a Serial Port Is Selected for Burning](#section18988185615914) + - [What should I do when the image failed to be burnt?](#section1370982513317) + - [What should I do when no command output is displayed?](#section183421944953) + - [What should I do when Windows-based PC failed to be connected to the board?](#section1215410450215) + + +## Mini and Small Systems + +### "Error: Opening COMxx: Access denied" Is Displayed After a Serial Port Is Selected for Burning + +- **Symptom** + + **Error: Opening COMxx: Access denied** is displayed after clicking **Burn** and selecting a serial port. + + ![](figures/failed-to-open-the-serial-port.png) + +- **Possible Causes** + + The serial port has been used. + +- Solution + + The serial port may be in use. Perform the following steps to troubleshoot: + + 1. Search for the serial port from the drop-down list in the **TERMINAL** panel. + + ![](figures/terminal-list.png) + + 2. Click the dustbin for the terminal using the serial port to disable the terminal. + + +### What should I do when the image failed to be burnt? + +- **Symptom** + + The burning status is not displayed after clicking **Burn** and selecting a serial port. + +- **Possible Causes** + + The IDE is not restarted after the DevEco plug-in is installed. + +- **Solutions** + + Restart the IDE. + + +### What should I do when no command output is displayed? + +- **Symptom** + + The serial port shows that the connection has been established. After the board is restarted, nothing is displayed when you press **Enter**. + +- **Possible Cause 1** + + The serial port is connected incorrectly. + +- **Solutions** + + Change the serial port number. + + Start **Device Manager** to check whether the serial port connected to the board is the same as that connected to the terminal device. If the serial ports are different, perform step 1 in the **Running an Image** section to change the serial port number. + + +- **Possible Cause 2** + + The U-Boot of the board is damaged. + +- **Solutions** + + Burn the U-Boot. + + If the fault persists after you perform the preceding operations, the U-Boot of the board may be damaged. You can burn the U-Boot by performing the following steps: + + +1. Obtain the U-Boot file. + + >![](public_sys-resources/icon-notice.gif) **NOTICE:** + >The U-Boot file of the two boards can be obtained from the following paths, respectively. + >Hi3516D V300: **device\\hisilicon\\hispark\_taurus\\sdk\_liteos\\uboot\\out\\boot\\u-boot-hi3516dv300.bin** + >Hi3518E V300: **device\\hisilicon\\hispark\_aries\\sdk\_liteos\\uboot\\out\\boot\\u-boot-hi3518ev300.bin** + +2. Burn the U-Boot file by following the procedures for burning a U-Boot file over USB. + + Select the U-Boot files of corresponding development boards for burning by referring to [Programming Flash Memory on the Hi3516](https://device.harmonyos.com/en/docs/ide/user-guides/hi3516_upload-0000001052148681)/[Programming Flash Memory on the Hi3518](https://device.harmonyos.com/en/docs/ide/user-guides/hi3518_upload-0000001057313128) + +3. Log in to the serial port after the burning is complete. + + **Figure 1** Serial port displayed after the U-Boot is burnt + ![](figures/serial-port-displayed-after-the-u-boot-is-burnt.png "serial-port-displayed-after-the-u-boot-is-burnt") + + +### What should I do when Windows-based PC failed to be connected to the board? + +- **Symptom** + + The file image cannot be obtained after clicking **Burn** and selecting a serial port. + + **Figure 2** Failed to obtain the image file due to unavailable connection + ![](figures/failed-to-obtain-the-image-file-due-to-unavailable-connection.png "failed-to-obtain-the-image-file-due-to-unavailable-connection") + +- **Possible Causes** + + The board is disconnected from the Windows-based PC. + + Windows Firewall does not allow Visual Studio Code to access the network. + +- **Solutions** + +1. Check whether the network cable is properly connected. +2. Click **Windows Firewall**. + + ![](figures/hi3516-network-and-firewall-setting.png) + +3. Click **Firewall & network protection**, and on the displayed page, click **Allow applications to communicate through Windows Firewall**. + + ![](figures/hi3516-firewall-and-network-protection.png) + +4. Select the Visual Studio Code application. + + ![](figures/hi3516-selecting-the-visual-studio-code-application.png) + +5. Select the **Private** and **Public** network access rights for the Visual Studio Code application. + + ![](figures/hi3516-allowing-the-visual-studio-code-application-to-access-the-network.png) + + diff --git a/en/device-dev/faqs/compilation-and-building-subsystem.md b/en/device-dev/faqs/compilation-and-building-subsystem.md new file mode 100644 index 0000000000000000000000000000000000000000..5bc568ead1f3a8fd282c354632bb781de04de325 --- /dev/null +++ b/en/device-dev/faqs/compilation-and-building-subsystem.md @@ -0,0 +1,243 @@ +# Compilation and Building Subsystem + +- [Mini and Small Systems](#section78686441462) + - [Invalid -- w Option](#section67961431372) + - [Library ncurses Not Found](#section199631617371) + - [mcopy not Found](#section937435175) + - [No riscv File or Directory](#section1115535018713) + - [No Crypto](#section17982573813) + - [Unexpected Operator](#section53663205819) + - [What should I do when the message Could not find a version that satisfies the requirement six\>=1.9.0 is displayed during compilation and building?](#section1917790845) + - [What should I do when the message cannot find -lgcc is displayed during compilation and building?](#section141771701647) + - [What should I do when the message indicating Python cannot be found is displayed during compilation and building?](#section51781202415) + - [What should I do when the message indicating Python 3 cannot be found is displayed during compilation and building?](#section1917950148) + + +## Mini and Small Systems + +### Invalid -- w Option + +- **Symptom** + + The build fails, and "usr/sbin/ninja: invalid option -- w" is displayed. + +- **Cause** + + The Ninja version in the build environment is outdated and does not support the **--w** option. + +- **Solution** + + Uninstall Ninja and GN and follow the instructions provided in [IDE](../get-code/gettools-ide.md) to install Ninja and GN of the required version. + + +### Library ncurses Not Found + +- **Symptom** + + The build fails, and "/usr/bin/ld: cannot find -lncurses" is displayed. + +- **Cause** + + The ncurses library is not installed. + +- **Solution** + + ``` + sudo apt-get install lib32ncurses5-dev + ``` + + +### mcopy not Found + +- **Symptom** + + The build fails, and "line 77: mcopy: command not found" is displayed. + +- **Cause** + + mcopy is not installed. + +- **Solution** + + ``` + ​sudo apt-get install dosfstools mtools + ``` + + +### No riscv File or Directory + +- **Symptom** + + The build fails, and the following information is displayed: + + riscv32-unknown-elf-gcc: error trying to exec 'cc1': execvp: No such file or directory. + +- **Cause** + + Permission is required to access files in the **riscv** compiler directory. + +- **Solution** + + Run the following command to query the directory where **gcc\_riscv32** is located: + + ``` + which riscv32-unknown-elf-gcc + ``` + + Run the **chmod** command to change the directory permission to **755**. + + +### No Crypto + +- **Symptom** + + The build fails, and "No module named 'Crypto'" is displayed. + +- **Cause** + + Crypto is not installed in Python 3. + +- **Solution** + 1. Run the following command to query the Python version: + + ``` + python3 --version + ``` + + 2. Ensure that Python 3.7 or later is installed, and then run the following command to install pycryptodome: + + ``` + sudo pip3 install pycryptodome + ``` + + + +### Unexpected Operator + +- **Symptom** + + The build fails, and "xx.sh \[: xx unexpected operator" is displayed. + +- **Cause** + + The build environment is shell, not bash. + +- **Solution** + + ``` + sudo rm -rf /bin/sh + sudo ln -s /bin/bash /bin/sh + ``` + + +### What should I do when the message **Could not find a version that satisfies the requirement six\>=1.9.0** is displayed during compilation and building? + +- **Symptom** + + The following error occurs during compilation and building: + + ``` + Could not find a version that satisfies the requirement six>=1.9.0 + ``` + + +- **Possible Causes** + + **six** is not installed. + + +- **Solutions** + + Solution 1: Run the **pip3 install six** command to install **six** online. + + Solution 2: Install **six** offline. + + - Download the installation package from [https://pypi.org/project/six/\#files](https://pypi.org/project/six/#files). + + ![](figures/download-six.png) + + - Save the source code to the Linux server and run the **pip3 install six-1.14.0-py2.py3-none-any.whl** command to install **six**. + - Rebuild an environment. + + +### What should I do when the message **cannot find -lgcc** is displayed during compilation and building? + +- **Symptom** + + The following error occurs during compilation and building: + + ``` + riscv32-unknown-elf-ld: cannot find -lgcc + ``` + + +- **Possible Causes** + + The PATH is incorrectly written by **gcc\_riscv32**. There is an extra slash \(/\). + + ``` + ~/gcc_riscv32/bin/:/data/toolchain/ + ``` + + +- **Solutions** + + Modify the PATH by deleting the slash \(/\). + + ``` + ~/gcc_riscv32/bin:/data/toolchain/ + ``` + + +### What should I do when the message indicating Python cannot be found is displayed during compilation and building? + +- **Symptom** + + The following error occurs during compilation and building: + + ``` + -bash: /usr/bin/python: No such file or directory + ``` + + +- **Possible Cause 1:** Python is not installed. +- **Solutions** + + [Install Python](../quick-start/quickstart-lite-env-setup-linux.md). + +- **Possible Cause 2:** The soft link that points to the Python does not exist in the **usr/bin** directory. + + ![](figures/reason-no-python-soft-link.png) + +- **Solutions** + + Run the following commands to add a soft link: + + ``` + # cd /usr/bin/ + # which python3 + # ln -s /usr/local/bin/python3 python + # python --version + ``` + + Example: + + ![](figures/solution-add-soft-link.png) + + +### What should I do when the message indicating Python 3 cannot be found is displayed during compilation and building? + +- **Symptom** + + ![](figures/11.png) + + +- **Possible Causes** + + Python 3 is not installed. + +- **Solutions** + + [Install Python](../quick-start/quickstart-lite-env-setup-linux.md). + + diff --git a/en/device-dev/faqs/environment-setup.md b/en/device-dev/faqs/environment-setup.md new file mode 100644 index 0000000000000000000000000000000000000000..2213897bdda18bb783464d0287102c2fc6c19533 --- /dev/null +++ b/en/device-dev/faqs/environment-setup.md @@ -0,0 +1,239 @@ +# Environment Setup + +- [Mini and Small Systems](#section1742119306399) + - [What should I do if garbled characters and segmentation faults occur during hb installation?](#section36351051193919) + - [What should I do if the message "cannot import 'sysconfig' from 'distutils'" is displayed during hb installation?](#section48221013144011) + - [What should I do if the message "module 'platform' has no attribute 'linux\_distribution'" is displayed during hb installation?](#section10307193044111) + - [What should I do if the message "Could not find a version that satisfies the requirement ohos-build" is displayed during hb installation?](#section8692735427) + - [What should I do when the message configure: error: no acceptable C compiler found in $PATH is displayed during Python 3 installation?](#section870082884217) + - [What should I do when the message -bash: make: command not found is displayed during Python 3 installation?](#section198707170455) + - [What should I do when the message zlib not available is displayed during Python 3 installation?](#section85401445204518) + - [What should I do when the message No module named '\_ctypes' is displayed during Python 3 installation?](#section12202694460) + - [What should I do when an error with lsb\_release occurs during kconfiglib installation?](#section5803174135115) + - [What should I do if the message "ImportError: No module named apt\_pkg" is displayed during the execution of an unidentifiable command?](#section510820516515) + + +## Mini and Small Systems + +### What should I do if garbled characters and segmentation faults occur during hb installation? + +- **Symptom** + + Garbled characters and segmentation faults occur during the execution of the **python3 -m pip install --user ohos-build** command. + + +- **Possible Causes** + + pip is of an early version. + +- **Solutions** + + Upgrade pip. + + ``` + python3 -m pip install -U pip + ``` + + +### What should I do if the message "cannot import 'sysconfig' from 'distutils'" is displayed during hb installation? + +- **Symptom** + + The message "cannot import 'sysconfig' from 'distutils'" is displayed during the execution of the **python3 -m pip install --user ohos-build** command. + + +- **Possible Causes** + + The **distutils** module is unavailable. + +- **Solutions** + + Install **distutils**. + + ``` + sudo apt-get install python3.8-distutils + ``` + + +### What should I do if the message "module 'platform' has no attribute 'linux\_distribution'" is displayed during hb installation? + +- **Symptom** + + The message "module 'platform' has no attribute 'linux\_distribution'" is displayed during the execution of the **python3 -m pip install --user ohos-build** command. + + +- **Possible Causes** + + There is a compatibility issue of python3-pip. + +- **Solutions** + + Reinstall pip. + + ``` + sudo apt remove python3-pip + curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py + python get-pip.py + ``` + + +### What should I do if the message "Could not find a version that satisfies the requirement ohos-build" is displayed during hb installation? + +- **Symptom** + + The message "Could not find a version that satisfies the requirement ohos-build" is displayed during the execution of the **python3 -m pip install --user ohos-build** command. + + +- **Possible Causes** + + The installation fails due to poor network connectivity. + +- **Solutions** + 1. Ensure that your computer has a good network connection. If the network connection is unstable, rectify the network fault and reinstall hb. + 2. If the network is functional, run the following commands to install hb by specifying a temporary PyPI source: + + ``` + python3 -m pip install -i https://pypi.tuna.tsinghua.edu.cn/simple ohos-build + ``` + + + +### What should I do when the message **configure: error: no acceptable C compiler found in $PATH** is displayed during Python 3 installation? + +- **Symptom** + + The following error occurs during Python 3 installation: + + ``` + configure: error: no acceptable C compiler found in $PATH. See 'config.log' for more details + ``` + +- **Possible Causes** + + **GCC** is not installed. + +- **Solutions** + + 1. Run the **apt-get install gcc** command to install **GCC** online. + + 2. After the installation, reinstall Python 3. + + +### What should I do when the message **-bash: make: command not found** is displayed during Python 3 installation? + +- **Symptom** + + The following error occurs during Python 3 installation: + + ``` + -bash: make: command not found + ``` + +- **Possible Causes** + + **Make** is not installed. + +- **Solutions** + + 1. Run the **apt-get install make** command to install **Make** online. + + 2. After the installation, reinstall Python 3. + + +### What should I do when the message **zlib not available** is displayed during Python 3 installation? + +- **Symptom** + + The following error occurs during Python 3 installation: + + ``` + zipimport.ZipImportError: can't decompress data; zlib not available + ``` + +- **Possible Causes** + + **zlib** is not installed. + +- **Solutions** + + Solution 1: Run the **apt-get install zlib** command to install **zlib** online. + + Solution 2: If the software source does not contain **zlib**, download the source code from https://www.zlib.net/. + + ![](figures/download-zlib.png) + + Then run the following commands to install **zlib** offline: + + ``` + # tar xvf zlib-1.2.11.tar.gz + # cd zlib-1.2.11 + # ./configure + # make && make install + ``` + + After the installation, reinstall Python 3. + + +### What should I do when the message **No module named '\_ctypes'** is displayed during Python 3 installation? + +- **Symptom** + + The following error occurs during Python 3 installation: + + ``` + ModuleNotFoundError: No module named '_ctypes' + ``` + + +- **Possible Causes** + + **libffi** and **libffi-devel** are not installed. + + +- **Solutions** + + 1. Run the **apt-get install libffi\* -y** command to install **libffi** and **libffi-devel** online. + + 2. After the installation, reinstall Python 3. + + +### What should I do when an error with **lsb\_release** occurs during **kconfiglib** installation? + +- **Symptom** + + The following error occurs during **kconfiglib** installation: + + ``` + subprocess.CalledProcessError: Command '('lsb_release', '-a')' returned non-zero exit status 1. + ``` + +- **Possible Causes** + + The Python version matched with the **lsb\_release** module is different from the current Python version. + +- **Solutions** + + Run the **find / -name lsb\_release** command, for example, **sudo rm -rf /usr/bin/lsb\_release** to locate and delete **lsb\_release**. + + +### What should I do if the message "ImportError: No module named apt\_pkg" is displayed during the execution of an unidentifiable command? + +- **Symptom** + + The message "ImportError: No module named apt\_pkg" is displayed when an unidentifiable command is executed on the Linux server. + + +- **Possible Causes** + + There is a compatibility issue of python3-apt. + +- **Solutions** + + Reinstall python3-apt. + + ``` + sudo apt-get remove python3-apt + sudo apt-get install python3-apt + ``` + + diff --git a/en/device-dev/faqs/figures/11.png b/en/device-dev/faqs/figures/11.png new file mode 100644 index 0000000000000000000000000000000000000000..ff9105c313d5755f140920bbfc2399e3ccb5e2f5 Binary files /dev/null and b/en/device-dev/faqs/figures/11.png differ diff --git a/en/device-dev/faqs/figures/download-six.png b/en/device-dev/faqs/figures/download-six.png new file mode 100644 index 0000000000000000000000000000000000000000..39ae26ac8f3254d023d6b90a9f9bb8a8ff0c940b Binary files /dev/null and b/en/device-dev/faqs/figures/download-six.png differ diff --git a/en/device-dev/faqs/figures/download-zlib.png b/en/device-dev/faqs/figures/download-zlib.png new file mode 100644 index 0000000000000000000000000000000000000000..3b7f6f4766c54f6ca1e0057fc8f869785cc63e56 Binary files /dev/null and b/en/device-dev/faqs/figures/download-zlib.png differ diff --git a/en/device-dev/faqs/figures/error-information.png b/en/device-dev/faqs/figures/error-information.png new file mode 100644 index 0000000000000000000000000000000000000000..015c38ba5516395527bcf6715535238f02b2bad9 Binary files /dev/null and b/en/device-dev/faqs/figures/error-information.png differ diff --git a/en/device-dev/faqs/figures/failed-to-obtain-the-image-file-due-to-unavailable-connection.png b/en/device-dev/faqs/figures/failed-to-obtain-the-image-file-due-to-unavailable-connection.png new file mode 100644 index 0000000000000000000000000000000000000000..548e03da4b76123cb67d41cbd1de4a0f33f5ef4b Binary files /dev/null and b/en/device-dev/faqs/figures/failed-to-obtain-the-image-file-due-to-unavailable-connection.png differ diff --git a/en/device-dev/faqs/figures/failed-to-open-the-serial-port.png b/en/device-dev/faqs/figures/failed-to-open-the-serial-port.png new file mode 100644 index 0000000000000000000000000000000000000000..25308b9cab52a166955e70ada35c3191d90dd64c Binary files /dev/null and b/en/device-dev/faqs/figures/failed-to-open-the-serial-port.png differ diff --git a/en/device-dev/faqs/figures/hi3516-allowing-the-visual-studio-code-application-to-access-the-network.png b/en/device-dev/faqs/figures/hi3516-allowing-the-visual-studio-code-application-to-access-the-network.png new file mode 100644 index 0000000000000000000000000000000000000000..13d77ce93c78ac07039c8f09741db1db1d05a124 Binary files /dev/null and b/en/device-dev/faqs/figures/hi3516-allowing-the-visual-studio-code-application-to-access-the-network.png differ diff --git a/en/device-dev/faqs/figures/hi3516-firewall-and-network-protection.png b/en/device-dev/faqs/figures/hi3516-firewall-and-network-protection.png new file mode 100644 index 0000000000000000000000000000000000000000..82faf7d05d2a40e9deae2649a1f59fccea67bdc2 Binary files /dev/null and b/en/device-dev/faqs/figures/hi3516-firewall-and-network-protection.png differ diff --git a/en/device-dev/faqs/figures/hi3516-network-and-firewall-setting.png b/en/device-dev/faqs/figures/hi3516-network-and-firewall-setting.png new file mode 100644 index 0000000000000000000000000000000000000000..9487849c5f8a860e9680016ff3657404b2c0ad6e Binary files /dev/null and b/en/device-dev/faqs/figures/hi3516-network-and-firewall-setting.png differ diff --git a/en/device-dev/faqs/figures/hi3516-selecting-the-visual-studio-code-application.png b/en/device-dev/faqs/figures/hi3516-selecting-the-visual-studio-code-application.png new file mode 100644 index 0000000000000000000000000000000000000000..81812f492838b439ea507d4afb763ff751c0a467 Binary files /dev/null and b/en/device-dev/faqs/figures/hi3516-selecting-the-visual-studio-code-application.png differ diff --git a/en/device-dev/faqs/figures/reason-no-python-soft-link.png b/en/device-dev/faqs/figures/reason-no-python-soft-link.png new file mode 100644 index 0000000000000000000000000000000000000000..b6bc36af5339ea5a4f67640e69836965b3776e17 Binary files /dev/null and b/en/device-dev/faqs/figures/reason-no-python-soft-link.png differ diff --git a/en/device-dev/faqs/figures/serial-port-displayed-after-the-u-boot-is-burnt.png b/en/device-dev/faqs/figures/serial-port-displayed-after-the-u-boot-is-burnt.png new file mode 100644 index 0000000000000000000000000000000000000000..ad4fd618860ca9f79e9bdc39436c3b2f9cdb72de Binary files /dev/null and b/en/device-dev/faqs/figures/serial-port-displayed-after-the-u-boot-is-burnt.png differ diff --git a/en/device-dev/faqs/figures/solution-add-soft-link.png b/en/device-dev/faqs/figures/solution-add-soft-link.png new file mode 100644 index 0000000000000000000000000000000000000000..9284df45bb1415d84f0325df85b4eb5c223281e8 Binary files /dev/null and b/en/device-dev/faqs/figures/solution-add-soft-link.png differ diff --git a/en/device-dev/faqs/figures/terminal-list.png b/en/device-dev/faqs/figures/terminal-list.png new file mode 100644 index 0000000000000000000000000000000000000000..a680547b305cccb4d8ea6cae3cbf2d046b841ff8 Binary files /dev/null and b/en/device-dev/faqs/figures/terminal-list.png differ diff --git a/en/device-dev/faqs/kernel.md b/en/device-dev/faqs/kernel.md new file mode 100644 index 0000000000000000000000000000000000000000..3a117be17d4ee2bf71358d2ba7339dba149e8cd7 --- /dev/null +++ b/en/device-dev/faqs/kernel.md @@ -0,0 +1,92 @@ +# Kernel + +- [Basic Kernel](#section263912372168) + - [What are the differences between APIs provided by LiteOS-A and LiteOS-M?](#section447571122918) + - [How do I analyze thread stack overflow?](#section8623141711293) + +- [File System](#section098519592162) + - [What should I do when the Hi3516 board fails to open the same file in write mode \(LiteOS-A\)?](#section517972255311) + - [What hardware platforms are supported by the LiteOS kernel?](#section868413518533) + - [What chip architectures are supported by the LiteOS kernel?](#section1131661465417) + +- [Third-party Components](#section971818231178) + - [What third-party components are supported by OpenHarmony?](#section74138185411) + - [What should I do if the key length verification fails when OpenSSL is used on OpenHarmony?](#section10564614135516) + - [Does setsockopt support SO\_RCVBUF and SO\_SNDBUF?](#section2093373215556) + +- [Compilation and Linking](#section10955302179) + - [How do I run an application developed by ARM Linux on LiteOS-A?](#section1164175713557) + - [What system is used for OpenHarmony compilation? What compiler is used?](#section132287223567) + - [For a third-party component that is independently compiled into a static library and used on LiteOS-M, what should I do when the component's global variable value is incorrect or the system is suspended after the component's function is called?](#section15189154225619) + - [What should I do if the message "use VFP register arguments, xxx.o does not" is displayed when LiteOS-A generates a target executable file?](#section193571012578) + - [What should I do when calling clock\_gettime obtains an incorrect time?](#section8973152015717) + + +## Basic Kernel + +### What are the differences between APIs provided by LiteOS-A and LiteOS-M? + +Basic kernel APIs are different. LiteOS-A provides the standard Portable Operating System Interface \(POSIX\), and LiteOS-M provides standard POSIX and Common Microcontroller Software Interface Standard \(CMSIS\) interfaces. To support cross-platform functions, standard interfaces such as POSIX are recommended for third-party adaptation. + +### How do I analyze thread stack overflow? + +**Symptom** + +The system is abnormal, and the message "CURRENT task _ThreadName_ stack overflow!" is displayed. + +**Solution** + +1. When creating the thread, double the thread stack size. If the problem does not recur after multiple attempts, the task stack size is insufficient and needs to be increased. +2. If the problem persists after the thread stack size is increased, check whether an ultra-large array is defined in the thread or whether recursive invoking exists in the process. +3. If the preceding causes are excluded, check whether memory corruption occurs. + +## File System + +### What should I do when the Hi3516 board fails to open the same file in write mode \(LiteOS-A\)? + +When a file is already open, it is not allowed to open the file in write mode again, because the Hi3516 board uses the FAT file system. + +### What hardware platforms are supported by the LiteOS kernel? + +LiteOS-A supports the Hi3516 and Hi3518 development boards. LiteOS-M supports the Hi3861 development board, STM32F103, STM32F429IGTb, and Nucleo\_f767zi. For details, see the **README.md** file in the **kernel/liteos\_m** directory. + +### What chip architectures are supported by the LiteOS kernel? + +LiteOS-M supports RISC-V, Cortex-M3, Cortex-M4, Cortex-M7, Cortex-M33, and Arm 9, and will support c-sky and Xtensa. LiteOS-A supports ARMv7-A and will support ARMv8-A. Any new update will be released in the OpenHarmony community. + +## Third-party Components + +### What third-party components are supported by OpenHarmony? + +Open-source components \(such as mbedTLS and LwIP\) and third-party libraries have been provided and can be directly used. In addition, standard POSIX is provided for adaptation. + +### What should I do if the key length verification fails when OpenSSL is used on OpenHarmony? + +Check whether the architecture type \(such as ARM and x86\) and the number of system bits \(32-bit and 64-bit\) are correctly selected in OpenSSL compilation options. + +### Does setsockopt support SO\_RCVBUF and SO\_SNDBUF? + +No. It does not support SO\_RCVBUF or SO\_SNDBUF. + +## Compilation and Linking + +### How do I run an application developed by ARM Linux on LiteOS-A? + +The application must be recompiled using the cross-compiler provided in OpenHarmony before it can run. + +### What system is used for OpenHarmony compilation? What compiler is used? + +LiteOS-A is compiled in the Linux environment by using the LLVM compiler. LiteOS-M can be compiled in the Linux or Windows environment by using compilers such as IAR, Keil, and GCC. + +### For a third-party component that is independently compiled into a static library and used on LiteOS-M, what should I do when the component's global variable value is incorrect or the system is suspended after the component's function is called? + +Check whether address-irrelevant compilation options, such as **-fPIE**, **-fpie**, **-fPIC**, and **-fpic**, exist in the third-party component compilation options. If yes, delete them and recompile the third-party component into a static library. + +### What should I do if the message "use VFP register arguments, xxx.o does not" is displayed when LiteOS-A generates a target executable file? + +Check whether the **-mfloat-abi=xxx**, **-mcpu=xxx**, and **-mfpu=xxx** compilation options are added during the compilation of **xxx.o**. If not, add them. + +### What should I do when calling clock\_gettime obtains an incorrect time? + +In **struct timespec**, **tv\_sec** is **time\_t**, which is of the long long type, and the print control character is **%lld**. Check whether the print control character in use is correct. + diff --git a/en/device-dev/faqs/overview-of-faqs.md b/en/device-dev/faqs/overview-of-faqs.md new file mode 100644 index 0000000000000000000000000000000000000000..b196c7ffe80e5337abf463a338bd15620bb1c673 --- /dev/null +++ b/en/device-dev/faqs/overview-of-faqs.md @@ -0,0 +1,138 @@ +# Overview of FAQs + +- [Environment Setup](#section93289248249) + - [Mini and Small Systems](#section197234983111) + +- [Compilation and Building](#section18826114693810) + - [Mini and Small Systems](#section693410399) + +- [Burning](#section6556741113712) + - [Mini and Small Systems](#section1029933713812) + +- [Kernel](#section13741125564211) + - [Basic Kernel](#section1723365191114) + - [File System](#section14523145918136) + - [Chip Adaptation](#section141541939159) + - [Third-party Components](#section4988163321816) + - [Compilation and Linking](#section080219574225) + +- [Porting](#section129331824154313) +- [Startup and Recovery](#section83501764443) +- [System Services](#section19567132114455) + - [Utils](#section3214181711465) + - [Visual Applications](#section295651815466) + - [HDC](#section178081876506) + + +FAQs are used to help developers solve problems frequently encountered during development. They cover a wide range of topics. + +## Environment Setup + +### Mini and Small Systems + +- [What should I do if garbled characters and segmentation faults occur during hb installation?](environment-setup.md#section36351051193919) +- [What should I do if the message "cannot import 'sysconfig' from 'distutils'" is displayed during hb installation?](environment-setup.md#section48221013144011) +- [What should I do if the message "module 'platform' has no attribute 'linux\_distribution'" is displayed during hb installation?](environment-setup.md#section10307193044111) +- [What should I do if the message "Could not find a version that satisfies the requirement ohos-build" is displayed during hb installation?](environment-setup.md#section8692735427) +- [What should I do when the message configure: error: no acceptable C compiler found in $PATH is displayed during Python 3 installation?](environment-setup.md#section870082884217) +- [What should I do when the message -bash: make: command not found is displayed during Python 3 installation?](environment-setup.md#section198707170455) +- [What should I do when the message zlib not available is displayed during Python 3 installation?](environment-setup.md#section85401445204518) +- [What should I do when the message No module named '\_ctypes' is displayed during Python 3 installation?](environment-setup.md#section12202694460) +- [What should I do when an error with lsb\_release occurs during kconfiglib installation?](environment-setup.md#section5803174135115) +- [What should I do if the message "ImportError: No module named apt\_pkg" is displayed during the execution of an unidentifiable command?](environment-setup.md#section510820516515) + +## Compilation and Building + +### Mini and Small Systems + +- [Invalid -- w Option](compilation-and-building-subsystem.md#section67961431372) +- [Library ncurses Not Found](compilation-and-building-subsystem.md#section199631617371) +- [mcopy not Found](compilation-and-building-subsystem.md#section937435175) +- [No riscv File or Directory](compilation-and-building-subsystem.md#section1115535018713) +- [No Crypto](compilation-and-building-subsystem.md#section17982573813) +- [Unexpected Operator](compilation-and-building-subsystem.md#section53663205819) +- [What should I do when the message Could not find a version that satisfies the requirement six\>=1.9.0 is displayed during compilation and building?](compilation-and-building-subsystem.md#section1917790845) +- [What should I do when the message cannot find -lgcc is displayed during compilation and building?](compilation-and-building-subsystem.md#section141771701647) +- [What should I do when the message indicating Python cannot be found is displayed during compilation and building?](compilation-and-building-subsystem.md#section51781202415) +- [What should I do when the message indicating Python 3 cannot be found is displayed during compilation and building?](compilation-and-building-subsystem.md#section1917950148) + +## Burning + +### Mini and Small Systems + +- ["Error: Opening COMxx: Access denied" Is Displayed After a Serial Port Is Selected for Burning](burning.md#section18988185615914) + +- [What should I do when the image failed to be burnt?](burning.md#section1370982513317) +- [What should I do when no command output is displayed?](burning.md#section183421944953) +- [What should I do when Windows-based PC failed to be connected to the board?](burning.md#section1215410450215) + +## Kernel + +### Basic Kernel + +- [What are the differences between APIs provided by LiteOS-A and LiteOS-M?](kernel.md#section447571122918) +- [How do I analyze thread stack overflow?](kernel.md#section8623141711293) + +### File System + +- [What should I do when the Hi3516 board fails to open the same file in write mode \(LiteOS-A\)?](kernel.md#section517972255311) + +### Chip Adaptation + +- [What hardware platforms are supported by the LiteOS kernel?](kernel.md#section868413518533) +- [What chip architectures are supported by the LiteOS kernel?](kernel.md#section1131661465417) + +### Third-party Components + +- [What third-party components are supported by OpenHarmony?](kernel.md#section74138185411) +- [What should I do if the key length verification fails when OpenSSL is used on OpenHarmony?](kernel.md#section10564614135516) +- [Does setsockopt support SO\_RCVBUF and SO\_SNDBUF?](kernel.md#section2093373215556) + +### Compilation and Linking + +- [How do I run an application developed by ARM Linux on LiteOS-A?](kernel.md#section1164175713557) +- [What system is used for OpenHarmony compilation? What compiler is used?](kernel.md#section132287223567) +- [For a third-party component that is independently compiled into a static library and used on LiteOS-M, what should I do when the component's global variable value is incorrect or the system is suspended after the component's function is called?](kernel.md#section15189154225619) +- [What should I do if the message "use VFP register arguments, xxx.o does not" is displayed when LiteOS-A generates a target executable file?](kernel.md#section193571012578) +- [What should I do when calling clock\_gettime obtains an incorrect time?](kernel.md#section8973152015717) + +## Porting + +- [How Do I Mount the Heap Memory to the Kernel?](porting.md#section21471536184914) + +## Startup and Recovery + +- [System startup interrupted due to "parse failed!" error](startup-and-recovery.md#section835662214302) +- [System automatically restarted again and again](startup-and-recovery.md#section3857921143117) +- [Failed to call the SetParameter or GetParameter API with correct parameter values](startup-and-recovery.md#section548818116328) + +## System Services + +### Utils + +- [1. Failure in running the KV store on the LiteOS-A kernel \(Hi3516 or Hi3518\) due to incorrect path setting for the KV store](system-applications.md#section16520347131511) + +### Visual Applications + +- [Is there a global variable that can be accessed by all pages?](system-applications.md#section187297991718) +- [How do I obtain DOM elements?](system-applications.md#section1833493719175) +- [How do I pass values between pages?](system-applications.md#section184283812183) +- [How do I scroll a list to an item?](system-applications.md#section11897734131811) +- [Does the component support multiple lines?](system-applications.md#section5872656121814) +- [Why is a component not displayed?](system-applications.md#section7397125317107) +- [How do I implement scrolling on a page?](system-applications.md#section338794422010) +- [Why do not the left and top attributes take effect?](system-applications.md#section2597193611217) +- [Why does not dynamic binding take effect?](system-applications.md#section6939050172115) +- [How do I implement relative and absolute positioning?](system-applications.md#section5547311192215) +- [How do I display or hide a component?](system-applications.md#section16107113352213) +- [What are the precautions for using the margin attribute?](system-applications.md#section1524910142314) +- [What are the precautions for event subscription?](system-applications.md#section1537132012231) +- [What are the precautions for using dynamic binding?](system-applications.md#section96561452236) +- [How does the loop attribute take effect for ?](system-applications.md#section690166112414) +- [What are the precautions for using an array?](system-applications.md#section1554552822414) + +### HDC + +- [hdc\_std Fails to Connect to a Device](system-applications.md#section1965012223257) +- [hdc\_std Fails to Run](system-applications.md#section1157575212515) + diff --git a/en/device-dev/faqs/porting.md b/en/device-dev/faqs/porting.md new file mode 100644 index 0000000000000000000000000000000000000000..d3cc2944c4484b600ab72e10db7593b8f3a5f969 --- /dev/null +++ b/en/device-dev/faqs/porting.md @@ -0,0 +1,39 @@ +# Porting + +- [How Do I Mount the Heap Memory to the Kernel?](#section21471536184914) + +## How Do I Mount the Heap Memory to the Kernel? + +- The following table describes the macros for configuring the kernel heap memory. You can configure them as required in the **target\_config.h** file. + +**Table 1** Macros for configuring the kernel heap memory + + + + + + + + + + + + + + + + +

Macro

+

Description

+

LOSCFG_SYS_EXTERNAL_HEAP

+

Specifies whether the internal kernel heap memory or the user heap memory will be used. The default value is 0 and indicates that the internal heap memory whose size is 0x10000 will be used. If you want to use the external heap memory, set this macro to 1.

+

LOSCFG_SYS_HEAP_ADDR

+

Specifies the start address of the kernel heap memory.

+

LOSCFG_SYS_HEAP_SIZE

+

Specifies the size of the kernel heap memory, that is, size of the memory block specified by LOSCFG_SYS_HEAP_ADDR.

+
+ +- Note: + +Ensure that the specified heap memory range is not used by other modules. Otherwise, functions of the heap memory will be damaged due to the heap memory corruption. + diff --git a/en/device-dev/faqs/public_sys-resources/icon-caution.gif b/en/device-dev/faqs/public_sys-resources/icon-caution.gif new file mode 100644 index 0000000000000000000000000000000000000000..6e90d7cfc2193e39e10bb58c38d01a23f045d571 Binary files /dev/null and b/en/device-dev/faqs/public_sys-resources/icon-caution.gif differ diff --git a/en/device-dev/faqs/public_sys-resources/icon-danger.gif b/en/device-dev/faqs/public_sys-resources/icon-danger.gif new file mode 100644 index 0000000000000000000000000000000000000000..6e90d7cfc2193e39e10bb58c38d01a23f045d571 Binary files /dev/null and b/en/device-dev/faqs/public_sys-resources/icon-danger.gif differ diff --git a/en/device-dev/faqs/public_sys-resources/icon-note.gif b/en/device-dev/faqs/public_sys-resources/icon-note.gif new file mode 100644 index 0000000000000000000000000000000000000000..6314297e45c1de184204098efd4814d6dc8b1cda Binary files /dev/null and b/en/device-dev/faqs/public_sys-resources/icon-note.gif differ diff --git a/en/device-dev/faqs/public_sys-resources/icon-notice.gif b/en/device-dev/faqs/public_sys-resources/icon-notice.gif new file mode 100644 index 0000000000000000000000000000000000000000..86024f61b691400bea99e5b1f506d9d9aef36e27 Binary files /dev/null and b/en/device-dev/faqs/public_sys-resources/icon-notice.gif differ diff --git a/en/device-dev/faqs/public_sys-resources/icon-tip.gif b/en/device-dev/faqs/public_sys-resources/icon-tip.gif new file mode 100644 index 0000000000000000000000000000000000000000..93aa72053b510e456b149f36a0972703ea9999b7 Binary files /dev/null and b/en/device-dev/faqs/public_sys-resources/icon-tip.gif differ diff --git a/en/device-dev/faqs/public_sys-resources/icon-warning.gif b/en/device-dev/faqs/public_sys-resources/icon-warning.gif new file mode 100644 index 0000000000000000000000000000000000000000..6e90d7cfc2193e39e10bb58c38d01a23f045d571 Binary files /dev/null and b/en/device-dev/faqs/public_sys-resources/icon-warning.gif differ diff --git a/en/device-dev/faqs/startup-and-recovery.md b/en/device-dev/faqs/startup-and-recovery.md new file mode 100644 index 0000000000000000000000000000000000000000..5bd7afc74519b3f039a4eba46101c43e186df8f9 --- /dev/null +++ b/en/device-dev/faqs/startup-and-recovery.md @@ -0,0 +1,57 @@ +# Startup and Recovery + +- [System startup interrupted due to "parse failed!" error](#section835662214302) +- [System automatically restarted again and again](#section3857921143117) +- [Failed to call the SetParameter or GetParameter API with correct parameter values](#section548818116328) + +## System startup interrupted due to "parse failed!" error + +**Problem** + +During system startup, the error message "\[Init\] InitReadCfg, parse failed! please check file /etc/init.cfg format." is displayed, and the startup is interrupted, as shown in the following figure. + +**Figure 1** Error information +![](figures/error-information.png "error-information") + +**Cause** + +During the modification of the **init.cfg** file, required commas \(,\) or parentheses are missing or unnecessary ones are added. As a result, the file's JSON format becomes invalid. + +**Solution** + +Check the **init.cfg** file and ensure that its format meets the JSON specifications. + +## System automatically restarted again and again + +**Problem** + +After the image burning is complete, the system keeps restarting. + +**Cause** + +Each service started by the init process has the **importance** attribute, as described in Table 3 in init Module. + +- If the attribute value is **0**, the init process does not need to restart the development board when the current service process exits. +- If the attribute value is **1**, the init process needs to restart the development board when the current service process exits. + +During the startup of a service whose **importance** is **1**, if the service exits due to a process crash or an error, the init process automatically restarts the development board. + +**Solution** + +1. View logs to identify the service that encounters a process crash or exits due to an error, rectify the issue, and then burn the image again. +2. Alternatively, change the value of **importance** to **0** for the service that exits due to a process crash or an error, and then burn the image again. In this way, the development board will not be restarted even if the service exits. + +## Failed to call the **SetParameter** or **GetParameter** API with correct parameter values + +**Problem** + +Calling the **SetParameter** or **GetParameter** API fails even if correct values are passed to all input parameters. + +**Cause** + +Permission verification has been enabled for the **SetParameter** and **GetParameter** APIs. If the UID of the caller is greater than 1000, that is, the caller does not have the permission to call these APIs, API calls will fail even if the parameters are correct. + +**Solution** + +No action is required. + diff --git a/en/device-dev/faqs/system-applications.md b/en/device-dev/faqs/system-applications.md new file mode 100644 index 0000000000000000000000000000000000000000..7bf65b072da8d9e09673adb02808ccf9b4319607 --- /dev/null +++ b/en/device-dev/faqs/system-applications.md @@ -0,0 +1,209 @@ +# System Applications + +- [Utils](#section639433461512) + - [1. Failure in running the KV store on the LiteOS-A kernel \(Hi3516 or Hi3518\) due to incorrect path setting for the KV store](#section16520347131511) + +- [Visual Applications](#section787718474161) + - [Is there a global variable that can be accessed by all pages?](#section187297991718) + - [How do I obtain DOM elements?](#section1833493719175) + - [How do I pass values between pages?](#section184283812183) + - [How do I scroll a list to an item?](#section11897734131811) + - [Does the component support multiple lines?](#section5872656121814) + - [Why is a component not displayed?](#section7397125317107) + - [How do I implement scrolling on a page?](#section338794422010) + - [Why do not the left and top attributes take effect?](#section2597193611217) + - [Why does not dynamic binding take effect?](#section6939050172115) + - [How do I implement relative and absolute positioning?](#section5547311192215) + - [How do I display or hide a component?](#section16107113352213) + - [What are the precautions for using the margin attribute?](#section1524910142314) + - [What are the precautions for event subscription?](#section1537132012231) + - [What are the precautions for using dynamic binding?](#section96561452236) + - [How does the loop attribute take effect for ?](#section690166112414) + - [What are the precautions for using an array?](#section1554552822414) + +- [HDC](#section412357182518) + - [hdc\_std Fails to Connect to a Device](#section1965012223257) + - [hdc\_std Fails to Run](#section1157575212515) + + +## Utils + +### 1. Failure in running the KV store on the LiteOS-A kernel \(Hi3516 or Hi3518\) due to incorrect path setting for the KV store + +**Problem** + +When the LiteOS-A kernel \(Hi3516 or Hi3518 platform\) directly calls the API provided by the KV store, the compiled executable program fails to run. + +**Possible Causes** + +The compiled executable program is run directly without being converted to an application using **AbilityKit** APIs. In this case, the Bundle Manager Service \(BMS\) cannot correctly set the path for storing application data during application installation. As a result, the KV store fails to run. + +**Solution** + +Call the **UtilsSetEnv** function of the KV store to set the data storage path. + +``` +UtilsSetEnv("/storage/com.huawei.kv"); +``` + +## Visual Applications + +### Is there a global variable that can be accessed by all pages? + +There is no such a global variable. + +### How do I obtain DOM elements? + +You can obtain DOM elements via the **ref** attribute. You can use methods of the obtained elements but cannot change their attributes. The sample code is as follows: + +``` + +
+ . + +
+ +/* index.js */ +export default { + data: { + images:[ + {src:"common/frame1.png"}, + {src:"common/frame2.png"}, + {src:"common/frame3.png"} + ] + }, + handleClick(){ + // Obtain the component through the $refs attribute. (The ref attribute of the component has been set to animator in the HML file.) + const animator = this.$refs.animator; + const state = animator.getState(); + if(state == "paused"){ + animator.resume(); + }else if(state == "stopped"){ + animator.start(); + }else{ + animator.pause(); + } + } +} +``` + +### How do I pass values between pages? + +You can pass values through **params** of the **router.replace** method. The sample code is as follows: + +Set **params** to the values to be passed on a page. + +``` +router.replace({ + uri:'pages/detail/detail', // URI of the page to switch to. + params:{transferData:this.data} // Data to be transferred. You need to define the data amount and name. +}); +``` + +Receive the passed values on another page. + +``` +onInit(){ + const data = this.transferData; // Receive the transferred data by the onInit function. +} +``` + +### How do I scroll a list to an item? + +Call the **scrollTo** method of the list. The input parameter of this method is the index of the target item. You can specify an item index, or obtain the index through the **scrollend** event. + +### Does the **** component support multiple lines? + +Yes. You can use the Enter key to start a new line. Alternatively, the component automatically starts a new line based on the content, without the need to set the height attribute of the text. + +### Why is a component not displayed? + +**Description** + +The component added to the **.hml** file cannot be displayed. + +**Possible Causes** + +- The width and height of the component may not be set. +- The style setting may be incorrect. + +**Solution** + +\(1\) Check whether the width and height values are set explicitly. + +\(2\) Check whether the style of the component is set correctly. + +### How do I implement scrolling on a page? + +There are three ways to implement page scrolling: **scroll**, ****, or ****. For a root component with **scroll** set, the scrolling effect is automatically implemented when the component size exceeds the screen size. For details, see the development specifications. + +### Why do not the **left** and **top** attributes take effect? + +**left** and **top** attributes must work with the **** component in addition to the root component. + +### Why does not dynamic binding take effect? + +The object or its attributes are not defined before dynamic binding. + +### How do I implement relative and absolute positioning? + +You can use the **** and **** \(with **top** and **left** attributes\) components. + +### How do I display or hide a component? + +You can use **display**, **show**, or **if**. When an **if** clause evaluates to **false**, the corresponding component will be removed from the VDOM. When **show** is set to **false**, the component will be invisible during rendering, but will not be removed from the VDOM. + +### What are the precautions for using the **margin** attribute? + +The **margin** attribute cannot be set for child components of the **** component. + +### What are the precautions for event subscription? + +Only one page exists when the application is running. Therefore, the **router.replace** function destroys the previous page and then creates a new one. For pages involving event subscription, an event should be subscribed every time a page is created, and unsubscribed before page switching. + +### What are the precautions for using dynamic binding? + +Do not use too many dynamic bindings because they consume too much memory. + +### How does the **loop** attribute take effect for ****? + +If the total length of the child components, except for the first and last ones, is greater than the length of ****, the **loop** attribute takes effect. + +### What are the precautions for using an array? + +Do not include too many elements in an array. Avoid frequent operations on a large array. + +## HDC + +### hdc\_std Fails to Connect to a Device + +- **Symptom** + + **\[Empty\]** is displayed in the output after the **hdc\_std list targets** command is executed. + +- **Solutions** + 1. The device cannot be identified. + + Check whether **HDC Device** exists in the universal serial bus device of the device manager. If **HDC Device** does not exist, the device cannot be connected. In this case, remove and then insert the device or burn the latest image for the device. + + 2. hdc\_std works improperly. + + Run the **hdc kill** or **hdc start -r** command to kill or restart the hdc service. Then, run the **hdc list targets** command to check whether device information can be obtained. + + 3. hdc\_std does not match the device. + + If the latest image is burnt on the device, the latest hdc\_std version must be used. As hdc\_std is updated continuously, obtain hdc\_std of the latest version from the **developtools\_hdc\_standard** repository in the **prebuilt** directory. + + + +### hdc\_std Fails to Run + +- **Symptom** + + The **hdc\_std.exe** file does not run after being clicked. + +- **Solutions** + + **hdc\_std.exe** requires no installation. It can be directly used on a disk or added to environment variables. Open the cmd window and run the **hdc\_std** command to use **hdc\_std.exe**. + + diff --git a/en/device-dev/get-code/sourcecode-acquire.md b/en/device-dev/get-code/sourcecode-acquire.md index 8ccf2c55e7f60fd80a151f3a23ae6b41a31e9e30..2f00491cc1ff1919411fd26d5c925456b97a1192 100644 --- a/en/device-dev/get-code/sourcecode-acquire.md +++ b/en/device-dev/get-code/sourcecode-acquire.md @@ -1,4 +1,4 @@ -# Source Code Acquisition +# Obtaining Source Code - [About OpenHarmony](#section6370143622110) - [Overview of Source Code Acquisition](#section12763342204) @@ -6,15 +6,14 @@ - [When to Use](#section10881513459) - [Prerequisites](#section102871547153314) - [How to Use](#section429012478331) - - [Method 2: Acquiring Source Code from DevEco Marketplace](#section463013147412) - [When to Use](#section26661067443) - [Prerequisites](#section17544943123315) - [How to Use](#section954619433333) - - [Method 3: Acquiring Source Code from a Mirror Site](#section1186691118430) - [Method 4: Acquiring Source Code from the GitHub Image Repository \(at 23:00 UTC Every Day\)](#section23448418360) -- [Source Code Directories](#section1072115612811) +- [ Source Code Directories](#section1072115612811) + ## About OpenHarmony @@ -174,9 +173,7 @@ You must install **Node.js** and HPM on your local PC. The installation proced To ensure the download performance, you are advised to download the source code or the corresponding solution from the image library of the respective site listed in the table below. ->![](../public_sys-resources/icon-note.gif) **NOTE:** ->- The table below provides only the sites for downloading the latest OpenHarmony master and LTS code. For details about how to obtain the source code of earlier versions, see the [Release-Notes](../../release-notes/Readme.md). ->- The Master 1.0 version is no longer maintained. +The table below provides only the sites for downloading the latest OpenHarmony master and LTS code. For details about how to obtain the source code of earlier versions, see the [Release-Notes](../../release-notes/Readme.md). **Table 1** Sites for acquiring source code @@ -248,7 +245,7 @@ To ensure the download performance, you are advised to download the source code

3.0

-

Download

+

Download

-

@@ -257,9 +254,9 @@ To ensure the download performance, you are advised to download the source code

Version Information

-

Site

+

Site

-

SHA-256 Verification Code

+

SHA-256 Verification Code

Beta version (for standard systems)

@@ -271,56 +268,11 @@ To ensure the download performance, you are advised to download the source code

Download

-

Full code (for standard systems)

- -

2.0 Canary

- -

Download (Site 1) Download (Site 2)

- -

Download

- - -

Full code (for mini and small systems)

- -

1.0 (no longer maintained)

- -

Download

- -

Download

- - -

Hi3861 solution (binary)

- -

1.0 (no longer maintained)

- -

Download

- -

Download

- - -

Hi3518 solution (binary)

- -

1.0 (no longer maintained)

- -

Download

- -

Download

- - -

Hi3516 solution (binary)

- -

1.0 (no longer maintained)

- -

Download

- -

Download

- -

RELEASE-NOTES

-

1.0 (no longer maintained)

+

2.2 Beta2

-

Download

+

Download

-

@@ -329,7 +281,7 @@ To ensure the download performance, you are advised to download the source code

Version Information

-

Site

+

Site

SHA-256 Verification Code

@@ -364,7 +316,7 @@ repo sync -c repo forall -c 'git lfs pull' ``` -## Source Code Directories +## Source Code Directories The following table describes the OpenHarmony source code directories. diff --git a/en/device-dev/guide/Readme-EN.md b/en/device-dev/guide/Readme-EN.md index 73cd1dffd06b51cb71f228b95168196583b7d16a..a21f8de99fe4e9973e63e6c08d5d1a5351b82e9e 100644 --- a/en/device-dev/guide/Readme-EN.md +++ b/en/device-dev/guide/Readme-EN.md @@ -1,32 +1,35 @@ # Development Examples -- [WLAN-connected Products](device-wifi.md) - - [LED Peripheral Control](device-wlan-led-outcontrol.md) - - [Third-Party SDK Integration](device-wlan-sdk.md) -- [Cameras Without a Screen](device-iotcamera.md) - - [Camera Control](device-iotcamera-control.md) - - [Overview](device-iotcamera-control-overview.md) - - [Development Guidelines](device-iotcamera-control-demo.md) - - [Photographing](device-iotcamera-control-demo-photodevguide.md) - - [Video Recording](device-iotcamera-control-demo-videodevguide.md) - - [Use Case](device-iotcamera-control-example.md) -- [Cameras with a Screen](device-camera.md) - - [Screen and Camera Control](device-camera-control.md) - - [Overview](device-camera-control-overview.md) - - [Development Guidelines](device-camera-control-demo.md) - - [Photographing](device-camera-control-demo-photoguide.md) - - [Video Recording](device-camera-control-demo-videoguide.md) - - [Previewing](device-camera-control-demo-previewguide.md) - - [Use Case](device-camera-control-example.md) - - [Visual Application Development](device-camera-visual.md) - - [Overview](device-camera-visual-overview.md) - - [Preparations](device-camera-visual-prepare.md) - - [Adding Pages](device-camera-visual-addpage.md) - - [Building the Home Page](device-camera-visual-firstpage.md) - - [Building the Details Page](device-camera-visual-details.md) - - [Debugging and Packaging](device-camera-visual-debug.md) - - [Running on the Device](device-camera-visual-run.md) - - [FAQs](device-camera-visual-faqs.md) -- [Development Guidelines on Clock Apps](device-clock-guide.md) -- [Development Example for Platform Drivers](device-driver-demo.md) -- [Development Example for Peripheral Drivers](device-outerdriver-demo.md) \ No newline at end of file +- [Mini- and Small-System Devices](device-lite.md) + - [WLAN-connected Products](device-wlan.md) + - [LED Peripheral Control](device-wlan-led.md) + - [LED Peripheral Control](device-wlan-led-outcontrol.md) + - [Third-Party SDK Integration](device-wlan-sdk.md) + - [Cameras Without a Screen](device-iotcamera.md) + - [Camera Control](device-iotcamera-control.md) + - [Overview](device-iotcamera-control-overview.md) + - [Development Guidelines](device-iotcamera-control-demo.md) + - [Photographing](device-iotcamera-control-demo-photodevguide.md) + - [Video Recording](device-iotcamera-control-demo-videodevguide.md) + - [Use Case](device-iotcamera-control-example.md) + - [Cameras with a Screen](device-camera.md) + - [Screen and Camera Control](device-camera-control.md) + - [Overview](device-camera-control-overview.md) + - [Development Guidelines](device-camera-control-demo.md) + - [Photographing](device-camera-control-demo-photoguide.md) + - [Video Recording](device-camera-control-demo-videoguide.md) + - [Previewing](device-camera-control-demo-previewguide.md) + - [Use Case](device-camera-control-example.md) + - [Visual Application Development](device-camera-visual.md) + - [Overview](device-camera-visual-overview.md) + - [Preparations](device-camera-visual-prepare.md) + - [Adding Pages](device-camera-visual-addpage.md) + - [Building the Home Page](device-camera-visual-firstpage.md) + - [Building the Details Page](device-camera-visual-details.md) + - [Debugging and Packaging](device-camera-visual-debug.md) + - [Running on the Device](device-camera-visual-run.md) + - [FAQs](device-camera-visual-faqs.md) +- [Standard-System Devices](device-standard.md) + - [Development Guidelines on Clock Apps](device-clock-guide.md) + - [Development Example for Platform Drivers](device-driver-demo.md) + - [Development Example for Peripheral Drivers](device-outerdriver-demo.md) \ No newline at end of file diff --git a/en/device-dev/guide/device-camera-control-demo-photoguide.md b/en/device-dev/guide/device-camera-control-demo-photoguide.md index eda733f15340836efaf5e6d25417821836bc333d..f355014896857760bfb5ff252b69b0608f1a1c67 100644 --- a/en/device-dev/guide/device-camera-control-demo-photoguide.md +++ b/en/device-dev/guide/device-camera-control-demo-photoguide.md @@ -363,7 +363,7 @@ None camKit->CreateCamera(camId, CamStateMng, eventHdlr); ``` -6. In the main process, synchronize configurations set by callback functions implemented in [step 1](#en-us_topic_0000001052170554_li378084192111), [step 2](#en-us_topic_0000001052170554_li8716104682913), and [step 3](#en-us_topic_0000001052170554_li6671035102514). +6. Based on the callback design in [1](#en-us_topic_0000001052170554_li378084192111), [2](#en-us_topic_0000001052170554_li8716104682913), and [3](#en-us_topic_0000001052170554_li6671035102514), perform related operations until the **OnCreated** callback obtains **cam\_**. ``` void OnCreated(Camera &c) override diff --git a/en/device-dev/guide/device-camera-control-example.md b/en/device-dev/guide/device-camera-control-example.md index 9e77598359a5ec1e410e39d9354f0d541ac367fb..2d599c0ef0ddc2e7bf69630bf5832cb6ad8229ed 100644 --- a/en/device-dev/guide/device-camera-control-example.md +++ b/en/device-dev/guide/device-camera-control-example.md @@ -3,7 +3,7 @@ This use case takes **camera\_sample** \(contained in the source code\) as an example for photographing, recording, and previewing on the development board. - You can obtain source code of the sample from **applications/sample/camera/media/camera\_sample.cpp**. -- Before running the sample camera, you need to compile, burn, and run the image. For details, see [Hi3516 Development Board](../quick-start/quickstart-lite-introduction-hi3516.md#section26131214194212). +- Before running the sample camera, you need to compile, burn, and run the image. For details, see [Hi3516 Development Board](../quick-start/oem_minitinier_des_3516.md#section26131214194212). >![](../public_sys-resources/icon-note.gif) **NOTE:** >After the development board is started, the home screen is loaded and displayed above the media layer by default. To prevent covering **camera\_sample**, you should remove the home screen during compilation or packaging. @@ -27,38 +27,38 @@ This use case takes **camera\_sample** \(contained in the source code\) as an 1. Run the **cd** command to go to the end path of the executable program and start **camera\_sample** by running the command in the following figure. **Figure 1** Starting camera\_sample - ![](figure/starting-camera_sample.png "starting-camera_sample") + ![](figures/starting-camera_sample.png "starting-camera_sample") The control commands are displayed as shown in the preceding figure. Press **S** to stop the current operation \(including video recording and preview\), and press **Q** to exit the program. 2. Press **1** to take a photo in JPG format. The photo is saved in the **/sdcard** directory and named **Capture\***. **Figure 2** Serial port logs displayed after the photographing command is executed - ![](figure/serial-port-logs-displayed-after-the-photographing-command-is-executed.png "serial-port-logs-displayed-after-the-photographing-command-is-executed") + ![](figures/serial-port-logs-displayed-after-the-photographing-command-is-executed.png "serial-port-logs-displayed-after-the-photographing-command-is-executed") To view the saved file, exit the program and enter the file system. To start the program again, return to the previous step. **Figure 3** Saved files - ![](figure/saved-files.png "saved-files") + ![](figures/saved-files.png "saved-files") 3. Press **2** to start recording. The video file is in MP4 format and saved in the **/sdcard** directory with the name **Record\***. Press **S** to stop recording. **Figure 4** Serial port logs displayed after the recording command is executed - ![](figure/serial-port-logs-displayed-after-the-recording-command-is-executed.png "serial-port-logs-displayed-after-the-recording-command-is-executed") + ![](figures/serial-port-logs-displayed-after-the-recording-command-is-executed.png "serial-port-logs-displayed-after-the-recording-command-is-executed") 4. Press **3** to start preview. The preview is displayed on the screen. Press **S** to stop preview. **Figure 5** Serial port logs displayed after the preview command is executed - ![](figure/serial-port-logs-displayed-after-the-preview-command-is-executed.png "serial-port-logs-displayed-after-the-preview-command-is-executed") + ![](figures/serial-port-logs-displayed-after-the-preview-command-is-executed.png "serial-port-logs-displayed-after-the-preview-command-is-executed") The following figure shows the preview. **Figure 6** Preview effect - ![](figure/preview-effect.jpg "preview-effect") + ![](figures/preview-effect.jpg "preview-effect") 5. Press **Q** to exit. **Figure 7** Serial port logs displayed after the exit command is executed - ![](figure/serial-port-logs-displayed-after-the-exit-command-is-executed.png "serial-port-logs-displayed-after-the-exit-command-is-executed") + ![](figures/serial-port-logs-displayed-after-the-exit-command-is-executed.png "serial-port-logs-displayed-after-the-exit-command-is-executed") diff --git a/en/device-dev/guide/device-camera-visual-addpage.md b/en/device-dev/guide/device-camera-visual-addpage.md index 2315fb68c61761574e12018baebf214b3006792a..42eae0107fbdff36aff7879586df0fedebc792b2 100644 --- a/en/device-dev/guide/device-camera-visual-addpage.md +++ b/en/device-dev/guide/device-camera-visual-addpage.md @@ -8,7 +8,7 @@ Upon creation of the project, the **index** page is automatically generated, which is the home page of AirQuality. [Figure 1](#fig16545205773718) shows the project directory. **Figure 1** Project directory -![](figure/project-directory.png "project-directory") +![](figures/project-directory.png "project-directory") ## Creating the Details Page @@ -17,18 +17,18 @@ To the details page, perform the following steps: 1. Right-click **pages** and choose **New** \> **JS Page** from the shortcut menu. **Figure 2** Adding a page - ![](figure/adding-a-page.png "adding-a-page") + ![](figures/adding-a-page.png "adding-a-page") 2. Enter the page name. **Figure 3** Entering the page name - ![](figure/entering-the-page-name.png "entering-the-page-name") + ![](figures/entering-the-page-name.png "entering-the-page-name") 3. Confirm the creation. The following figure shows the application project directory after the **detail** page is created. It contains a **.hml** layout file, a **.css** file, and a **.js** file \(containing service logic code\). **Figure 4** Complete project directory - ![](figure/complete-project-directory.png "complete-project-directory") + ![](figures/complete-project-directory.png "complete-project-directory") diff --git a/en/device-dev/guide/device-camera-visual-faqs.md b/en/device-dev/guide/device-camera-visual-faqs.md index 1a8fa2eae8d539e023e1914ca6b586efc9fe6d69..4e57b6551777c7e00d7b5dfcb1dea60f8e5c94a0 100644 --- a/en/device-dev/guide/device-camera-visual-faqs.md +++ b/en/device-dev/guide/device-camera-visual-faqs.md @@ -1,128 +1,148 @@ # FAQs -1. Is there a global variable that can be accessed by all pages? - - There is no such a global variable. - -2. How do I obtain DOM elements? - - You can obtain DOM elements via the **ref** attribute. You can use methods of the obtained elements but cannot change their attributes. The sample code is as follows: - - ``` - -
- . - -
- - /* index.js */ - export default { - data: { - images:[ - {src:"common/frame1.png"}, - {src:"common/frame2.png"}, - {src:"common/frame3.png"} - ] - }, - handleClick(){ - // Obtain the component through the $refs attribute. (The ref attribute of the component has been set to animator in the HML file.) - const animator = this.$refs.animator; - const state = animator.getState(); - if(state == "paused"){ - animator.resume(); - }else if(state == "stopped"){ - animator.start(); - }else{ - animator.pause(); - } +- [Visual Application FAQs](#section147421736145813) + - [Is there a global variable that can be accessed by all pages?](#section294382614018) + - [How do I obtain DOM elements?](#section1423713435019) + - [How do I pass values between pages?](#section119822143117) + - [How do I scroll a list to an item?](#section188663819111) + - [Does the component support multiple lines?](#section205741157418) + - [Why is a component not displayed?](#section1345810151025) + - [How do I implement scrolling on a page?](#section1724052813218) + - [Why do not the left and top attributes take effect?](#section34659571520) + - [Why does not dynamic binding take effect?](#section1758881511313) + - [How do I implement relative and absolute positioning?](#section1378730235) + - [How do I display or hide a component?](#section1243424718312) + - [What are the precautions for using the margin attribute?](#section7923357414) + - [What are the precautions for event subscription?](#section91641925548) + - [What are the precautions for using dynamic binding?](#section1292412431744) + - [How does the loop attribute take effect for ?](#section1136434952) + - [What are the precautions for using an array?](#section1979819133510) + + +## Visual Application FAQs + +### Is there a global variable that can be accessed by all pages? + +There is no such a global variable. + +### How do I obtain DOM elements? + +You can obtain DOM elements via the **ref** attribute. You can use methods of the obtained elements but cannot change their attributes. The sample code is as follows: + +``` + +
+ . + +
+ +/* index.js */ +export default { + data: { + images:[ + {src:"common/frame1.png"}, + {src:"common/frame2.png"}, + {src:"common/frame3.png"} + ] + }, + handleClick(){ + // Obtain the component through the $refs attribute. (The ref attribute of the component has been set to animator in the HML file.) + const animator = this.$refs.animator; + const state = animator.getState(); + if(state == "paused"){ + animator.resume(); + }else if(state == "stopped"){ + animator.start(); + }else{ + animator.pause(); } } - ``` +} +``` -3. How do I pass values between pages? +### How do I pass values between pages? - You can pass values through **params** of the **router.replace** method. The sample code is as follows: +You can pass values through **params** of the **router.replace** method. The sample code is as follows: - Set **params** to the values to be passed on a page. +Set **params** to the values to be passed on a page. - ``` - router.replace({ - uri:'pages/detail/detail', // URI of the page to switch to. - params:{transferData:this.data} // Data to be transferred. You need to define the data amount and name. - }); - ``` +``` +router.replace({ + uri:'pages/detail/detail', // URI of the page to switch to. + params:{transferData:this.data} // Data to be transferred. You need to define the data amount and name. +}); +``` - Receive the passed values on another page. +Receive the passed values on another page. - ``` - onInit(){ - const data = this.transferData; // Receive the transferred data by the onInit function. - } - ``` +``` +onInit(){ + const data = this.transferData; // Receive the transferred data by the onInit function. +} +``` -4. How do I scroll a list to an item? +### How do I scroll a list to an item? - Call the **scrollTo** method of the list. The input parameter of this method is the index of the target item. You can specify an item index, or obtain the index through the **scrollend** event. +Call the **scrollTo** method of the list. The input parameter of this method is the index of the target item. You can specify an item index, or obtain the index through the **scrollend** event. -5. Does the **** component support multiple lines? +### Does the **** component support multiple lines? - Yes. You can use the Enter key to start a new line. Alternatively, the component automatically starts a new line based on the content, without the need to set the height attribute of the text. +Yes. You can use the Enter key to start a new line. Alternatively, the component automatically starts a new line based on the content, without the need to set the height attribute of the text. -6. Why is a component not displayed? +### Why is a component not displayed? - **Description** +**Description** - The component added to the **.hml** file cannot be displayed. +The component added to the **.hml** file cannot be displayed. - **Possible Causes** +**Possible Causes** - - The width and height of the component may not be set. - - The style setting may be incorrect. +- The width and height of the component may not be set. +- The style setting may be incorrect. - **Solution** +**Solution** - \(1\) Check whether the width and height values are set explicitly. +\(1\) Check whether the width and height values are set explicitly. - \(2\) Check whether the style of the component is set correctly. +\(2\) Check whether the style of the component is set correctly. -7. How do I implement scrolling on a page? +### How do I implement scrolling on a page? - There are three ways to implement page scrolling: **scroll**, ****, or ****. For a root component with **scroll** set, the scrolling effect is automatically implemented when the component size exceeds the screen size. For details, see the development specifications. +There are three ways to implement page scrolling: **scroll**, ****, or ****. For a root component with **scroll** set, the scrolling effect is automatically implemented when the component size exceeds the screen size. For details, see the development specifications. -8. Why do not the **left** and **top** attributes take effect? +### Why do not the **left** and **top** attributes take effect? - **left** and **top** attributes must work with the **** component in addition to the root component. +**left** and **top** attributes must work with the **** component in addition to the root component. -9. Why does not dynamic binding take effect? +### Why does not dynamic binding take effect? - The object or its attributes are not defined before dynamic binding. +The object or its attributes are not defined before dynamic binding. -10. How do I implement relative and absolute positioning? +### How do I implement relative and absolute positioning? - You can use the **** and **** \(with **top** and **left** attributes\) components. +You can use the **** and **** \(with **top** and **left** attributes\) components. -11. How do I display or hide a component? +### How do I display or hide a component? - You can use **display**, **show**, or **if**. When an **if** clause evaluates to **false**, the corresponding component will be removed from the VDOM. When **show** is set to **false**, the component will be invisible during rendering, but will not be removed from the VDOM. +You can use **display**, **show**, or **if**. When an **if** clause evaluates to **false**, the corresponding component will be removed from the VDOM. When **show** is set to **false**, the component will be invisible during rendering, but will not be removed from the VDOM. -12. What are the precautions for using the **margin** attribute? +### What are the precautions for using the **margin** attribute? - The **margin** attribute cannot be set for child components of the **** component. +The **margin** attribute cannot be set for child components of the **** component. -13. What are the precautions for event subscription? +### What are the precautions for event subscription? - Only one page exists when the application is running. Therefore, the **router.replace** function destroys the previous page and then creates a new one. For event subscription pages, the event should be subscribed every time a page is created, and unsubscribed before page switching. +Only one page exists when the application is running. Therefore, the **router.replace** function destroys the previous page and then creates a new one. For pages involving event subscription, an event should be subscribed every time a page is created, and unsubscribed before page switching. -14. What are the precautions for using dynamic binding? +### What are the precautions for using dynamic binding? - Do not use too many dynamic bindings because they consume too much memory. +Do not use too many dynamic bindings because they consume too much memory. -15. How does the **loop** attribute take effect for ****? +### How does the **loop** attribute take effect for ****? - If the total length of the child components, except for the first and last ones, is greater than the length of ****, the **loop** attribute takes effect. +If the total length of the child components, except for the first and last ones, is greater than the length of ****, the **loop** attribute takes effect. -16. What are the precautions for using an array? - - Do not include too many elements in an array. Avoid frequent operations on a large array. +### What are the precautions for using an array? +Do not include too many elements in an array. Avoid frequent operations on a large array. diff --git a/en/device-dev/guide/device-camera-visual-firstpage.md b/en/device-dev/guide/device-camera-visual-firstpage.md index a610376cea65e108c28acfb8e25a22935fd7c6e5..65ca14d651942de443efd52928deb68432007183 100644 --- a/en/device-dev/guide/device-camera-visual-firstpage.md +++ b/en/device-dev/guide/device-camera-visual-firstpage.md @@ -2,7 +2,7 @@ The application home page displays air quality information of different cities. The home page provides two screens \(for two information bars\), which can be added as required. Each screen displays the air quality information of one city, including the Air Quality Index \(AQI\), city name, pollution level, update time, and data source. -The home page of AirQuality consists of three parts: +The home page of [AirQuality](device-camera-visual-overview.md) consists of three parts: - Title bar: displays the page title and provides an exit button. The title bar is fixed at the top of the page. - Information bar: displays air quality information. Multiple information bars can be added based on user requirements and support looping scroll. @@ -83,7 +83,7 @@ The following steps describe how to build the home page with a flexible layout t After the code is compiled, run the project on the simulator. The following figure shows the display effect. **Figure 1** Title bar - ![](figure/title-bar.png "title-bar") + ![](figures/title-bar.png "title-bar") 3. The **** component is required to implement the switching between screens. @@ -175,7 +175,7 @@ The following steps describe how to build the home page with a flexible layout t After the code is compiled, the display effect on the simulator is as follows. **Figure 2** Title bar and information bar - ![](figure/title-bar-and-information-bar.png "title-bar-and-information-bar") + ![](figures/title-bar-and-information-bar.png "title-bar-and-information-bar") 5. Add the indicator bar. Currently, the **** component does not support indicator settings. You need to implement a dots indicator by adding **** components and setting the style. Add a **** as a child component to the root node and set the style. Add two **** to the parent ****, set **border-radius** for the two child ****, and dynamically change the background colors of the **** components in the swiping event. @@ -187,7 +187,7 @@ The following steps describe how to build the home page with a flexible layout t ``` **Figure 3** Indicator bar - ![](figure/indicator-bar.png "indicator-bar") + ![](figures/indicator-bar.png "indicator-bar") 6. Set the style, animation effect, and dynamic data binding for all components. The complete sample code is as follows: diff --git a/en/device-dev/guide/device-camera-visual-overview.md b/en/device-dev/guide/device-camera-visual-overview.md index bf44297f7f42964b9883c939893a07bbbfe94a18..3164d864b9d888d69c518f8e62be57801d0b69d3 100644 --- a/en/device-dev/guide/device-camera-visual-overview.md +++ b/en/device-dev/guide/device-camera-visual-overview.md @@ -8,8 +8,6 @@ This document describes how to quickly set up an application development environ AirQuality displays information about the urban air quality on two pages, the home page and details page. The following GIF shows AirQuality on the DevEco Studio simulator. -**Figure 1** Display effects of the AirQuality - - -![](figure/video_2020-07-25_173141.gif) +**Figure 1** Display effect of the AirQuality application +![](figures/display-effect-of-the-airquality-application.gif "display-effect-of-the-airquality-application") diff --git a/en/device-dev/guide/device-camera-visual-prepare.md b/en/device-dev/guide/device-camera-visual-prepare.md index 52beaf139d6ebb7fbe8460cc8bb01fea5b1aa78c..b66b6e9ceec8f93eb1e0b072549c9c8369751d3e 100644 --- a/en/device-dev/guide/device-camera-visual-prepare.md +++ b/en/device-dev/guide/device-camera-visual-prepare.md @@ -15,13 +15,13 @@ Download and install DevEco Studio. For details, see the [HUAWEI DevEco Studio 2. Choose the **Smart Vision** for **Device** and **Empty Feature Ability** for **Template**. - ![](figure/en-us_image_0000001082434703.png) + ![](figures/empty-feature-ability.png) 3. Click **Next** and configure the project. - **Project Name**: project name. - **Package Name**: software package name. By default, this name will also be used as your application ID. Your application must have a unique ID to be released. - **Save Location**: path for storing project files. The path cannot contain Chinese characters or spaces. - - **Compatible API Version**: compatible API version. + - **Compatible API Version**: compatible API version of the SDK. 4. Click **Finish**. DevEco Studio will automatically generate the sample code and resources that match your project type. Wait until the project is created. diff --git a/en/device-dev/guide/device-camera-visual-run.md b/en/device-dev/guide/device-camera-visual-run.md index 3668d68d278d34f1aae9f34c0fcda9ca1157269d..72814c352e68d8565f6c1b3e8570d643655cca91 100644 --- a/en/device-dev/guide/device-camera-visual-run.md +++ b/en/device-dev/guide/device-camera-visual-run.md @@ -1,6 +1,6 @@ # Running on the Device -Before you install the application and run it on the development board, install the DevEco Device Tool by following operations provided in [HUAWEI DevEco Device Tool User Guide](https://device.harmonyos.com/en/docs/ide/user-guides/service_introduction-0000001050166905). Burn OpenHarmony into the development board, and run it on the board. For details about how to compile, burn, and run an image, see the [Hi3516 Development Board](../quick-start/quickstart-lite-introduction-hi3516.md#section26131214194212). After the image is running normally and the system is started properly, perform the following steps to install or uninstall the application: +Before you install the application and run it on the development board, install the DevEco Device Tool by following operations provided in [HUAWEI DevEco Device Tool User Guide](https://device.harmonyos.com/en/docs/ide/user-guides/service_introduction-0000001050166905). Burn OpenHarmony into the development board, and run it on the board. For details about how to compile, burn, and run an image, see the [Hi3516 Development Board](../quick-start/oem_minitinier_des_3516.md#section26131214194212). After the image is running normally and the system is started properly, perform the following steps to install or uninstall the application: 1. Store the compiled unsigned application installation package and installation tool in an SD card and insert the SD card into the development board slot. The installation tool is in **dev\_tools** of the directory where the image file is generated. 2. Run the following command to disable signature verification, which is enabled by default for application installation: @@ -20,7 +20,7 @@ Before you install the application and run it on the development board, install 4. After the application is installed, touch the application icon on the home screen to enter the application. **Figure 1** Home screen - ![](figure/home-screen.png "home-screen") + ![](figures/home-screen.png "home-screen") 5. \(Optional\) Uninstall the application. diff --git a/en/device-dev/guide/device-clock-guide.md b/en/device-dev/guide/device-clock-guide.md index 81918c4596a0dcea072e9c9f5489fec21ea0449a..c9d006e9c4ddf9fca5ad9cdf74bc524068e7ec11 100644 --- a/en/device-dev/guide/device-clock-guide.md +++ b/en/device-dev/guide/device-clock-guide.md @@ -19,11 +19,11 @@ The clock app displays the current time, as shown in the following figure. **Figure 1** Clock display effect -![](figure/clock.png) +![](figures/clock.png) ## Preparations -Download and install DevEco Studio. For details, see the [HUAWEI DevEco Studio User Guide](../../application-dev/quick-start/deveco-studio-(openharmony)-user-guide.md). +Download and install DevEco Studio. For details, see the [HUAWEI DevEco Studio User Guide](../../application-dev/quick-start/deveco-studio-user-guide-for-openharmony.md). ## How to Develop @@ -257,7 +257,7 @@ To build such an app, we can create a page that has a flexible layout with two r ## Signing and Packaging -After finishing writing the app code, you need to sign and package the app before running it on a real device. For details, see [Configuring the OpenHarmony App Signature](../../application-dev/quick-start/configuring-the-openharmony-app-signature.md). +After finishing writing the app code, you need to sign and package the app before running it on a real device. For details, see [Signing and Packaging Guide](../../application-dev/quick-start/configuring-openharmony-app-signature.md). ## Running on the Real Device diff --git a/en/device-dev/guide/device-driver-demo.md b/en/device-dev/guide/device-driver-demo.md index 3eb518594af5616fb000a8dde12b2cb30f81d489..7ae5f854cf295fd41092b61bc3851137af7a1935 100644 --- a/en/device-dev/guide/device-driver-demo.md +++ b/en/device-dev/guide/device-driver-demo.md @@ -19,18 +19,10 @@ This document uses the I2C driver as an example to describe how to develop platf The HDF provides a standard driver framework for common peripherals. To use the APIs provided by the HDF to perform operations on peripherals, you only need to adapt the specific driver to the HDF. -In this example, an I2C driver is used. [Figure 1](#fig148041484161) shows the sequence diagram of the I2C driver. +In this example, an I2C driver is used. [Figure 1](#fig9596628607) shows the sequence diagram of the I2C driver. -**Figure 1** I2C driver sequence diagram - - -![](figure/en-us_image_0000001169991055.png) - -- User Business: business-triggered driver -- i2cManagerEntry: entry to the I2C manager, which is used to register the I2C manager with the HDF -- I2cManager: I2C manager, which manages the I2C controller -- I2cCntlr: I2C controller -- i2cDriverEntry: entry to the I2C controller, which is used to register the I2C controller with the HDF +**Figure 1** I2C driver sequence diagram +![](figures/i2c-driver-sequence-diagram.png "i2c-driver-sequence-diagram") ## Preparations diff --git a/en/device-dev/guide/device-iotcamera-control-demo-photodevguide.md b/en/device-dev/guide/device-iotcamera-control-demo-photodevguide.md index a8da63373f6c284ee608836d504e38e5ee7c1569..adf90ccd674dc68969756ded3773c3bbab9111af 100644 --- a/en/device-dev/guide/device-iotcamera-control-demo-photodevguide.md +++ b/en/device-dev/guide/device-iotcamera-control-demo-photodevguide.md @@ -363,7 +363,7 @@ None camKit->CreateCamera(camId, CamStateMng, eventHdlr); ``` -6. In the main process, synchronize configurations set by callback functions implemented in [step 1](#en-us_topic_0000001052170554_li378084192111), [step 2](#en-us_topic_0000001052170554_li8716104682913), and [step 3](#en-us_topic_0000001052170554_li6671035102514). +6. Based on the callback design in [1](#en-us_topic_0000001052170554_li378084192111), [2](#en-us_topic_0000001052170554_li8716104682913), and [3](#en-us_topic_0000001052170554_li6671035102514), perform related operations until the **OnCreated** callback obtains **cam\_**. ``` void OnCreated(Camera &c) override diff --git a/en/device-dev/guide/device-iotcamera-control-example.md b/en/device-dev/guide/device-iotcamera-control-example.md index bb9875ea20896e4319e8124befa33a74a6c3f280..d2ab0fd2dbc859bd0f7e56ff1b3793896d409025 100644 --- a/en/device-dev/guide/device-iotcamera-control-example.md +++ b/en/device-dev/guide/device-iotcamera-control-example.md @@ -1,6 +1,6 @@ # Use Case -- For details about the development board, compilation, burning, and image running, see [Hi3518 Development Board](../quick-start/quickstart-lite-introduction-hi3518.md#section14815247616). A compilation result file of sample code is stored in **out/ipcamera\_hi3518ev300/dev\_tools/bin/camera\_sample**. You can copy the file to a TF card, or modify the compilation script of **camera\_sample** to copy the result to **rootfs.img**. +- For details about the development board, compilation, burning, and image running, see [Hi3518 Development Board](../quick-start/oem_minitinier_des_3518.md#section14815247616). A compilation result file of sample code is stored in **out/ipcamera\_hi3518ev300/dev\_tools/bin/camera\_sample**. You can copy the file to a TF card, or modify the compilation script of **camera\_sample** to copy the result to **rootfs.img**. Modify **output\_dir** in **applications/sample/camera/media/BUILD.gn**. @@ -18,28 +18,28 @@ 1. Run the **cd** command to go to the end path of the executable program and start **camera\_sample** by running the command in the following figure. **Figure 1** Starting camera\_sample - ![](figure/starting-camera_sample.png "starting-camera_sample") + ![](figures/starting-camera_sample.png "starting-camera_sample") The control commands are displayed as shown in the preceding figure. Press **S** to stop the current operation \(including video recording and preview\), and press **Q** to exit the program. 2. Press **1** to take a photo in JPG format. The photo is saved in the **/sdcard** directory and named **Capture\***. **Figure 2** Serial port logs displayed after the photographing command is executed - ![](figure/serial-port-logs-displayed-after-the-photographing-command-is-executed.png "serial-port-logs-displayed-after-the-photographing-command-is-executed") + ![](figures/serial-port-logs-displayed-after-the-photographing-command-is-executed.png "serial-port-logs-displayed-after-the-photographing-command-is-executed") To view the saved file, exit the program and enter the file system. To start the program again, return to the previous step. **Figure 3** Saved files - ![](figure/saved-files.png "saved-files") + ![](figures/saved-files.png "saved-files") 3. Press **2** to start recording. The video file is in MP4 format and saved in the **/sdcard** directory with the name **Record\***. Press **S** to stop recording. **Figure 4** Serial port logs displayed after the recording command is executed - ![](figure/serial-port-logs-displayed-after-the-recording-command-is-executed.png "serial-port-logs-displayed-after-the-recording-command-is-executed") + ![](figures/serial-port-logs-displayed-after-the-recording-command-is-executed.png "serial-port-logs-displayed-after-the-recording-command-is-executed") 4. Press **Q** to exit. **Figure 5** Serial port logs displayed after the exit command is executed - ![](figure/serial-port-logs-displayed-after-the-exit-command-is-executed.png "serial-port-logs-displayed-after-the-exit-command-is-executed") + ![](figures/serial-port-logs-displayed-after-the-exit-command-is-executed.png "serial-port-logs-displayed-after-the-exit-command-is-executed") diff --git a/en/device-dev/guide/device-lite.md b/en/device-dev/guide/device-lite.md new file mode 100644 index 0000000000000000000000000000000000000000..506b0beefeaad68acee95d488329dbf0d292ae7d --- /dev/null +++ b/en/device-dev/guide/device-lite.md @@ -0,0 +1,9 @@ +# Mini- and Small-System Devices + +- **[WLAN-connected Products](device-wlan.md)** + +- **[Cameras Without a Screen](device-iotcamera.md)** + +- **[Cameras with a Screen](device-camera.md)** + + diff --git a/en/device-dev/guide/device-outerdriver-demo.md b/en/device-dev/guide/device-outerdriver-demo.md index 5ae984c6f5fbd954f55c4f8cca4e329cd26e0950..64ca3a3c009910f869ec4a3baa2700c791e80463 100644 --- a/en/device-dev/guide/device-outerdriver-demo.md +++ b/en/device-dev/guide/device-outerdriver-demo.md @@ -28,7 +28,7 @@ This document describes how to develop a touchscreen driver on the Hi3516D V300 The touchscreen integrated circuit \(IC\) provided by the Hi3516D V300 development board is GT911, which uses the standard inter-integrated circuit \(I2C\) to communicate with the development board and connects to the main board through the 6-pin flexible flat cable. The following figure shows the distribution of the 6 pins and their connection. -![](figure/绘图1.png) +![](figures/6-pin-distribution-and-physical-connection.png) ### Input Driver Model @@ -44,7 +44,7 @@ For details about the input driver model, see [Touchscreen Overview](../driver/ ## Setting Up the Environment -Follow the instructions in [Environment Setup for Standard System](../quick-start/quickstart-standard.md). +Follow the instructions in [Environment Setup for Standard System](../quick-start/quickstart-standard-overview.md). >![](../public_sys-resources/icon-notice.gif) **NOTICE:** >This development example applies to standard, small, and mini OpenHarmony systems. The following sections use the standard system as an example. You can refer to the specific guide for your system to set up the environment. @@ -335,7 +335,7 @@ The input driver model consists of three parts of drivers. To develop a brand-ne **touch\_gt911.o** is the content added in this example. -2. Build source code and burn images. For details, see the related sections in [Getting Started for Standard System](../nottoctopics/en-us_topic_0000001135402541.md#section375234715135). +2. Build source code and burn images. For details, see the related sections in [Getting Started for Standard System](../quick-start/quickstart-standard.md). ## Debugging and Verification diff --git a/en/device-dev/guide/device-standard.md b/en/device-dev/guide/device-standard.md new file mode 100644 index 0000000000000000000000000000000000000000..7ee3a52b865cae093c77aa56f784bbd56bcc91f3 --- /dev/null +++ b/en/device-dev/guide/device-standard.md @@ -0,0 +1,9 @@ +# Standard-System Devices + +- **[Development Guidelines on Clock Apps](device-clock-guide.md)** + +- **[Development Example for Platform Drivers](device-driver-demo.md)** + +- **[Development Example for Peripheral Drivers](device-outerdriver-demo.md)** + + diff --git a/en/device-dev/guide/device-wlan-led-outcontrol.md b/en/device-dev/guide/device-wlan-led-outcontrol.md index af9d86a4d2b7b3b514e02d41b2e0949fc386cc50..ec884688cc8a7443943317a83f8203a71bd807ee 100644 --- a/en/device-dev/guide/device-wlan-led-outcontrol.md +++ b/en/device-dev/guide/device-wlan-led-outcontrol.md @@ -10,7 +10,7 @@ Based on the Hi3861 platform, the OpenHarmony WLAN module provides abundant peri ## Development -1. Complete the operations described in [Getting Started with Hi3861](../quick-start/quickstart-lite-introduction-hi3861.md#section19352114194115). +1. Complete the operations described in [Getting Started with Hi3861](../quick-start/oem_minitinier_des_3861.md#section19352114194115). LED control examples are stored in the file **applications/sample/wifi-iot/app/iothardware/led\_example.c**. @@ -101,10 +101,10 @@ Based on the Hi3861 platform, the OpenHarmony WLAN module provides abundant peri ## Verification -For details about the compilation and burning processes, see [Building Source Code](../quick-start/quickstart-lite-steps-board3861-connection.md#section191121332125319) and [Burning Images](../quick-start/quickstart-lite-steps-board3861-connection.md#section19458165166) in the _Getting Started with Hi3861_. +For details about the compilation and burning processes, see [Building Source Code](../quick-start/quickstart-lite-steps-hi3861-connection.md#section191121332125319) and [Burning Images](../quick-start/quickstart-lite-steps-hi3861-connection.md#section3288165814218) in the _Getting Started with Hi3861_. After the preceding two steps are complete, press the **RST** button to reset the module. If the LED blinks periodically as expected, the verification is passed. **Figure 1** LED blinking -![](figure/led-blinking.gif "led-blinking") +![](figures/led-blinking.gif "led-blinking") diff --git a/en/device-dev/guide/device-wlan-led.md b/en/device-dev/guide/device-wlan-led.md new file mode 100644 index 0000000000000000000000000000000000000000..3e7c9e9ef49d53ee8f82557daacc18db4eb9d99e --- /dev/null +++ b/en/device-dev/guide/device-wlan-led.md @@ -0,0 +1,5 @@ +# LED Peripheral Control + +- **[LED Peripheral Control](device-wlan-led-outcontrol.md)** + + diff --git a/en/device-dev/guide/device-wlan-sdk.md b/en/device-dev/guide/device-wlan-sdk.md index dee530d9b864c0a98ddcde0288576294c69769f5..c33274024590c39d111925ee0962c7a9a8d5079a 100644 --- a/en/device-dev/guide/device-wlan-sdk.md +++ b/en/device-dev/guide/device-wlan-sdk.md @@ -121,7 +121,7 @@ Before building **libs**, you must perform the following steps: After the preceding operations are complete, run the **hb build -T //domains/iot/link:iot** command in the root directory of the code and then check whether the target library file is generated in the **out/hispark\_pegasus/wifiiot\_hispark\_pegasus/libs/** directory. -![](figure/en-us_image_0000001078563230.png) +![](figures/device-wlan-sdk-files.png) Copy the library file to the **device/hisilicon/hispark\_pegasus/sdk\_liteos/3rd\_sdk/demolink/libs/** directory and delete the **.c** and **.h** files from the **domains/iot/link/libbuild/** directory. diff --git a/en/device-dev/guide/device-wlan-touch.md b/en/device-dev/guide/device-wlan-touch.md new file mode 100644 index 0000000000000000000000000000000000000000..5ff4442e9710c245f56d5c303493ee3d5ad742d4 --- /dev/null +++ b/en/device-dev/guide/device-wlan-touch.md @@ -0,0 +1,19 @@ +# OneHop + +- **[Overview](onehop-overview.md)** + +- **[Preparations](onehop-dev-prerequisites.md)** + +- **[Developing the Hi3861 Development Board](onehop-dev-hi3861.md)** + +- **[Developing Atomic Services](onehop-dev-atomic-service.md)** + +- **[Writing an NFC Tag](onehop-write-nfc-info.md)** + +- **[Configuring a Service Association Intent](onehop-configuration-device-tag.md)** + +- **[Tapping to Launch an Atomic Service](onehop-open-atomic-service.md)** + +- **[References](onehop-reference-info.md)** + + diff --git a/en/device-dev/guide/device-wifi.md b/en/device-dev/guide/device-wlan.md similarity index 57% rename from en/device-dev/guide/device-wifi.md rename to en/device-dev/guide/device-wlan.md index 791c0edb6895af3ebf0e6712799ce2a8459a5930..e4618dfb06cc8140fa3072cad3c2a0ec484dceb4 100644 --- a/en/device-dev/guide/device-wifi.md +++ b/en/device-dev/guide/device-wlan.md @@ -1,6 +1,8 @@ # WLAN-connected Products -- **[LED Peripheral Control](device-wlan-led-outcontrol.md)** +- **[OneHop](device-wlan-touch.md)** + +- **[LED Peripheral Control](device-wlan-led.md)** - **[Third-Party SDK Integration](device-wlan-sdk.md)** diff --git a/en/device-dev/guide/device.md b/en/device-dev/guide/device.md index 894af2e23daf71222d293f844a2132856d49245b..651da70de63631e3aeec538fea3974a9fe75b122 100644 --- a/en/device-dev/guide/device.md +++ b/en/device-dev/guide/device.md @@ -1,15 +1,7 @@ -# Device Development Guidelines +# Devices -- **[WLAN-connected Products](device-wifi.md)** +- **[Mini- and Small-System Devices](device-lite.md)** -- **[Cameras Without a Screen](device-iotcamera.md)** - -- **[Cameras with a Screen](device-camera.md)** - -- **[Development Guidelines on Clock Apps](device-clock-guide.md)** - -- **[Development Example for Platform Drivers](device-driver-demo.md)** - -- **[Development Example for Peripheral Drivers](device-outerdriver-demo.md)** +- **[Standard-System Devices](device-standard.md)** diff --git a/en/device-dev/guide/figures/2021-01-27_170334-9.png b/en/device-dev/guide/figures/2021-01-27_170334-9.png new file mode 100644 index 0000000000000000000000000000000000000000..5b573a4ddfe89fe25cb1b567736823244fdb9e97 Binary files /dev/null and b/en/device-dev/guide/figures/2021-01-27_170334-9.png differ diff --git "a/en/device-dev/guide/figure/\347\273\230\345\233\2761.png" b/en/device-dev/guide/figures/6-pin-distribution-and-physical-connection.png similarity index 100% rename from "en/device-dev/guide/figure/\347\273\230\345\233\2761.png" rename to en/device-dev/guide/figures/6-pin-distribution-and-physical-connection.png diff --git a/en/device-dev/guide/figures/ability-gallery-service.png b/en/device-dev/guide/figures/ability-gallery-service.png new file mode 100644 index 0000000000000000000000000000000000000000..9c978562dbf0f49feb6f55e4abbd722febcc726d Binary files /dev/null and b/en/device-dev/guide/figures/ability-gallery-service.png differ diff --git a/en/device-dev/guide/figures/ability-test.png b/en/device-dev/guide/figures/ability-test.png new file mode 100644 index 0000000000000000000000000000000000000000..9718ef6bb1eaa084069bd716963af47f196d2383 Binary files /dev/null and b/en/device-dev/guide/figures/ability-test.png differ diff --git a/en/device-dev/guide/figures/add_tools.png b/en/device-dev/guide/figures/add_tools.png new file mode 100644 index 0000000000000000000000000000000000000000..8737e531e2536d7e7e485af539ace34ea747da8d Binary files /dev/null and b/en/device-dev/guide/figures/add_tools.png differ diff --git a/en/device-dev/guide/figure/adding-a-page.png b/en/device-dev/guide/figures/adding-a-page.png similarity index 100% rename from en/device-dev/guide/figure/adding-a-page.png rename to en/device-dev/guide/figures/adding-a-page.png diff --git a/en/device-dev/guide/figures/build-project.png b/en/device-dev/guide/figures/build-project.png new file mode 100644 index 0000000000000000000000000000000000000000..24c23b9f35a4a1edaf57f6dd983c32138adf8594 Binary files /dev/null and b/en/device-dev/guide/figures/build-project.png differ diff --git a/en/device-dev/guide/figures/build-success.png b/en/device-dev/guide/figures/build-success.png new file mode 100644 index 0000000000000000000000000000000000000000..26d93f832bef054618d31d8e2cecf6684ecdb891 Binary files /dev/null and b/en/device-dev/guide/figures/build-success.png differ diff --git a/en/device-dev/guide/figures/burn_settings.png b/en/device-dev/guide/figures/burn_settings.png new file mode 100644 index 0000000000000000000000000000000000000000..a510dcecc23495dc515a8deecce580a660cf721b Binary files /dev/null and b/en/device-dev/guide/figures/burn_settings.png differ diff --git a/en/device-dev/guide/figures/choose-nfc.png b/en/device-dev/guide/figures/choose-nfc.png new file mode 100644 index 0000000000000000000000000000000000000000..081ec7447c1701b2fd531a49da5492098f19907a Binary files /dev/null and b/en/device-dev/guide/figures/choose-nfc.png differ diff --git a/en/device-dev/guide/figures/choose-product-id.png b/en/device-dev/guide/figures/choose-product-id.png new file mode 100644 index 0000000000000000000000000000000000000000..28f68adb980f92fd4915100e4ccafb0bc313fe74 Binary files /dev/null and b/en/device-dev/guide/figures/choose-product-id.png differ diff --git a/en/device-dev/guide/figures/choose-requested-product-id.png b/en/device-dev/guide/figures/choose-requested-product-id.png new file mode 100644 index 0000000000000000000000000000000000000000..71766ee591ee7bb3a9beab459d67e94dd1edb6e4 Binary files /dev/null and b/en/device-dev/guide/figures/choose-requested-product-id.png differ diff --git a/en/device-dev/guide/figures/choose-template.png b/en/device-dev/guide/figures/choose-template.png new file mode 100644 index 0000000000000000000000000000000000000000..2932ec5fd69fc4e786c698afdbf95ab64e23be1d Binary files /dev/null and b/en/device-dev/guide/figures/choose-template.png differ diff --git a/en/device-dev/guide/figure/clock.png b/en/device-dev/guide/figures/clock.png similarity index 100% rename from en/device-dev/guide/figure/clock.png rename to en/device-dev/guide/figures/clock.png diff --git a/en/device-dev/guide/figure/complete-project-directory.png b/en/device-dev/guide/figures/complete-project-directory.png similarity index 100% rename from en/device-dev/guide/figure/complete-project-directory.png rename to en/device-dev/guide/figures/complete-project-directory.png diff --git a/en/device-dev/guide/figures/component-reference-code.png b/en/device-dev/guide/figures/component-reference-code.png new file mode 100644 index 0000000000000000000000000000000000000000..21b9b6e4cb88a620d07cf7c37a3795b9adc87397 Binary files /dev/null and b/en/device-dev/guide/figures/component-reference-code.png differ diff --git a/en/device-dev/guide/figures/configure-project.png b/en/device-dev/guide/figures/configure-project.png new file mode 100644 index 0000000000000000000000000000000000000000..f1f80f3a77db74d3f730e13b165a1113e699c04f Binary files /dev/null and b/en/device-dev/guide/figures/configure-project.png differ diff --git a/en/device-dev/guide/figures/console.png b/en/device-dev/guide/figures/console.png new file mode 100644 index 0000000000000000000000000000000000000000..bf7cdf4e3bf09762cc5750da8eb1fcab114b9d6c Binary files /dev/null and b/en/device-dev/guide/figures/console.png differ diff --git a/en/device-dev/guide/figures/control-module-icon.png b/en/device-dev/guide/figures/control-module-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..45f126abf60662d98f881d884d8483557a5ea831 Binary files /dev/null and b/en/device-dev/guide/figures/control-module-icon.png differ diff --git a/en/device-dev/guide/figures/control-module.png b/en/device-dev/guide/figures/control-module.png new file mode 100644 index 0000000000000000000000000000000000000000..a515a1739fe19fbce722621e26b39cc1239a11d4 Binary files /dev/null and b/en/device-dev/guide/figures/control-module.png differ diff --git a/en/device-dev/guide/figures/copy-hals-and-winder.png b/en/device-dev/guide/figures/copy-hals-and-winder.png new file mode 100644 index 0000000000000000000000000000000000000000..966e00018189222882bb6b1ef13c8599e75eadbf Binary files /dev/null and b/en/device-dev/guide/figures/copy-hals-and-winder.png differ diff --git a/en/device-dev/guide/figures/date-and-time-picker.png b/en/device-dev/guide/figures/date-and-time-picker.png new file mode 100644 index 0000000000000000000000000000000000000000..06eb0c04dcd1a426f4d2d8033e0b1306408a648e Binary files /dev/null and b/en/device-dev/guide/figures/date-and-time-picker.png differ diff --git a/en/device-dev/guide/figures/date-picker.png b/en/device-dev/guide/figures/date-picker.png new file mode 100644 index 0000000000000000000000000000000000000000..fd08cbb096aa2396a6881ac6988f3f5774ed0a06 Binary files /dev/null and b/en/device-dev/guide/figures/date-picker.png differ diff --git a/en/device-dev/guide/figure/en-us_image_0000001078563230.png b/en/device-dev/guide/figures/device-wlan-sdk-files.png similarity index 100% rename from en/device-dev/guide/figure/en-us_image_0000001078563230.png rename to en/device-dev/guide/figures/device-wlan-sdk-files.png diff --git a/en/device-dev/guide/figures/display-component.png b/en/device-dev/guide/figures/display-component.png new file mode 100644 index 0000000000000000000000000000000000000000..1a4b6daa3bb19cc207029a6975dc9c22e44cfed7 Binary files /dev/null and b/en/device-dev/guide/figures/display-component.png differ diff --git a/en/device-dev/guide/figure/video_2020-07-25_173141.gif b/en/device-dev/guide/figures/display-effect-of-the-airquality-application.gif similarity index 100% rename from en/device-dev/guide/figure/video_2020-07-25_173141.gif rename to en/device-dev/guide/figures/display-effect-of-the-airquality-application.gif diff --git a/en/device-dev/guide/figures/edit-configurations.png b/en/device-dev/guide/figures/edit-configurations.png new file mode 100644 index 0000000000000000000000000000000000000000..a9657f5b25dd269d6189ad9308b05da2c8c55e40 Binary files /dev/null and b/en/device-dev/guide/figures/edit-configurations.png differ diff --git a/en/device-dev/guide/figure/en-us_image_0000001082434703.png b/en/device-dev/guide/figures/empty-feature-ability.png similarity index 100% rename from en/device-dev/guide/figure/en-us_image_0000001082434703.png rename to en/device-dev/guide/figures/empty-feature-ability.png diff --git a/en/device-dev/guide/figure/entering-the-page-name.png b/en/device-dev/guide/figures/entering-the-page-name.png similarity index 100% rename from en/device-dev/guide/figure/entering-the-page-name.png rename to en/device-dev/guide/figures/entering-the-page-name.png diff --git a/en/device-dev/guide/figures/enum-component.png b/en/device-dev/guide/figures/enum-component.png new file mode 100644 index 0000000000000000000000000000000000000000..5932d8a32cdbd1dd8a43a9439ae53ea608d9430c Binary files /dev/null and b/en/device-dev/guide/figures/enum-component.png differ diff --git a/en/device-dev/guide/figures/enum-dialog.png b/en/device-dev/guide/figures/enum-dialog.png new file mode 100644 index 0000000000000000000000000000000000000000..711f56980462d6f57ba0389b50419aea838d10a3 Binary files /dev/null and b/en/device-dev/guide/figures/enum-dialog.png differ diff --git a/en/device-dev/guide/figures/fa-information.png b/en/device-dev/guide/figures/fa-information.png new file mode 100644 index 0000000000000000000000000000000000000000..100a876ac7e5fb3062f50e11e1a12146b2bab49e Binary files /dev/null and b/en/device-dev/guide/figures/fa-information.png differ diff --git a/en/device-dev/guide/figures/harmonyos-tag.png b/en/device-dev/guide/figures/harmonyos-tag.png new file mode 100644 index 0000000000000000000000000000000000000000..2d82b4b1600692a0ddc457f913e8016018634630 Binary files /dev/null and b/en/device-dev/guide/figures/harmonyos-tag.png differ diff --git a/en/device-dev/guide/figures/harmonyos-test-ability-model.png b/en/device-dev/guide/figures/harmonyos-test-ability-model.png new file mode 100644 index 0000000000000000000000000000000000000000..f26812841a6204c5156995045b02ca1c5338e184 Binary files /dev/null and b/en/device-dev/guide/figures/harmonyos-test-ability-model.png differ diff --git a/en/device-dev/guide/figures/harmonyos-test-ability.png b/en/device-dev/guide/figures/harmonyos-test-ability.png new file mode 100644 index 0000000000000000000000000000000000000000..f5336179d609c3a8f57e63107a5ae0c95281b7cd Binary files /dev/null and b/en/device-dev/guide/figures/harmonyos-test-ability.png differ diff --git a/en/device-dev/guide/figures/hi3861-burning-succeeded-13.png b/en/device-dev/guide/figures/hi3861-burning-succeeded-13.png new file mode 100644 index 0000000000000000000000000000000000000000..3628f3f4778012a577d4ee28c703669eb5533594 Binary files /dev/null and b/en/device-dev/guide/figures/hi3861-burning-succeeded-13.png differ diff --git a/en/device-dev/guide/figures/hi3861-record-the-serial-port-number-10.png b/en/device-dev/guide/figures/hi3861-record-the-serial-port-number-10.png new file mode 100644 index 0000000000000000000000000000000000000000..43496f076a463ec6fbf320b358a32505284ff40f Binary files /dev/null and b/en/device-dev/guide/figures/hi3861-record-the-serial-port-number-10.png differ diff --git a/en/device-dev/guide/figures/hi3861-restart-the-development-board-12.png b/en/device-dev/guide/figures/hi3861-restart-the-development-board-12.png new file mode 100644 index 0000000000000000000000000000000000000000..e6b632288105421a07bd4f8d542293deb0d35fd2 Binary files /dev/null and b/en/device-dev/guide/figures/hi3861-restart-the-development-board-12.png differ diff --git a/en/device-dev/guide/figures/hi3861-upload-11.png b/en/device-dev/guide/figures/hi3861-upload-11.png new file mode 100644 index 0000000000000000000000000000000000000000..8dde7632636856203030c2abf0867f03abaafcba Binary files /dev/null and b/en/device-dev/guide/figures/hi3861-upload-11.png differ diff --git a/en/device-dev/guide/figure/home-screen.png b/en/device-dev/guide/figures/home-screen.png similarity index 100% rename from en/device-dev/guide/figure/home-screen.png rename to en/device-dev/guide/figures/home-screen.png diff --git a/en/device-dev/guide/figure/en-us_image_0000001169991055.png b/en/device-dev/guide/figures/i2c-driver-sequence-diagram.png similarity index 100% rename from en/device-dev/guide/figure/en-us_image_0000001169991055.png rename to en/device-dev/guide/figures/i2c-driver-sequence-diagram.png diff --git a/en/device-dev/guide/figures/import-project-confirm.png b/en/device-dev/guide/figures/import-project-confirm.png new file mode 100644 index 0000000000000000000000000000000000000000..27fe1d133a31b275a2788cab1f5b37dd3450a7df Binary files /dev/null and b/en/device-dev/guide/figures/import-project-confirm.png differ diff --git a/en/device-dev/guide/figures/import-project-setting.png b/en/device-dev/guide/figures/import-project-setting.png new file mode 100644 index 0000000000000000000000000000000000000000..b522b9b1e490b5ba65a0afd021cd5f472110136c Binary files /dev/null and b/en/device-dev/guide/figures/import-project-setting.png differ diff --git a/en/device-dev/guide/figures/import-project.png b/en/device-dev/guide/figures/import-project.png new file mode 100644 index 0000000000000000000000000000000000000000..5ba534eaf39165891a31c7837ae7ff4126f6414c Binary files /dev/null and b/en/device-dev/guide/figures/import-project.png differ diff --git a/en/device-dev/guide/figures/increase-decrease-component.png b/en/device-dev/guide/figures/increase-decrease-component.png new file mode 100644 index 0000000000000000000000000000000000000000..9682d0c59724f7f32f316148e7fb84d17e3a0382 Binary files /dev/null and b/en/device-dev/guide/figures/increase-decrease-component.png differ diff --git a/en/device-dev/guide/figure/indicator-bar.png b/en/device-dev/guide/figures/indicator-bar.png similarity index 100% rename from en/device-dev/guide/figure/indicator-bar.png rename to en/device-dev/guide/figures/indicator-bar.png diff --git a/en/device-dev/guide/figures/info-dialog.png b/en/device-dev/guide/figures/info-dialog.png new file mode 100644 index 0000000000000000000000000000000000000000..ca79a10ce965a312c803e5826e472d0c1b4100c7 Binary files /dev/null and b/en/device-dev/guide/figures/info-dialog.png differ diff --git a/en/device-dev/guide/figures/launch-atomic-service-procedure.png b/en/device-dev/guide/figures/launch-atomic-service-procedure.png new file mode 100644 index 0000000000000000000000000000000000000000..4560ab4ce023873e1ef05e6ef452375ed50883a0 Binary files /dev/null and b/en/device-dev/guide/figures/launch-atomic-service-procedure.png differ diff --git a/en/device-dev/guide/figure/led-blinking.gif b/en/device-dev/guide/figures/led-blinking.gif similarity index 100% rename from en/device-dev/guide/figure/led-blinking.gif rename to en/device-dev/guide/figures/led-blinking.gif diff --git a/en/device-dev/guide/figures/multi-column-picker.png b/en/device-dev/guide/figures/multi-column-picker.png new file mode 100644 index 0000000000000000000000000000000000000000..53f32e8a8cde61da704e9ae659030c3fcd93e3e9 Binary files /dev/null and b/en/device-dev/guide/figures/multi-column-picker.png differ diff --git a/en/device-dev/guide/figures/multifunction-component.png b/en/device-dev/guide/figures/multifunction-component.png new file mode 100644 index 0000000000000000000000000000000000000000..62a70a366de541497c869831bc231f60753c06b8 Binary files /dev/null and b/en/device-dev/guide/figures/multifunction-component.png differ diff --git a/en/device-dev/guide/figures/onehop-develop-procedure.png b/en/device-dev/guide/figures/onehop-develop-procedure.png new file mode 100644 index 0000000000000000000000000000000000000000..f3e7102e986823405b04af7f762926550f362d37 Binary files /dev/null and b/en/device-dev/guide/figures/onehop-develop-procedure.png differ diff --git a/en/device-dev/guide/figures/onehop-procedure.png b/en/device-dev/guide/figures/onehop-procedure.png new file mode 100644 index 0000000000000000000000000000000000000000..b33573f4111300ae7f7c1132339fdf35a50a5d4a Binary files /dev/null and b/en/device-dev/guide/figures/onehop-procedure.png differ diff --git a/en/device-dev/guide/figures/place-product-diagram.png b/en/device-dev/guide/figures/place-product-diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..b7fe68aadf4a045bd8657054a07d3d4328b004ca Binary files /dev/null and b/en/device-dev/guide/figures/place-product-diagram.png differ diff --git a/en/device-dev/guide/figure/preview-effect.jpg b/en/device-dev/guide/figures/preview-effect.jpg similarity index 100% rename from en/device-dev/guide/figure/preview-effect.jpg rename to en/device-dev/guide/figures/preview-effect.jpg diff --git a/en/device-dev/guide/figures/process-component.png b/en/device-dev/guide/figures/process-component.png new file mode 100644 index 0000000000000000000000000000000000000000..1189bb4a0166bd28f1652863633270a14a880bf9 Binary files /dev/null and b/en/device-dev/guide/figures/process-component.png differ diff --git a/en/device-dev/guide/figure/project-directory.png b/en/device-dev/guide/figures/project-directory.png similarity index 100% rename from en/device-dev/guide/figure/project-directory.png rename to en/device-dev/guide/figures/project-directory.png diff --git a/en/device-dev/guide/figures/project-structure.png b/en/device-dev/guide/figures/project-structure.png new file mode 100644 index 0000000000000000000000000000000000000000..f398e88cdee262566526d9cceecf06b0bbb83028 Binary files /dev/null and b/en/device-dev/guide/figures/project-structure.png differ diff --git a/en/device-dev/guide/figures/project_settings.png b/en/device-dev/guide/figures/project_settings.png new file mode 100644 index 0000000000000000000000000000000000000000..f869bc8e66050bd10c558724fa210fb1a84163f4 Binary files /dev/null and b/en/device-dev/guide/figures/project_settings.png differ diff --git a/en/device-dev/guide/figures/radio-dialog.png b/en/device-dev/guide/figures/radio-dialog.png new file mode 100644 index 0000000000000000000000000000000000000000..bf72de195c375ef902ebcd343a212767616cf300 Binary files /dev/null and b/en/device-dev/guide/figures/radio-dialog.png differ diff --git a/en/device-dev/guide/figures/request-product-id.png b/en/device-dev/guide/figures/request-product-id.png new file mode 100644 index 0000000000000000000000000000000000000000..0475d074078981b3efb2f9d47178aa48bd1ad9e8 Binary files /dev/null and b/en/device-dev/guide/figures/request-product-id.png differ diff --git a/en/device-dev/guide/figures/reversal-component.png b/en/device-dev/guide/figures/reversal-component.png new file mode 100644 index 0000000000000000000000000000000000000000..24760b8b92af7b414aba747f4b35453a3093e1f1 Binary files /dev/null and b/en/device-dev/guide/figures/reversal-component.png differ diff --git a/en/device-dev/guide/figures/run-entry.png b/en/device-dev/guide/figures/run-entry.png new file mode 100644 index 0000000000000000000000000000000000000000..7cd572c6ebbb57e8d33b38df67c0fd0bb26fc4cc Binary files /dev/null and b/en/device-dev/guide/figures/run-entry.png differ diff --git a/en/device-dev/guide/figure/saved-files.png b/en/device-dev/guide/figures/saved-files.png similarity index 100% rename from en/device-dev/guide/figure/saved-files.png rename to en/device-dev/guide/figures/saved-files.png diff --git a/en/device-dev/guide/figure/serial-port-logs-displayed-after-the-exit-command-is-executed.png b/en/device-dev/guide/figures/serial-port-logs-displayed-after-the-exit-command-is-executed.png similarity index 100% rename from en/device-dev/guide/figure/serial-port-logs-displayed-after-the-exit-command-is-executed.png rename to en/device-dev/guide/figures/serial-port-logs-displayed-after-the-exit-command-is-executed.png diff --git a/en/device-dev/guide/figure/serial-port-logs-displayed-after-the-photographing-command-is-executed.png b/en/device-dev/guide/figures/serial-port-logs-displayed-after-the-photographing-command-is-executed.png similarity index 100% rename from en/device-dev/guide/figure/serial-port-logs-displayed-after-the-photographing-command-is-executed.png rename to en/device-dev/guide/figures/serial-port-logs-displayed-after-the-photographing-command-is-executed.png diff --git a/en/device-dev/guide/figure/serial-port-logs-displayed-after-the-preview-command-is-executed.png b/en/device-dev/guide/figures/serial-port-logs-displayed-after-the-preview-command-is-executed.png similarity index 100% rename from en/device-dev/guide/figure/serial-port-logs-displayed-after-the-preview-command-is-executed.png rename to en/device-dev/guide/figures/serial-port-logs-displayed-after-the-preview-command-is-executed.png diff --git a/en/device-dev/guide/figure/serial-port-logs-displayed-after-the-recording-command-is-executed.png b/en/device-dev/guide/figures/serial-port-logs-displayed-after-the-recording-command-is-executed.png similarity index 100% rename from en/device-dev/guide/figure/serial-port-logs-displayed-after-the-recording-command-is-executed.png rename to en/device-dev/guide/figures/serial-port-logs-displayed-after-the-recording-command-is-executed.png diff --git a/en/device-dev/guide/figures/set-config-i2c-support.png b/en/device-dev/guide/figures/set-config-i2c-support.png new file mode 100644 index 0000000000000000000000000000000000000000..1921ee61abb7bf05674558121ebb6c812dc627df Binary files /dev/null and b/en/device-dev/guide/figures/set-config-i2c-support.png differ diff --git a/en/device-dev/guide/figures/set-sn-number.png b/en/device-dev/guide/figures/set-sn-number.png new file mode 100644 index 0000000000000000000000000000000000000000..c8035452ec2d2844bad9639494c9b8311650220c Binary files /dev/null and b/en/device-dev/guide/figures/set-sn-number.png differ diff --git a/en/device-dev/guide/figure/starting-camera_sample.png b/en/device-dev/guide/figures/starting-camera_sample.png similarity index 100% rename from en/device-dev/guide/figure/starting-camera_sample.png rename to en/device-dev/guide/figures/starting-camera_sample.png diff --git a/en/device-dev/guide/figures/text-picker.png b/en/device-dev/guide/figures/text-picker.png new file mode 100644 index 0000000000000000000000000000000000000000..84b6223f94db63c3a12c571b1e52b34948dff528 Binary files /dev/null and b/en/device-dev/guide/figures/text-picker.png differ diff --git a/en/device-dev/guide/figures/time-picker.png b/en/device-dev/guide/figures/time-picker.png new file mode 100644 index 0000000000000000000000000000000000000000..dba5c5fc20951b0bd8805578bf303909230bafb4 Binary files /dev/null and b/en/device-dev/guide/figures/time-picker.png differ diff --git a/en/device-dev/guide/figure/title-bar-and-information-bar.png b/en/device-dev/guide/figures/title-bar-and-information-bar.png similarity index 100% rename from en/device-dev/guide/figure/title-bar-and-information-bar.png rename to en/device-dev/guide/figures/title-bar-and-information-bar.png diff --git a/en/device-dev/guide/figure/title-bar.png b/en/device-dev/guide/figures/title-bar.png similarity index 100% rename from en/device-dev/guide/figure/title-bar.png rename to en/device-dev/guide/figures/title-bar.png diff --git a/en/device-dev/guide/figures/write-to-buffer.png b/en/device-dev/guide/figures/write-to-buffer.png new file mode 100644 index 0000000000000000000000000000000000000000..f2701a424e5c9c7c6c3f852c0ae4d2ac9e74a2bf Binary files /dev/null and b/en/device-dev/guide/figures/write-to-buffer.png differ diff --git a/en/device-dev/guide/figures/written-to-tag.png b/en/device-dev/guide/figures/written-to-tag.png new file mode 100644 index 0000000000000000000000000000000000000000..15a2850869a3a0bf23133dac213ec5ad8cf372e4 Binary files /dev/null and b/en/device-dev/guide/figures/written-to-tag.png differ diff --git a/en/device-dev/kernel/Readme-EN.md b/en/device-dev/kernel/Readme-EN.md index 86c4084c5fa70b97c2d9998ee822fad69700f144..01ff40387c6f6816aea29dc6941e7c7b660f2d85 100644 --- a/en/device-dev/kernel/Readme-EN.md +++ b/en/device-dev/kernel/Readme-EN.md @@ -173,6 +173,15 @@ - [Memory Information Statistics](kernel-small-debug-memory-info.md) - [Memory Leak Check](kernel-small-debug-memory-leak.md) - [Memory Corruption Check](kernel-small-debug-memory-corrupt.md) + - [User-Mode Memory Debugging](kernel-small-debug-user.md) + - [Basic Concepts](kernel-small-debug-user-concept.md) + - [Working Principles](kernel-small-debug-user-function.md) + - [Usage](kernel-small-debug-user-guide.md) + - [API Description](kernel-small-debug-user-guide-api.md) + - [How to Use](kernel-small-debug-user-guide-use.md) + - [Calling APIs](kernel-small-debug-user-guide-use-api.md) + - [Using the CLI](kernel-small-debug-user-guide-use-cli.md) + - [Typical Memory Problems](kernel-small-debug-user-faqs.md) - [Other Kernel Debugging Methods](kernel-small-debug-other.md) - [Dying Gasp](kernel-small-debug-trace-other-lastwords.md) - [Common Fault Locating Methods](kernel-small-debug-trace-other-faqs.md) diff --git a/en/device-dev/kernel/figure/adding-a-check-value-to-the-node-header-information.png b/en/device-dev/kernel/figure/adding-a-check-value-to-the-node-header-information.png new file mode 100644 index 0000000000000000000000000000000000000000..9a49391cd3d662305134251f4ee4261c10852106 Binary files /dev/null and b/en/device-dev/kernel/figure/adding-a-check-value-to-the-node-header-information.png differ diff --git a/en/device-dev/kernel/figure/dynamic-memory-core-algorithm.png b/en/device-dev/kernel/figure/dynamic-memory-core-algorithm.png index 226466c21b0f7375c9ef70f340ad573f2916a674..bd73700c41d62b47005ad0612c74f2823a1921a9 100644 Binary files a/en/device-dev/kernel/figure/dynamic-memory-core-algorithm.png and b/en/device-dev/kernel/figure/dynamic-memory-core-algorithm.png differ diff --git a/en/device-dev/kernel/figure/heap-memory-node-information.png b/en/device-dev/kernel/figure/heap-memory-node-information.png new file mode 100644 index 0000000000000000000000000000000000000000..131519e92cadb00d4ae33f180fba7e410120f98f Binary files /dev/null and b/en/device-dev/kernel/figure/heap-memory-node-information.png differ diff --git a/en/device-dev/kernel/figure/heap-memory-node-linked-list.png b/en/device-dev/kernel/figure/heap-memory-node-linked-list.png new file mode 100644 index 0000000000000000000000000000000000000000..17c3d03c4b35ad7b8d31e9ec091d683d498a0d90 Binary files /dev/null and b/en/device-dev/kernel/figure/heap-memory-node-linked-list.png differ diff --git a/en/device-dev/kernel/figure/layout-of-the-memory-allocated-by-using-the-mmap-mechanism-of-malloc.png b/en/device-dev/kernel/figure/layout-of-the-memory-allocated-by-using-the-mmap-mechanism-of-malloc.png new file mode 100644 index 0000000000000000000000000000000000000000..ff50b0e8ef50063df83834091a8d0c0992372599 Binary files /dev/null and b/en/device-dev/kernel/figure/layout-of-the-memory-allocated-by-using-the-mmap-mechanism-of-malloc.png differ diff --git a/en/device-dev/kernel/figure/process-of-locating-the-code-lines-for-a-memory-leak.png b/en/device-dev/kernel/figure/process-of-locating-the-code-lines-for-a-memory-leak.png new file mode 100644 index 0000000000000000000000000000000000000000..a6913eb1699f73e3ac187195cb79533823d1f592 Binary files /dev/null and b/en/device-dev/kernel/figure/process-of-locating-the-code-lines-for-a-memory-leak.png differ diff --git a/en/device-dev/kernel/figure/process-of-releasing-memory.png b/en/device-dev/kernel/figure/process-of-releasing-memory.png new file mode 100644 index 0000000000000000000000000000000000000000..a8e6e991fc5a81574ad92c44d45bff71c450bbc3 Binary files /dev/null and b/en/device-dev/kernel/figure/process-of-releasing-memory.png differ diff --git a/en/device-dev/kernel/kernel-small-debug-user-concept.md b/en/device-dev/kernel/kernel-small-debug-user-concept.md new file mode 100644 index 0000000000000000000000000000000000000000..e7deb11d9233d832e793fe3bd55f05adab2859de --- /dev/null +++ b/en/device-dev/kernel/kernel-small-debug-user-concept.md @@ -0,0 +1,6 @@ +# Basic Concepts + +The musl libc library of the debug version provides maintenance and test methods, such as memory leak check, heap memory statistics, memory corruption check, and backtrace, to improve the efficiency of locating memory problems in user space. + +Instrumentation is performed on the **malloc** and **free** APIs to log key node information. When memory is requested and released by a program, the memory node integrity is checked. When the program ends, memory statistics are provided for identifying memory leaks. + diff --git a/en/device-dev/kernel/kernel-small-debug-user-faqs.md b/en/device-dev/kernel/kernel-small-debug-user-faqs.md new file mode 100644 index 0000000000000000000000000000000000000000..ec114f13d974efbdd966f916e6e905c73af42648 --- /dev/null +++ b/en/device-dev/kernel/kernel-small-debug-user-faqs.md @@ -0,0 +1,52 @@ +# Typical Memory Problems + +- [Use After Free \(UAF\)](#section4427132815445) +- [Double Free](#section827194818458) +- [Heap Memory Node Corrupted](#section1763741216461) + +## Use After Free \(UAF\) + +- Requested memory block less than or equal to 0x1c000 bytes: + + After the memory is released: + + Read operation: If the magic number \(0xFEFEFEFE\) is read from the memory block released, UAF occurs. + + >![](../public_sys-resources/icon-note.gif) **NOTE:** + >After **free** is called, the heap memory will not be released to the heap memory pool immediately. Instead, the heap memory is placed in a queue with a fixed length and filled with the magic number 0xFE. When the queue is full, the memory block first placed in the queue is released to the heap memory pool first. + + Write operation: The memory debugging module cannot detect UAF errors from write operations. + + +- Requested memory block greater than 0x1c000 bytes: + + The heap memory greater than 0x1c000 bytes must be requested by calling the **mmap** API via **malloc**. If the heap memory is accessed after being released, the user program will become abnormal \(because the memory region has been unmapped\). + + +## Double Free + +Double free errors occur when **free\(\)** is called more than once with the same memory address as an argument. When a double free error occurs, the user program exits unexpectedly. + +## Heap Memory Node Corrupted + +- Requested memory block less than or equal to 0x1c000 bytes: + + When a heap memory node is corrupted, the user program exits unexpectedly, and the call stack that requests the heap memory of the node corrupted is output. The memory debugging module, however, cannot debug the memory corrupted by a wild pointer. For example, if the user program mem\_check has heap memory overwriting, you can use the command line to obtain the possible location of the memory corruption. + + ``` + OHOS # ./mem_check --mwatch + OHOS # + ==PID:6== Memory integrity information: + [TID:28 allocated addr: 0x272e1ea0, size: 0x120] The possible attacker was allocated from: + #00: [0x640e8] -> /lib/libc.so + #01: [0x21d0] -> mem_check + ``` + + You can use the call stack parsing script to parse the call stack information. + + +- Requested memory block greater than 0x1c000 bytes: + + When a large memory block \(greater than 0x1c000 bytes\) is requested by calling the **mmap** API via **malloc**, one more page of **PAGE\_SIZE** is allocated at the start and end of the memory region. The two pages are neither readable nor writeable. Any read or write operation to the pages may cause an exception of the user program. + + diff --git a/en/device-dev/kernel/kernel-small-debug-user-function.md b/en/device-dev/kernel/kernel-small-debug-user-function.md new file mode 100644 index 0000000000000000000000000000000000000000..4c0397279316be57dc4e092683852c2827a726b1 --- /dev/null +++ b/en/device-dev/kernel/kernel-small-debug-user-function.md @@ -0,0 +1,58 @@ +# Working Principles + +- [Memory Leak Check](#section142061581018) +- [Heap Memory Statistics](#section136902041337) +- [Memory Integrity Check](#section196491231761) + +## Memory Leak Check + +The memory debugging module maintains 128 \(that is the maximum number of threads supported in the system\) linked lists for each process. The index of each linked list is the thread ID. + +When memory is requested, key information is saved to the memory node control block, which is inserted to the corresponding linked list based on the thread ID. + +When memory is released, the system matches the memory node control block based on the memory address to be released and deletes the control block. + +**Figure 1** Heap memory node linked list +![](figure/heap-memory-node-linked-list.png "heap-memory-node-linked-list") + +When memory is allocated, the returned address is saved in a link register \(LR\). During the process running, the system adds information, such as the LR corresponding to the suspected leak, to the memory node control block. [Figure 2](#fig716011269106) shows the heap memory node information. + +**Figure 2** Heap memory node information +![](figure/heap-memory-node-information.png "heap-memory-node-information") + +**TID** indicates the thread ID; **PID** indicates the process ID; **ptr** indicates the address of the memory requested; **size** indicates the size of the requested memory; **lr\[_n_\]** indicates the address of the call stack, and _n_ is configurable. + +When memory is released, the input parameter pointer in the **free** API is used to match the **ptr** field of the memory node. If the pointer is the same as the **ptr** field of the memory node, the memory node control block will be deleted. + +You can export the memory debugging information of each process through the serial port or file, and use the addr2line tool to convert the exported information into the code lines that cause memory leaks. In this way, the memory leakage problem can be solved. + +**Figure 3** Process of locating the code lines for a memory leak +![](figure/process-of-locating-the-code-lines-for-a-memory-leak.png "process-of-locating-the-code-lines-for-a-memory-leak") + +## Heap Memory Statistics + +You can collect statistics on the percentage of heap memory requested by each thread to provide data support for optimizing memory usage of user programs. The **malloc** and **free** APIs are involved in user-mode heap memory statistics. As shown in [Figure 1](#fig4294145810543), each process maintains 128 linked lists, and the index of each linked list is a thread ID. When heap memory is requested, the **ptr** and **size** information is recorded in the memory node control block, which is inserted to a linked list with the thread ID as the header. When the heap memory is released, the corresponding heap memory block is removed from the linked list based on the **ptr**. In addition, the system calculates the total heap memory used by the current thread and updates its heap memory usage and peak heap memory usage. + +## Memory Integrity Check + +- If the memory requested by using **malloc** is less than or equal to 0x1c000 bytes, the heap allocation algorithm is used to allocate memory. + + When a user program requests heap memory, information such as the check value is added to the heap memory node. If the check value is abnormal, it is probably that the previous heap memory block is overwritten. Currently, the scenario where the check value is damaged by a wild pointer cannot be identified. When memory is allocated or released, the memory node check value is verified. If the memory node is corrupted and the verification fails, the following information is output: TID, PID, and call stack information saved when the previous heap memory block of the corrupted node is allocated. You can use the addr2line tool to obtain the specific code line and rectify the fault. + + **Figure 4** Adding a check value to the node header information + ![](figure/adding-a-check-value-to-the-node-header-information.png "adding-a-check-value-to-the-node-header-information") + + When heap memory is released by using **free**, the memory block is not released immediately. Instead, the magic number 0xFE is written into the memory block, which is then placed in the free queue to prevent the memory block from being allocated by **malloc** within a certain period of time. When a wild pointer or **use-after-free** operation is performed to read the memory, an exception can be detected. However, this mechanism does not apply to write operations. + + **Figure 5** Process of releasing memory + ![](figure/process-of-releasing-memory.png "process-of-releasing-memory") + + +- If the memory requested by using **malloc** is greater than 0x1c000 bytes, **mmap** is used to allocate memory. + + When **mmap** is used to request a large memory block, one more page is allocated at the start and end of the memory region. The current **PAGE\_SIZE** of each page is **0x1000**. The permissions of the two pages are set to **PROT\_NONE** \(no read or write permission\) by using the **mprotect** API to prevent out-of-bounds read and write of memory. If out-of-bounds read and write of memory occurs, the user program becomes abnormal because the user does not have the read or write permission. The code logic can be identified based on the abnormal call stack information. + + **Figure 6** Layout of the memory allocated by using the **mmap** mechanism of **malloc** + ![](figure/layout-of-the-memory-allocated-by-using-the-mmap-mechanism-of-malloc.png "layout-of-the-memory-allocated-by-using-the-mmap-mechanism-of-malloc") + + diff --git a/en/device-dev/kernel/kernel-small-debug-user-guide-api.md b/en/device-dev/kernel/kernel-small-debug-user-guide-api.md new file mode 100644 index 0000000000000000000000000000000000000000..dd4edac33c85d74bfb8bda00e278c2d0988675c7 --- /dev/null +++ b/en/device-dev/kernel/kernel-small-debug-user-guide-api.md @@ -0,0 +1,55 @@ +# API Description + +**Table 1** Memory debugging module APIs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Category

+

API

+

Description

+

Memory debugging

+

mem_check_init

+

Initializes the memory check module.

+

watch_mem

+

Obtains the thread-level heap memory usage.

+

check_leak

+

Checks for heap memory leaks.

+

check_heap_integrity

+

Checks the heap memory integrity.

+

Call stack backtracking

+

backtrace

+

Obtains the address information of the call stack.

+

backtrace_symbols

+

Obtains symbol information based on address information.

+

print_trace

+

Prints call stack information.

+
+ diff --git a/en/device-dev/kernel/kernel-small-debug-user-guide-use-api.md b/en/device-dev/kernel/kernel-small-debug-user-guide-use-api.md new file mode 100644 index 0000000000000000000000000000000000000000..5ed88069026d5cb7f980f77409895b34b801815a --- /dev/null +++ b/en/device-dev/kernel/kernel-small-debug-user-guide-use-api.md @@ -0,0 +1,147 @@ +# Calling APIs + +- [Sample Code](#section5490173592518) +- [Compilation](#section534302242515) +- [Debugging Information](#section1017419992515) +- [Call Stack Parsing](#section1485163282417) + +## Sample Code + +The sample code explicitly calls the related APIs of the memory debugging module to check the memory. + +``` +#include +#include +#include +#include // Header file that includes the declaration of the memory debugging APIs + +#define MALLOC_LEAK_SIZE 0x300 + +void func(void) { + char *ptr = malloc(MALLOC_LEAK_SIZE); + memset(ptr, '3', MALLOC_LEAK_SIZE); +} + +int main() +{ + mem_check_init(NULL); // Output the memory debugging information through the serial port. This function must be called before the user program requests the heap memory for the first time (generally called at the entry of the main function). Otherwise, the debugging information is inaccurate. + // mem_check_init("/storage/mem_debug.txt"); // Output the memory debugging information to the /storage/mem_debug.txt file. If the file fails to be created, output the information through the serial port. + char *ptr = malloc(MALLOC_LEAK_SIZE); + memset(ptr, '1', MALLOC_LEAK_SIZE); + + watch_mem(); // Obtain the thread-level memory statistics in the current code. + func(); + check_heap_integrity(); // Check the integrity of the heap memory nodes. + check_leak(); // Check whether a heap memory leak occurs in the current code. (Generally, the check result is accurate before the application exits. If the check is performed after the calling of malloc and before the calling of free, the result is inaccurate.) + return 0; +} +``` + +## Compilation + +``` +$ clang -o mem_check mem_check.c -funwind-tables -rdynamic -g -mfloat-abi=softfp -mcpu=cortex-a7 -mfpu=neon-vfpv4 -target arm-liteos --sysroot=/home//harmony/out/hispark_taurus/ipcamera_hispark_taurus/sysroot $(clang -mfloat-abi=softfp -mcpu=cortex-a7 -mfpu=neon-vfpv4 -target arm-liteos -print-file-name=libunwind.a) +``` + +>![](../public_sys-resources/icon-note.gif) **NOTE:** +>- In this example, the compiler path is written into an environment variable in the **.bashrc** file. +>- When compiling user programs and required libraries, add the option **-funwind-tables -rdynamic -g** for stack backtracking. +>- The **-mfloat-abi=softfp**, **-mcpu=cortex-a7**, and **-mfpu=neon-vfpv4** options specify the floating-point calculation optimization, chip architecture, and FPU, which must be the same as the compilation options used by the libc library. Otherwise, the libc library file cannot be found during the link time. +>- **-target arm-liteos** specifies the path of the library files related to the compiler. +>- **--sysroot=/home//harmony/out/hispark\_taurus/ipcamera\_hispark\_taurus/sysroot** specifies the root directory of the compiler library files. In this example, the OpenHarmony project code is stored in **/home//harmony**. The **out/hispark\_taurus/ipcamera\_hispark\_taurus** directory indicates the product specified by the **hb set** command during compilation. In this example, **ipcamera\_hispark\_taurus** is the product specified. +>- **$\(clang -mfloat-abi=softfp -mcpu=cortex-a7 -mfpu=neon-vfpv4 -target arm-liteos -print-file-name=libunwind.a\)** specifies the path of the unwind library. + +## Debugging Information + +``` +OHOS # ./mem_check +OHOS # +==PID:4== Heap memory statistics(bytes): // Heap memory statistics + [Check point]: // Call stack of the check point + #00: [0x86c] -> mem_check + #01: <(null)+0x24baf9dc>[0x219dc] -> /lib/libc.so + + [TID: 18, Used: 0x320] // The heap memory is occupied by thread No. 18. The current process has only one thread. + +==PID:4== Total heap: 0x320 byte(s), Peak: 0x320 byte(s) + +Check heap integrity ok! // Heap memory integrity check + +==PID:4== Detected memory leak(s): // Memory leak information and call stack + [Check point]: + #00: [0x2da4c] -> /lib/libc.so + #01: [0x878] -> mem_check + + [TID:18 Leak:0x320 byte(s)] Allocated from: + #00: [0x850] -> mem_check + #01: <(null)+0x24baf9dc>[0x219dc] -> /lib/libc.so + + [TID:18 Leak:0x320 byte(s)] Allocated from: + #00: [0x810] -> mem_check + #01: [0x870] -> mem_check + #02: <(null)+0x24baf9dc>[0x219dc] -> /lib/libc.so + +==PID:4== SUMMARY: 0x640 byte(s) leaked in 2 allocation(s). + +==PID:4== Detected memory leak(s): + [Check point]: + #00: [0x2da4c] -> /lib/libc.so + #01: [0x111ec] -> /lib/libc.so + + [TID:18 Leak:0x320 byte(s)] Allocated from: + #00: [0x850] -> mem_check + #01: <(null)+0x24baf9dc>[0x219dc] -> /lib/libc.so + + [TID:18 Leak:0x320 byte(s)] Allocated from: + #00: [0x810] -> mem_check + #01: [0x870] -> mem_check + #02: <(null)+0x24baf9dc>[0x219dc] -> /lib/libc.so + +==PID:4== SUMMARY: 0x640 byte(s) leaked in 2 allocation(s). + +Check heap integrity ok! +``` + +## Call Stack Parsing + +The **parse\_mem\_info.sh** script in **kernel/liteos\_a/tools/scripts/parse\_memory/** can be used to parse the call stack. You can use the script to convert the debug information into specific source code line number. In the following command, **mem\_debug.txt** stores the memory debugging information, and **elf1** and **elf2** are the executable and linkable format \(ELF\) files to parse. + +``` +$ ./parse_mem_info.sh mem_debug.txt elf1 elf2 elf3 ... +``` + +Example: + +``` +$ ./parse_mem_info.sh mem_debug.txt mem_check +Compiler is [gcc/llvm]: llvm +Now using addr2line ... + +==PID:4== Heap memory statistics(bytes): + [Check point]: + #00: [0x86c] at /usr1/xxx/TEST_ELF/mem_check.c:22 + #01: <(null)+0x24baf9dc>[0x219dc] -> /lib/libc.so + + [TID: 18, Used: 0x320] + +==PID:4== Total heap: 0x320 byte(s), Peak: 0x320 byte(s) + +Check heap integrity ok! + +==PID:4== Detected memory leak(s): + [Check point]: + #00: [0x2da4c] -> /lib/libc.so + #01: [0x878] at /usr1/xxx/TEST_ELF/mem_check.c:28 + + [TID:18 Leak:0x320 byte(s)] Allocated from: + #00: [0x850] at /usr1/xxx/TEST_ELF/mem_check.c:17 + #01: <(null)+0x24baf9dc>[0x219dc] -> /lib/libc.so + + [TID:18 Leak:0x320 byte(s)] Allocated from: + #00: [0x810] at /usr1/xxx/TEST_ELF/mem_check.c:9 + #01: [0x870] at /usr1/xxx/TEST_ELF/mem_check.c:24 + #02: <(null)+0x24baf9dc>[0x219dc] -> /lib/libc.so + +==PID:4== SUMMARY: 0x640 byte(s) leaked in 2 allocation(s). +``` + diff --git a/en/device-dev/kernel/kernel-small-debug-user-guide-use-cli.md b/en/device-dev/kernel/kernel-small-debug-user-guide-use-cli.md new file mode 100644 index 0000000000000000000000000000000000000000..5d6a69f907560cb76c18ded46088ee78a6866544 --- /dev/null +++ b/en/device-dev/kernel/kernel-small-debug-user-guide-use-cli.md @@ -0,0 +1,229 @@ +# Using the CLI + +- [Sample Code](#section13793104782316) +- [Compilation](#section1676431122320) +- [Running the mwatch Command](#section1703415132311) +- [Call Stack Parsing](#section1880675510221) +- [Running the mrecord Command](#section071022822210) + +In addition to calling APIs to check the memory used by user-mode processes, you can run CLI commands to collect memory statistics, check for memory leaks, and check memory integrity. + +``` +--mwatch: initializes memory debugging, registers signals, and outputs memory debugging information through the serial port. +--mrecord : initializes memory debugging, registers signals, and saves the memory debugging information to the f_path file. If the f_path file fails to be created, output the memory debugging information through the serial port. +``` + +If the process to debug does not exit, you can use the signal mechanism to obtain the corresponding information: + +``` +kill -35 # Check the thread-level heap memory usage. +kill -36 # Check for heap memory leaks. +kill -37 # Check whether the head node of the heap memory is complete. +``` + +## Sample Code + +The sample code constructs a memory problem and uses the command line to perform memory debugging. + +``` +#include +#include +#include + +#define MALLOC_LEAK_SIZE 0x300 + +void func(void) { + char *ptr = malloc(MALLOC_LEAK_SIZE); + memset(ptr, '3', MALLOC_LEAK_SIZE); +} + +int main() +{ + char *ptr = malloc(MALLOC_LEAK_SIZE); + memset(ptr, '1', MALLOC_LEAK_SIZE); + func(); + while (1); +} +``` + +## Compilation + +For details, see [Calling APIs](kernel-small-debug-user-guide-use-api.md#section534302242515). + +## Running the mwatch Command + +``` +OHOS # ./mem_check --mwatch // Run the task command to obtain the mem_check process PID, which is 4. +OHOS # +OHOS # kill -35 4 // Check heap memory statistics. +OHOS # +==PID:4== Heap memory statistics(bytes): + [Check point]: + #00: [0x58dfc] -> /lib/libc.so + + [TID: 18, Used: 0x640] + +==PID:4== Total heap: 0x640 byte(s), Peak: 0x640 byte(s) + +OHOS # kill -36 4 // Check for heap memory leaks. +OHOS # +==PID:4== Detected memory leak(s): + [Check point]: + #00: [0x2da4c] -> /lib/libc.so + #01: [0x58dfc] -> /lib/libc.so + + [TID:18 Leak:0x320 byte(s)] Allocated from: + #00: [0x724] -> mem_check + #01: <(null)+0x2555a9dc>[0x219dc] -> /lib/libc.so + + [TID:18 Leak:0x320 byte(s)] Allocated from: + #00: [0x6ec] -> mem_check + #01: [0x740] -> mem_check + #02: <(null)+0x2555a9dc>[0x219dc] -> /lib/libc.so + +==PID:4== SUMMARY: 0x640 byte(s) leaked in 2 allocation(s). + +OHOS # kill -37 4 // Check the integrity of the head node of the heap memory. +OHOS # +Check heap integrity ok! +``` + +## Call Stack Parsing + +Save the debugging information to the **test.txt** file and use the script to parse the information to obtain the number of line where the memory leak occurs. + +``` +$ ./parse_mem_info.sh test.txt mem_check +Compiler is [gcc/llvm]: llvm +Now using addr2line ... + +==PID:4== Detected memory leak(s): + [Check point]: + #00: [0x2da4c] -> /lib/libc.so + #01: [0x58dfc] -> /lib/libc.so + + [TID:18 Leak:0x320 byte(s)] Allocated from: + #00: [0x724] at /usr1/xxx/TEST_ELF/mem_check.c:14 + #01: <(null)+0x2555a9dc>[0x219dc] -> /lib/libc.so + + [TID:18 Leak:0x320 byte(s)] Allocated from: + #00: [0x6ec] at /usr1/xxx/TEST_ELF/mem_check.c:8 + #01: [0x740] at /usr1/xxx/TEST_ELF/mem_check.c:19 + #02: <(null)+0x2555a9dc>[0x219dc] -> /lib/libc.so + +==PID:4== SUMMARY: 0x640 byte(s) leaked in 2 allocation(s). +``` + +## Running the mrecord Command + +1. Run the user program and specify the path of the file that stores the memory debugging information. + + ``` + OHOS # ./mem_check --mrecord /storage/check.txt + ``` + +2. Run the **kill -35 <_pid_\>** command to collect statistics on the memory information. The information is exported to a file. Run the **cat** command to view the information. + + ``` + OHOS # kill -35 4 + OHOS # Memory statistics information saved in /storage/pid(4)_check.txt + + OHOS # cat /storage/pid(4)_check.txt + + ==PID:4== Heap memory statistics(bytes): + [Check point]: + #00: [0x5973c] -> /lib/libc.so + + [TID: 18, Used: 0x640] + + ==PID:4== Total heap: 0x640 byte(s), Peak: 0x640 byte(s) + ``` + +3. Run the **kill -36 <_pid_\>** command to check memory integrity. The information is exported to a file. Run the **cat** command to view the information. + + ``` + OHOS # kill -36 4 + OHOS # Leak check information saved in /storage/pid(4)_check.txt + + OHOS # cat /storage/pid(4)_check.txt + + ==PID:4== Heap memory statistics(bytes): + [Check point]: + #00: [0x5973c] -> /lib/libc.so + + [TID: 18, Used: 0x640] + + ==PID:4== Total heap: 0x640 byte(s), Peak: 0x640 byte(s) + + ==PID:4== Detected memory leak(s): + [Check point]: + #00: [0x2e38c] -> /lib/libc.so + #01: [0x5973c] -> /lib/libc.so + + [TID:18 Leak:0x320 byte(s)] Allocated from: + #00: [0x724] -> mem_check + #01: <(null)+0x1fdd231c>[0x2231c] -> /lib/libc.so + + [TID:18 Leak:0x320 byte(s)] Allocated from: + #00: [0x6ec] -> mem_check + #01: [0x740] -> mem_check + #02: <(null)+0x1fdd231c>[0x2231c] -> /lib/libc.so + + ==PID:4== SUMMARY: 0x640 byte(s) leaked in 2 allocation(s). + ``` + +4. Run the **kill -9 <_pid_\>** command to kill the current process. After the process exits, a memory integrity check is performed by default. The check result is output to a file. You can run the **cat** command to view it. + + ``` + OHOS # kill -9 4 + OHOS # Leak check information saved in /storage/pid(4)_check.txt + + Check heap integrity ok! + + OHOS # cat /storage/pid(4)_check.txt + OHOS # + ==PID:4== Heap memory statistics(bytes): + [Check point]: + #00: [0x5973c] -> /lib/libc.so + + [TID: 18, Used: 0x640] + + ==PID:4== Total heap: 0x640 byte(s), Peak: 0x640 byte(s) + + ==PID:4== Detected memory leak(s): + [Check point]: + #00: [0x2e38c] -> /lib/libc.so + #01: [0x5973c] -> /lib/libc.so + + [TID:18 Leak:0x320 byte(s)] Allocated from: + #00: [0x724] -> mem_check + #01: <(null)+0x1fdd231c>[0x2231c] -> /lib/libc.so + + [TID:18 Leak:0x320 byte(s)] Allocated from: + #00: [0x6ec] -> mem_check + #01: [0x740] -> mem_check + #02: <(null)+0x1fdd231c>[0x2231c] -> /lib/libc.so + + ==PID:4== SUMMARY: 0x640 byte(s) leaked in 2 allocation(s). + + ==PID:4== Detected memory leak(s): + [Check point]: + #00: [0x2e38c] -> /lib/libc.so + #01: [0x11b2c] -> /lib/libc.so + + [TID:18 Leak:0x320 byte(s)] Allocated from: + #00: [0x724] -> mem_check + #01: <(null)+0x1fdd231c>[0x2231c] -> /lib/libc.so + + [TID:18 Leak:0x320 byte(s)] Allocated from: + #00: [0x6ec] -> mem_check + #01: [0x740] -> mem_check + #02: <(null)+0x1fdd231c>[0x2231c] -> /lib/libc.so + + ==PID:4== SUMMARY: 0x640 byte(s) leaked in 2 allocation(s). + ``` + + +>![](../public_sys-resources/icon-note.gif) **NOTE:** +>The preceding information recorded gradually is added to the file specified during initialization. Therefore, running the **cat** command can also display the historical information in the file. + diff --git a/en/device-dev/kernel/kernel-small-debug-user-guide-use.md b/en/device-dev/kernel/kernel-small-debug-user-guide-use.md new file mode 100644 index 0000000000000000000000000000000000000000..cbdc9e1152b875c46e9dadc154b906b418311d08 --- /dev/null +++ b/en/device-dev/kernel/kernel-small-debug-user-guide-use.md @@ -0,0 +1,17 @@ +# How to Use + +By default, the OpenHarmony debug version is compiled when a project is built. The libc library of the debug version has integrated the APIs for memory debugging. You can enable memory debugging as required. + +You can perform heap memory debugging by using either of the following: + +- API: By calling APIs, you can accurately check the heap memory information of a specific code logic segment. However, you have to modify user code. +- CLI: By using the CLI, you do not need to modify user code. However, you cannot accurately check the heap memory information of a specific logic segment. + +>![](../public_sys-resources/icon-note.gif) **NOTE:** +>After memory debugging is enabled, a heap memory leak check and a heap memory integrity check will be performed by default when a process exits. If memory debugging is disabled, the heap memory statistics, heap memory leak check, and heap memory integrity check cannot be enabled, and there is no response to the calling of any debug API. + +- **[Calling APIs](kernel-small-debug-user-guide-use-api.md)** + +- **[Using the CLI](kernel-small-debug-user-guide-use-cli.md)** + + diff --git a/en/device-dev/kernel/kernel-small-debug-user-guide.md b/en/device-dev/kernel/kernel-small-debug-user-guide.md new file mode 100644 index 0000000000000000000000000000000000000000..49ba86149d6b654a7bf652160a6d8fee09351ac0 --- /dev/null +++ b/en/device-dev/kernel/kernel-small-debug-user-guide.md @@ -0,0 +1,7 @@ +# Usage + +- **[API Description](kernel-small-debug-user-guide-api.md)** + +- **[How to Use](kernel-small-debug-user-guide-use.md)** + + diff --git a/en/device-dev/kernel/kernel-small-debug-user.md b/en/device-dev/kernel/kernel-small-debug-user.md new file mode 100644 index 0000000000000000000000000000000000000000..14f7c5097c529f46841a3b0a9592463b59ec3a81 --- /dev/null +++ b/en/device-dev/kernel/kernel-small-debug-user.md @@ -0,0 +1,17 @@ +# User-Mode Memory Debugging + +- **[Basic Concepts](kernel-small-debug-user-concept.md)** + +- **[Working Principles](kernel-small-debug-user-function.md)** + +- **[Usage](kernel-small-debug-user-guide.md)** + +- **[Typical Memory Problems](kernel-small-debug-user-faqs.md)** + +- **[Linux Kernel Overview](kernel-standard-overview.md)** + +- **[Guidelines for Using Patches on OpenHarmony Development Boards](kernel-standard-patch.md)** + +- **[Guidelines for Compiling and Building the Linux Kernel](kernel-standard-build.md)** + + diff --git a/en/device-dev/subsystems/subsys-ota-guide.md b/en/device-dev/subsystems/subsys-ota-guide.md index a249a319bae47c068ae9051865429d0e7f74bc27..dac093e437eede6b62f3dde0776fdab317072841 100644 --- a/en/device-dev/subsystems/subsys-ota-guide.md +++ b/en/device-dev/subsystems/subsys-ota-guide.md @@ -1,206 +1,415 @@ -# OTA Upgrade +# OTA Update -- [Limitations and Constraints](#section691733275418) -- [Generating a Public/Private Key Pair](#section94411533155010) -- [Generating an Upgrade Package](#section632383718539) -- [Uploading the Upgrade Package](#section5772112473213) -- [Downloading the Upgrade Package](#section251732474917) -- [Integrating OTA Update Capabilities](#section298217330534) -- [API Application Scenario \(Default\)](#section7685171192916) - - [How to Develop](#section0745926153017) - - [Sample Code](#section1337111363306) +- [Introduction](#section753413913562) +- [Constraints](#section61232796162135) +- [Generating a Public/Private Key Pair](#section1392711588162135) +- [Generating an Update Package](#section704519924162135) + - [Mini and Small Systems](#section527064658162135) + - [Standard System](#section1291354584162135) -- [API Application Scenario \(Custom\)](#section1686395317306) - - [How to Develop](#section524515314317) - - [Sample Code](#section525974743120) +- [Uploading the Update Package](#section1040019352162135) +- [Downloading the Update Package](#section1870792413162135) +- [Integrating OTA Update Capabilities](#section2107348555162135) +- [API Application Scenario \(Default\)](#section1308521557162135) + - [How to Develop](#section2103641927162135) + - [Sample Code](#section1918621904162135) -- [Upgrading the System](#section151997114334) +- [API Application Scenario \(Custom\)](#section1332839930162135) + - [How to Develop](#section2120976727162135) + - [Sample Code](#section1743369672162135) -Over the Air \(OTA\) is a technology that makes it easier for you to remotely update devices, such as IP cameras. A device can be upgraded with a full or differential package. A full package contains all content of a new system, and a differential package contains the differences between the old and new systems. Currently, only the full-package upgrade is supported. +- [Upgrading the System](#section1704276175162135) -## Limitations and Constraints +## Introduction -- The open-source suites for devices developed based on Hi3861, Hi3518E V300 and Hi3516D V300 are supported. +Over the Air \(OTA\) is a technology that makes it easier for you to remotely update devices, such as IP cameras. Currently, the mini and small systems support update using a full package, but not a differential package. A full package contains all content of a new system, and a differential package contains the differences between the old and new systems. + +## Constraints + +- Only the open-source suites for devices powered by Hi3861, Hi3518E V300, and Hi3516D V300 are supported. - Devices developed based on Hi3518E V300 and Hi3516D V300 must support the SD card in the Virtual Festival of Aerobatic Teams \(VFAT\) format. -## Generating a Public/Private Key Pair + >![](../public_sys-resources/icon-note.gif) **NOTE:** + >Generation of update packages can only be performed on the Linux system. + + +## Generating a Public/Private Key Pair -1. Download the OpenSSL tool from the following website and install it on a Windows PC, and configure environment variables. +1. Download the [OpenSSL](http://slproweb.com/products/Win32OpenSSL.html) tool, install it on a Windows PC, and configure environment variables. +2. Use the OpenSSL tool to generate a public/private key pair. +3. Keep the private key file properly as this file stores the private key used to sign the update package. You need to specify the private key file in the command used for preparing the update package. The public key is used to verify the signature of the update package during the upgrade, and it is stored as follows: - [http://slproweb.com/products/Win32OpenSSL.html](http://slproweb.com/products/Win32OpenSSL.html) + For the mini and small systems, the generated public key is preset in the code. The vendor needs to implement the **HotaHalGetPubKey** API to obtain the key. For the standard system, the generated public key is stored in the **./device/hisilicon/hi3516dv300/build/updater\_config/signing\_cert.crt** file. -2. Access the **tools\\update\_tools\\update\_pkg\_tools** directory, download the upgrade package making tool, and save it to a local directory, for example, **D:\\ota\_tools**. -3. Run **Generate\_public\_private\_key.bat** in the **ota\_tools\\key** directory to generate **Metis\_PUBLIC.key**, **private.key**, and **public\_arr.txt** that contains public values, as shown in the following figure. Keep the private key properly. +4. For the mini and small systems that use the Hi3518E V300 or Hi3516D V300 suite, also use the content in **public\_arr.txt** to replace the content in **g\_pub\_key** in the **device\\hisilicon\\third\_party\\uboot\\u-boot-2020.01\\product\\hiupdate\\verify\\update\_public\_key.c** file of the U-Boot module. + + Example configuration for the public key of the U-Boot module: + + ``` + static unsigned char g_pub_key[PUBKEY_LEN] = { + 0x30, 0x82, 0x01, 0x0A, 0x02, 0x82, 0x01, 0x01, + 0x00, 0xBF, 0xAA, 0xA5, 0xB3, 0xC2, 0x78, 0x5E, + } + ``` - **Figure 1** Generating a Public/Private Key Pair - - ![](figure/en-us_image_0000001060200050.png) +## Generating an Update Package -4. Use the array written in **public\_arr.txt** as a substitute for **g\_pubKeyBuf** in **base\\update\\ota\_lite\\frameworks\\source\\verify\\hota\_verify.c** of the OTA module. +### Mini and Small Systems - Example array in **public\_arr.txt**: +1. Create the **target\_package** folder with the following directory structure: ``` - 0x30,0x82,0x1,0xa,0x2,0x82,0x1,0x1,0x0,0xc7,0x8c,0xf3,0x91,0xa1,0x98,0xbf,0xb1,0x8c, - 0xbe,0x22,0xde,0x32,0xb2,0xfa,0xec,0x2c,0x69,0xf6,0x8f,0x43,0xa7,0xb7,0x6f,0x1e,0x4a,0x97, - 0x4b,0x27,0x5d,0x56,0x33,0x9a,0x73,0x4e,0x7c,0xf8,0xfd,0x1a,0xf0,0xe4,0x50,0xda,0x2b,0x8, - 0x74,0xe6,0x28,0xcc,0xc8,0x22,0x1,0xa8,0x14,0x9,0x46,0x46,0x6a,0x10,0xcd,0x39,0xd,0xf3, - 0x4a,0x7f,0x1,0x63,0x21,0x33,0x74,0xc6,0x4a,0xeb,0x68,0x40,0x55,0x3,0x80,0x1d,0xd9,0xbc, - 0xd4,0xb0,0x4a,0x84,0xb7,0xac,0x43,0x1d,0x76,0x3a,0x61,0x40,0x23,0x3,0x88,0xcc,0x80,0xe, - 0x75,0x10,0xe4,0xad,0xac,0xb6,0x4c,0x90,0x8,0x17,0x26,0x21,0xff,0xbe,0x1,0x82,0x16,0x76, - 0x9a,0x1c,0xee,0x8e,0xd9,0xb0,0xea,0xd5,0x50,0x61,0xcc,0x9c,0x2e,0x78,0x15,0x2d,0x1f,0x8b, - 0x94,0x77,0x30,0x39,0x70,0xcf,0x16,0x22,0x82,0x99,0x7c,0xe2,0x55,0x37,0xd4,0x76,0x9e,0x4b, - 0xfe,0x48,0x26,0xc,0xff,0xd9,0x59,0x6f,0x77,0xc6,0x92,0xdd,0xce,0x23,0x68,0x83,0xbd,0xd4, - 0xeb,0x5,0x1b,0x2a,0x7e,0xda,0x9a,0x59,0x93,0x41,0x7b,0x4d,0xef,0x19,0x89,0x4,0x8d,0x5, - 0x7d,0xbc,0x3,0x1f,0x77,0xe6,0x3d,0xa5,0x32,0xf5,0x4,0xb7,0x9c,0xe9,0xfa,0x6e,0xc,0x9f, - 0x4,0x62,0xfe,0x2a,0x5f,0xbf,0xeb,0x9a,0x73,0xa8,0x2a,0x72,0xe3,0xf0,0x57,0x56,0x5c,0x59, - 0x14,0xdd,0x79,0x11,0x42,0x3a,0x48,0xf7,0xe8,0x80,0xb1,0xaf,0x1c,0x40,0xa2,0xc6,0xec,0xf5, - 0x67,0xc1,0x88,0xf6,0x26,0x5c,0xd3,0x11,0x5,0x11,0xed,0xb1,0x45,0x2,0x3,0x1,0x0,0x1, + target_package + ├── OTA.tag + ├── config + ├── {component_1} + ├── {component_2} + ├── ... + ├── {component_N} + └── updater_config + └── updater_specified_config.xml ``` - Example configuration for the public key of the OTA module: +2. Place the components to be updated, including the image file \(for example, **rootfs.img**\), as \{component\_N\} in the root directory of the **target\_package** folder. +3. Configure the **updater\_specified\_config.xml** file in the **update\_config** folder. + + Example configuration of the **updater\_specified\_config.xml** file: ``` - #define PUBKEY_LENGTH 270 - - static uint8 g_pubKeyBuf[PUBKEY_LENGTH] = { - 0x30, 0x82, 0x01, 0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, 0xBF, 0xAA, 0xA5, 0xB3, 0xC2, 0x78, 0x5E, - 0x63, 0x07, 0x84, 0xCF, 0x37, 0xF0, 0x45, 0xE8, 0xB9, 0x6E, 0xEF, 0x04, 0x88, 0xD3, 0x43, 0x06, + + + + head info + + + ./OTA.tag + ./config + ./u-boot-xxxx.bin + + ``` -5. \(Optional\) For Hi3518E V300 and Hi3516D V300 suites, further replace the array written in **g\_pub\_key** with that in **public\_arr.txt**. The **g\_pub\_key** file is provided in **device\\hisilicon\\third\_party\\uboot\\u-boot-2020.01\\product\\hiupdate\\verify\\update\_public\_key.c** of the U-Boot module. + **Table 1** Description of nodes in the component configuration file - Example configuration for the public key of the U-Boot module: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Type

+

Node Name

+

Node Label

+

Mandatory

+

Description

+

Header information (head node)

+

info

+

/

+

Yes

+

Content of this node: head info

+

fileVersion

+

Yes

+

This field is reserved and does not affect the generation of the update package.

+

prdID

+

Yes

+

This field is reserved and does not affect the generation of the update package.

+

softVersion

+

Yes

+

Software version number, that is, the version number of the update package. The version number must be within the range specified by VERSION.mbn. Otherwise, an update package will not be generated.

+

date

+

Yes

+

Date when the update package is generated. This field is reserved and does not affect the generation of the update package.

+

time

+

Yes

+

Time when the update package is generated. This field is reserved and does not affect the generation of the update package.

+

Component information (group node)

+

component

+

/

+

Yes

+

Content of this node: path of the component or image file to be packed into the update package. It is the root directory of the version package by default.

+

compAddr

+

Yes

+

Name of the partition corresponding to the component, for example, system or vendor.

+

compId

+

Yes

+

Component ID, which must be unique.

+

resType

+

Yes

+

This field is reserved and does not affect the generation of the update package.

+

compType

+

Yes

+

Image type, which can be a full or differential package. The value 0 indicates a full package, and value 1 indicates a differential package.

+
+ + >![](../public_sys-resources/icon-note.gif) **NOTE:** + >As mini and small systems do not support update using a differential package, **compType** must be set to **0**, other than **1**. + >For mini and small systems, an update package cannot be created by changing partitions. + +4. Create the **OTA.tag** file, which contains the magic number of the update package. The magic number is as follows: ``` - static unsigned char g_pub_key[PUBKEY_LEN] = { - 0x30, 0x82, 0x01, 0x0A, 0x02, 0x82, 0x01, 0x01, - 0x00, 0xBF, 0xAA, 0xA5, 0xB3, 0xC2, 0x78, 0x5E, + package_type:ota1234567890qwertw ``` +5. Create the **config** file, and configure the **bootargs** and **bootcmd** information in the file. -## Generating an Upgrade Package + Example configuration: -1. Save the files to be upgraded in the **ota\_tools\\Components** directory. + ``` + setenv bootargs 'mem=128M console=ttyAMA0,115200 root=/dev/mmcblk0p3 rw rootfstype=ext4 rootwait blkdevparts=mmcblk0:1M + (u-boot.bin),9M(kernel.bin),50M(rootfs_ext4.img),50M(userfs.img)' setenv bootcmd 'mmc read 0x0 0x82000000 0x800 0x4800;bootm 0x82000000' + ``` - **Figure 2** Location of original image files - +6. Generate the update package. + + ``` + python build_update.py ./target_package/ ./output_package/ -pk ./rsa_private_key3072.pem -nz -nl2x + ``` + + - **./target\_package/**: path of **target\_package** + - **./output\_package/**: output path of the update package + - **-pk ./rsa\_private\_key3072.pem**: path of the private key file + - **-nz**: **not zip** mode + - **-nl2**: non-standard system mode + + +### Standard System + +1. Create the **target\_package** folder with the following directory structure: + + ``` + target_package + ├── {component_1} + ├── {component_2} + ├── ... + ├── {component_N} + └── updater_config + ├── BOARD.list + ├── VERSION.mbn + └── updater_specified_config.xml + ``` + +2. Place the components to be updated, including the image file \(for example, **system.img**\), as \{component\_N\} in the root directory of the **target\_package** folder. + +3. Configure the component configuration file in the **update\_config** folder. + +4. Configure the list of products supported by the current update package in **BOARD.list** in the **update\_config** folder. + + Example configuration: + + ``` + HI3516 + HI3518 + ``` - ![](figure/en-us_image_0000001061889268.png) +5. Configure the versions supported by the current update package in **VERSION.mbn** in the **update\_config** folder. - **Table 1** Files to be upgraded + Version number format: Hi3516DV300-eng 10 QP1A.XXXXXX.\{Major version number \(6 digits\)\}.XXX\{Minor version number \(3 digits\)\} - - -

File

+ For example, Hi3516DV300-eng 10 QP1A.190711.020, where **190711** is the major version number, and **020** is the minor version number. + + Example configuration: + + ``` + Hi3516DV300-eng 10 QP1A.190711.001 + Hi3516DV300-eng 10 QP1A.190711.020 + Hi3518DV300-eng 10 QP1A.190711.021 + ``` + +6. For update using an incremental \(differential\) package, also prepare a source version package \(source\_package\) in the same format as the target version package \(target\_package\), and then compress it as a **.zip** file, that is, **source\_package.zip**. + +7. If you create an update package with partitions changed, also provide the partition table file named **partition\_file.xml**. You can specify the file using the **-pf** parameter. For details about the configuration nodes, see the description below. + + The partition table is generated with the image. The format is as follows: + + ``` + + + + + + ``` + + **Table 2** Description of labels in the partition table + + + - - + + + - - - - - - - - - + + +

Label

Description

+

Description

u-boot.bin

+

Sel

+

Whether the partition is effective. The value 1 indicates that the partition is effective, and value 0 indicates the opposite.

+

PartitionName

Renamed from the u-boot-hi351XevX00.bin file generated after compilation.

+

Partition name, for example, fastboot or boot.

kernel.bin

+

FlashType

Renamed from the liteos.bin or kernel file generated after compilation.

+

Flash type, for example, emmc or ufs.

rootfs.img

+

FileSystem

Renamed from the rootfs_xxxxx.img file generated after compilation.

+

File system type, for example, ext3/4 or f2fs. The value can also be none.

config

+

Start

Provides development board and kernel information. For details, see the SD card burning description of the corresponding open-source suite.

+

Start address of the partition, in MB. The start address of all partitions is 0.

OTA.tag

+

Length

Contains 32 bytes in the package_type:otaA1S2D3F4G5H6J7K8 format. The last 16 bytes are random, varying with the version.

+

Size of the partition, in MB.

+

SelectFile

+

Actual path of the image or file.

-2. Open the **packet\_harmony.xml** file in **ota\_tools\\xml** to modify **compAddr** as follows. Other items are reserved. +8. Generate the update package. + + **Full package** - Example configuration for the component information: + Run the following command: ``` - - - .\Components\rootfs_jffs2.img - .\Components\liteos.bin - .\Components\userfs_jffs2.img - + python build_update.py ./target_package/ ./output_package/ -pk ./rsa_private_key3072.pem ``` -3. Configure the paths of private and public keys in **packet\_harmony.xml**. + - **./target\_package/**: path of **target\_package** + - **./output\_package/**: output path of the update package + - **-pk ./rsa\_private\_key3072.pem**: path of the private key file - Example configuration for paths of private and public keys: + **Incremental \(differential\) package** + + Run the following command: ``` - - .\key\private.key - .\key\Metis_PUBLIC.key - + python build_update.py ./target_package/ ./output_package/ -s ./source_package.zip -pk ./rsa_private_key3072.pem ``` -4. Configure the product name and software version in **ota\_tools\\VersionDefine.bat** for anti-rollback. + - **./target\_package/**: path of **target\_package** + - **./output\_package/**: output path of the update package + - **-s ./source\_package.zip**: path of the **source\_package.zip** file. For update using a differential package, use the **-s** parameter to specify the source version package. + - **-pk ./rsa\_private\_key3072.pem**: path of the private key file + + **Update package with partitions changed** - Example configuration for the product name and software version: + Run the following command: ``` - set FILE_PRODUCT_NAME=Hisi - - @rem Set the software version number to a string of no more than 16 characters. - set SOFTWARE_VER=OpenHarmony 1.1 + python build_update.py ./target_package/ ./output_package/ -pk ./rsa_private_key3072.pem -pf ./partition_file.xml ``` -5. Run **Make\_Harmony\_PKG.bat** in the **ota\_tools** directory to generate the **Hisi\_OpenHarmony 1.1.bin** upgrade package. The upgrade package is signed using **SHA-256** and **RSA 2048** to ensure its integrity and validity. + - **./target\_package/**: path of **target\_package** + - **./output\_package/**: output path of the update package + - **-pk ./rsa\_private\_key3072.pem**: path of the private key file + - **-pf ./partition\_file.xml**: path of the partition table file + + +## Uploading the Update Package - **Figure 3** Upgrade package making tool - +Upload the update package to the vendor's OTA server. - ![](figure/en-us_image_0000001059334449.png) +## Downloading the Update Package +1. Download the update package from the OTA server. +2. \(Optional\) Insert an SD card \(with a capacity greater than 100 MB\) if the device is developed based on Hi3518E V300 or Hi3516D V300. -## Uploading the Upgrade Package +## Integrating OTA Update Capabilities -Upload the **Hisi\_OpenHarmony 1.1.bin** upgrade package to the vendor's OTA server. +1. For mini and small systems -## Downloading the Upgrade Package + - If a vendor requests OTA capabilities, use the dynamic library **libhota.so** and include the header files **hota\_partition.h** and **hota\_updater.h** in **base\\update\\ota\_lite\\interfaces\\kits**. -1. Download the **Hisi\_OpenHarmony 1.1.bin** upgrade package from the OTA server. -2. \(Optional\) Insert an SD card \(capacity greater than 100 MB\) if the device is developed based on Hi3518E V300 or Hi3516D V300. + - The **libhota.so** source code is stored in **base\\update\\ota\_lite\\frameworks\\source**. -## Integrating OTA Update Capabilities + - For details about how to use APIs, see _API Application Scenario_ and OTA APIs in _API Reference_. -- If vendors request OTA capabilities, use the dynamic library **libhota.so** and include the header files **hota\_partition.h** and **hota\_updater.h** in **base\\update\\ota\_lite\\interfaces\\kits**. -- The **libhota.so** source code is stored in **base\\update\\ota\_lite\\frameworks\\source**. -- For details about how to use APIs, see [API Application Scenario \(Default\)](#section7685171192916) and OTA APIs in _API Reference_. -- If the development board needs to be adapted, see the **base\\update\\ota\_lite\\hals\\hal\_hota\_board.h** header file. + - If the development board needs to be adapted, see the **base\\update\\ota\_lite\\hals\\hal\_hota\_board.h** file. -## API Application Scenario \(Default\) +2. For the standard system, see the _JS Reference Specifications_ for details. -The upgrade package is generated by following the instructions provided in [Generating a Public/Private Key Pair](#section94411533155010) and [Generating an Upgrade Package](#section632383718539). -### **How to Develop** +## API Application Scenario \(Default\) + +The update package is generated by following the instructions provided in Generating a Public/Private Key Pair and Generating an Update Package. + +### **How to Develop** + +1. Download the update package for the current device, and then call the **HotaInit** function to initialize the OTA module. -1. Download the upgrade package for the current device, and then call the **HotaInit** function to initialize the OTA module. 2. Call the **HotaWrite** function to verify, parse, and write data streams into the device. -3. Call the **HotaRestart** function to restart the system. - If you want to cancel the upgrade, call the **HotaCancel** function. +3. Call the **HotaRestart** function to restart the system for the update to take effect. Call the **HotaCancel** function if you want to cancel the update. -### **Sample Code** +### **Sample Code** -Perform an OTA update using the upgrade package format and verification method provided by OpenHarmony. +Perform an OTA update using the update package format and verification method provided by OpenHarmony. ``` int main(int argc, char **argv) @@ -252,25 +461,28 @@ int main(int argc, char **argv) } ``` -## API Application Scenario \(Custom\) +## API Application Scenario \(Custom\) + +The update package is generated in other ways instead of following the instructions provided in Generating a Public/Private Key Pair and Generating an Update Package. -The upgrade package is generated in other ways instead of by referring to the preceding two sections. +### **How to Develop** -### **How to Develop** +1. Download the update package for the current device, and then call the **HotaInit** function to initialize the OTA module. -1. Download the upgrade package for the current device, and then call the **HotaInit** function to initialize the OTA module. 2. Call the **HotaSetPackageType** function to set the package type to **NOT\_USE\_DEFAULT\_PKG**. + 3. Call the **HotaWrite** function to write data streams into the device. -4. Call the **HotaRead** function to read data. Vendors can choose to verify the data. -5. \(Optional\) Call the **HotaSetBootSettings** function to set the startup tag used for entering the U-Boot mode after restarting the system. -6. Call the **HotaRestart** function to restart the system. - If you want to cancel the upgrade, call the **HotaCancel** function. +4. Call the **HotaRead** function to read data. Vendors can choose whether to verify the data. + +5. \(Optional\) Call the **HotaSetBootSettings** function to set the startup tag used for entering the U-Boot mode during system restarting. + +6. Call the **HotaRestart** function to restart the system for the update to take effect. Call the **HotaCancel** function if you want to cancel the update. -### **Sample Code** +### **Sample Code** -Perform an OTA update using the upgrade package format and verification method not provided by OpenHarmony. +Perform an OTA update using the update package format and verification method not provided by OpenHarmony. ``` int main(int argc, char **argv) @@ -339,11 +551,11 @@ int main(int argc, char **argv) } ``` -## Upgrading the System +## Upgrading the System -Vendor applications call APIs of the OTA module to perform functions such as signature verification of the upgrade package, anti-rollback, burning and data flushing-to-disk. After the upgrade is complete, the system automatically restarts. +Vendor applications call APIs of the OTA module to perform functions such as signature verification of the update package, anti-rollback, burning and data flushing-to-disk. After the update is complete, the system automatically restarts. -For Hi3518E V300 and Hi3516D V300 open-source suites, the value of **LOCAL\_VERSION** needs to be modified for anti-rollback, for example, modifying **ohos default 1.0** to **ohos default 1.1**. The macro **LOCAL\_VERSION** is provided in **device\\hisilicon\\third\_party\\uboot\\u-boot-2020.01\\product\\hiupdate\\ota\_update\\ota\_local\_info.c**. +For the mini and small systems that use the Hi3518E V300 or Hi3516D V300 open source suite, add the value of **LOCAL\_VERSION** to the version that needs to implement the anti-rollback function. For example, for **"ohos default 1.0"-\>"ohos default 1.1"**, add the value of **LOCAL\_VERSION** in **device\\hisilicon\\third\_party\\uboot\\u-boot-2020.01\\product\\hiupdate\\ota\_update\\ota\_local\_info.c**. Example for modification of the local version: @@ -351,8 +563,8 @@ Example for modification of the local version: const char *get_local_version(void) { #if defined(CONFIG_TARGET_HI3516EV200) || \ - defined(CONFIG_TARGET_HI3516DV300) || \ - defined(CONFIG_TARGET_HI3518EV300) + defined(CONFIG_TARGET_HI3516DV300) || \ + defined(CONFIG_TARGET_HI3518EV300) #define LOCAL_VERSION "ohos default 1.0" /* increase: default release version */ ``` diff --git a/en/readme.md b/en/readme.md index 8df0f62f265a3f798337e59cb1b802fdc9f4bbc9..c3293c74dab84f93735326759ada19b32e475df2 100644 --- a/en/readme.md +++ b/en/readme.md @@ -5,56 +5,51 @@ This project stores OpenHarmony documentation, including the quick start guide, ## Contents - [OpenHarmony Overview](OpenHarmony-Overview.md) -- Mini and Small System Development Guidelines \(Reference Memory < 128 MB\) - - Device development - - **overview**: [device development overview](device-dev/Readme-EN.md) - - **quick-start**: [quick start guide](device-dev/quick-start/Readme-EN.md) \(covering environment setup, source code acquisition, build, and burning\) - - Basic development capabilities - - **Kernel**: [Kernel for Mini Systems](device-dev/kernel/kernel-lite-mini.md) - - **Kernel:**[Kernel for Small Systems](device-dev/kernel/kernel-lite-small.md) - - **Drivers**: [drivers](device-dev/driver/Readme-EN.md) - - **Subsystems**: [subsystems](device-dev/subsystems/Readme-EN.md) \(such as compilation and building, graphics, DFX, and XTS\) - - **Security**: [privacy and security](device-dev/security/Readme-EN.md) - - - **guide**: - - [WLAN-connected products](device-dev/guide/device-wifi.md) \(LED peripheral control and third-party SDK integration\) - - [Screenless cameras](device-dev/guide/device-iotcamera-control.md) \(camera control\) - - [Cameras with a screen](device-dev/guide/device-camera.md) \(screen and camera control, visual application development\) - - - **porting**: - - [Third-Party Library Porting Guide for Mini and Small Systems](device-dev/porting/porting-thirdparty.md) - - [Mini System SoC Porting Guide](device-dev/porting/porting-minichip.md) - - [Small System SoC Porting Guide](device-dev/porting/porting-smallchip.md) - - - **bundles**: - - [HPM Bundle Development Specifications](device-dev/bundles/bundles-standard-rules.md) - - [HPM Bundle Development Guidelines](device-dev/bundles/bundles-guide.md) - - [HPM User Guide](device-dev/bundles/bundles-demo.md) - -- Standard System Development Guidelines \(Reference Memory ≥ 128 MB\) - - Device development +- Device development + - Mini and Small System Development Guidelines \(Reference Memory < 128 MB\) + - Device development + - **overview**: [device development overview](device-dev/Readme-EN.md) + - **quick-start**: [quick start guide](device-dev/quick-start/Readme-EN.md) \(covering environment setup, source code acquisition, build, and burning\) + - Basic development capabilities + - **Kernel**: [Kernel for Mini Systems](device-dev/kernel/kernel-lite-mini.md) + - **Kernel:**[Kernel for Small Systems](device-dev/kernel/kernel-lite-small.md) + - **Drivers**: [drivers](device-dev/driver/Readme-EN.md) + - **Subsystems**: [subsystems](device-dev/subsystems/Readme-EN.md) \(such as compilation and building, graphics, DFX, and XTS\) + - **Security**: [privacy and security](device-dev/security/Readme-EN.md) + - **guide**: + - [OneHop](device-dev/guide/device-wlan-touch.md) + - [WLAN-connected products](device-dev/guide/device-wifi.md) \(LED peripheral control and third-party SDK integration\) + - [Screenless cameras](device-dev/guide/device-iotcamera-control.md) \(camera control\) + - [Cameras with a screen](device-dev/guide/device-camera.md) \(screen and camera control, visual application development\) + - **porting**: + - [Third-Party Library Porting Guide for Mini and Small Systems](device-dev/porting/porting-thirdparty.md) + - [Mini System SoC Porting Guide](device-dev/porting/porting-minichip.md) + - [Small System SoC Porting Guide](device-dev/porting/porting-smallchip.md) + - **bundles**: + - [HPM Bundle Development Specifications](device-dev/bundles/bundles-standard-rules.md) + - [HPM Bundle Development Guidelines](device-dev/bundles/bundles-guide.md) + - [HPM User Guide](device-dev/bundles/bundles-demo.md) + - Standard System Development Guidelines \(Reference Memory ≥ 128 MB\) + - Device development - **overview**: [device development overview](device-dev/Readme-EN.md) - **quick-start**: [quick start guide](device-dev/quick-start/quickstart-standard.md) \(covering environment setup, source code acquisition, build, and burning\) - Basic development capabilities - - **Kernel**: [Kernel for Standard Systems](device-dev/kernel/kernel-standard.md) - - **Drivers**: [drivers](device-dev/driver/Readme-EN.md) - - **Subsystems**: [subsystems](device-dev/subsystems/Readme-EN.md) \(such as compilation and building, graphics, DFX, and XTS\) - - **Security**: [privacy and security](device-dev/security/Readme-EN.md) - + - **Kernel**: [Kernel for Standard Systems](device-dev/kernel/kernel-standard.md) + - **Drivers**: [drivers](device-dev/driver/Readme-EN.md) + - **Subsystems**: [subsystems](device-dev/subsystems/Readme-EN.md) \(such as compilation and building, graphics, DFX, and XTS\) + - **Security**: [privacy and security](device-dev/security/Readme-EN.md) - **guide**: - - [Clock apps](device-dev/guide/device-clock-guide.md) - - [Platform drivers](device-dev/guide/device-driver-demo.md) - - [Peripheral drivers](device-dev/guide/device-outerdriver-demo.md) - + - [Clock apps](device-dev/guide/device-clock-guide.md) + - [Platform drivers](device-dev/guide/device-driver-demo.md) + - [Peripheral drivers](device-dev/guide/device-outerdriver-demo.md) - **porting**: - - - [Standard System SoC Porting Guide](device-dev/porting/standard-system-porting-guide.md) - - [A Method for Rapidly Porting the OpenHarmony Linux Kernel ](device-dev/porting/porting-linux-kernel-overview.md) - + - [Standard System SoC Porting Guide](device-dev/porting/standard-system-porting-guide.md) + - [A Method for Rapidly Porting the OpenHarmony Linux Kernel ](device-dev/porting/porting-linux-kernel-overview.md) - **bundles**: - - [HPM Bundle Development Specifications](device-dev/bundles/bundles-standard-rules.md) - - [HPM Bundle Development Guidelines](device-dev/bundles/bundles-guide.md) - - [HPM User Guide](device-dev/bundles/bundles-demo.md) + - [HPM Bundle Development Specifications](device-dev/bundles/bundles-standard-rules.md) + - [HPM Bundle Development Guidelines](device-dev/bundles/bundles-guide.md) + - [HPM User Guide](device-dev/bundles/bundles-demo.md) + - [FAQs](device-dev/faqs/Readme-EN) - App development diff --git a/zh-cn/device-dev/Readme-CN.md b/zh-cn/device-dev/Readme-CN.md index 992ec8d7ec53e5c9da385a1d46503b9d5992be80..802a3928dcfbed62ccfd5c39d14a2c316e379069 100644 --- a/zh-cn/device-dev/Readme-CN.md +++ b/zh-cn/device-dev/Readme-CN.md @@ -76,7 +76,7 @@ OpenHarmony也提供了一系列可选的系统组件,方便设备开发者按

结合系统能力开发智能设备

+

移植适配

diff --git a/zh-cn/device-dev/driver/Readme-CN.md b/zh-cn/device-dev/driver/Readme-CN.md index a5b29873e75b372a7de4b8c29761252d7cc9b755..17116f4e45cb37b89953e10d828a63f229c8c7a1 100755 --- a/zh-cn/device-dev/driver/Readme-CN.md +++ b/zh-cn/device-dev/driver/Readme-CN.md @@ -4,21 +4,21 @@ - [HDF开发概述](driver-hdf-overview.md) - [驱动开发](driver-hdf-development.md) - [驱动服务管理](driver-hdf-servicemanage.md) - - [驱动消息机制管理](driver-hdf-news.md) + - [驱动消息机制管理](driver-hdf-message-management.md) - [配置管理](driver-hdf-manage.md) - [HDF开发实例](driver-hdf-sample.md) -- [平台驱动开发](driver-platform-develop.md) +- [平台驱动开发](driver-develop.md) + - [ADC](driver-platform-adc-develop.md) - [GPIO](driver-platform-gpio-develop.md) - - [I2C](driver-platform-i2c-develop.md) - - [RTC](driver-platform-rtc-develop.md) + - [I2C](driver-platform-i2c-develop.md) + - [MIPI-DSI](driver-platform-mipidsi-develop.md) + - [MMC](driver-platform-mmc-develop.md) + - [PWM](driver-platform-pwm-develop.md) + - [RTC](driver-platform-rtc-develop.md) - [SDIO](driver-platform-sdio-develop.md) - [SPI](driver-platform-spi-develop.md) - [UART](driver-platform-uart-develop.md) - - [WATCHDOG](driver-platform-watchdog-develop.md) - - [MIPI_DSI](driver-platform-mipidsi-develop.md) - - [MMC](driver-platform-mmc-develop.md) - - [PWM](driver-platform-pwm-develop.md) - - [ADC](driver-platform-adc-develop.md) + - [WatchDog](driver-platform-watchdog-develop.md) - [平台驱动使用](driver-platform.md) - [GPIO](driver-platform-gpio-des.md) - [I2C](driver-platform-i2c-des.md) @@ -28,9 +28,9 @@ - [UART](driver-platform-uart-des.md) - [WATCHDOG](driver-platform-watchdog-des.md) - [MIPI DSI](driver-platform-mipidsi-des.md) -- [外设驱动开发](driver-peripherals.md) + - [PWM](driver-platform-pwm-des.md) +- [外设驱动使用](driver-peripherals.md) - [LCD](driver-peripherals-lcd-des.md) - [TOUCHSCREEN](driver-peripherals-touch-des.md) - [SENSOR](driver-peripherals-sensor-des.md) - - [WLAN](driver-peripherals-external-des.md) - - [USB](driver-peripherals-usb-des.md) + - [WLAN](driver-peripherals-external-des.md) \ No newline at end of file diff --git a/zh-cn/device-dev/driver/driver-develop.md b/zh-cn/device-dev/driver/driver-develop.md new file mode 100644 index 0000000000000000000000000000000000000000..b4bf84d947fb1fdb94ff7280896871f25a806faa --- /dev/null +++ b/zh-cn/device-dev/driver/driver-develop.md @@ -0,0 +1,25 @@ +# 平台驱动开发 + +- **[ADC](driver-platform-adc-develop.md)** + +- **[GPIO](driver-platform-gpio-develop.md)** + +- **[I2C](driver-platform-i2c-develop.md)** + +- **[MIPI-DSI](driver-platform-mipidsi-develop.md)** + +- **[MMC](driver-platform-mmc-develop.md)** + +- **[PWM](driver-platform-pwm-develop.md)** + +- **[RTC](driver-platform-rtc-develop.md)** + +- **[SDIO](driver-platform-sdio-develop.md)** + +- **[SPI](driver-platform-spi-develop.md)** + +- **[UART](driver-platform-uart-develop.md)** + +- **[WatchDog](driver-platform-watchdog-develop.md)** + + diff --git a/zh-cn/device-dev/driver/driver-hdf-development.md b/zh-cn/device-dev/driver/driver-hdf-development.md index bd393dc8965a5f55b406d8db87f6321a80c2c2e0..fe34066779e0b8c6f21b9d64de3f3d15e96dd206 100644 --- a/zh-cn/device-dev/driver/driver-hdf-development.md +++ b/zh-cn/device-dev/driver/driver-hdf-development.md @@ -7,10 +7,8 @@ HDF框架以组件化的驱动模型作为核心设计思路,为开发者提供更精细化的驱动管理,让驱动开发和部署更加规范。HDF框架将一类设备驱动放在同一个host里面,开发者也可以将驱动功能分层独立开发和部署,支持一个驱动多个node,HDF驱动模型如下图所示: -**图 1** HDF驱动模型 - - -![](figure/zh-cn_image_0000001054564784.png) +**图 1** HDF驱动模型 +![](figures/HDF驱动模型.png "HDF驱动模型") ## 驱动开发步骤 @@ -167,7 +165,7 @@ HDF框架以组件化的驱动模型作为核心设计思路,为开发者提 > DEVICE_PRELOAD_INVALID > } DevicePreload; > ``` -> 配置文件中preload 字段配成 0 (DEVICE\_PRELOAD\_ENABLE ),则系统启动过程中默认加载;配成1(DEVICE\_PRELOAD\_ENABLE\_STEP2),当系统支持快启的时候,则在系统完成之后再加载这一类驱动,否则和DEVICE\_PRELOAD\_ENABLE 含义相同;配成2(DEVICE\_PRELOAD\_DISABLE),则系统启动过程中默认不加载,支持后续动态加载,当用户态获取驱动服务(参考[消息机制](driver-hdf-news.md))时,如果驱动服务不存在时,HDF框架会尝试动态加载该驱动。 +> 配置文件中preload 字段配成 0 (DEVICE\_PRELOAD\_ENABLE ),则系统启动过程中默认加载;配成1(DEVICE\_PRELOAD\_ENABLE\_STEP2),当系统支持快启的时候,则在系统完成之后再加载这一类驱动,否则和DEVICE\_PRELOAD\_ENABLE 含义相同;配成2(DEVICE\_PRELOAD\_DISABLE),则系统启动过程中默认不加载,支持后续动态加载,当用户态获取驱动服务(参考[消息机制](driver-hdf-message-management.md))时,如果驱动服务不存在时,HDF框架会尝试动态加载该驱动。 >- 按序加载(需要驱动为默认加载) > 配置文件中的priority(取值范围为整数0到200)是用来表示host和驱动的优先级,不同的host内的驱动,host的priority值越小,驱动加载优先级越高;同一个host内驱动的priority值越小,加载优先级越高。 diff --git a/zh-cn/device-dev/driver/driver-hdf-manage.md b/zh-cn/device-dev/driver/driver-hdf-manage.md index 86cc85d8c7d56c8d5fbe544187e191cb48243a56..df612787c738041d32061dafd2d6ae8c27ac9f62 100644 --- a/zh-cn/device-dev/driver/driver-hdf-manage.md +++ b/zh-cn/device-dev/driver/driver-hdf-manage.md @@ -2,18 +2,20 @@ - [配置概述](#section59914284576) - [配置语法](#section533713333580) -- [关键字](#section1316625413586) -- [基本结构](#section173481622115918) -- [数据类型](#section96521601302) -- [预处理](#section8164295515) -- [注释](#section0338205819610) -- [引用修改](#section179799204716) -- [节点复制](#section382424014712) -- [删除](#section165211112586) -- [属性引用](#section192841514490) -- [模板](#section520134294) + - [关键字](#section4522107333) + - [基本结构](#section853042911312) + - [数据类型](#section177001259134) + - [预处理](#section14867121641) + - [注释](#section1323412417) + - [引用修改](#section193708571145) + - [节点复制](#section1487792020513) + - [删除](#section1096515391155) + - [属性引用](#section20271317611) + - [模板](#section958819191063) + - [配置生成](#section106152531919) -- [hc-gen介绍](#section8260625101012) + - [hc-gen介绍](#section359734416616) + ## 配置概述 @@ -26,10 +28,8 @@ HC-GEN**\(H**DF **C**onfiguration **G**enerator**\)**是HCS配置转换工具 以下是使用HCB模式的典型应用场景: -**图 1** 配置使用流程图 - - -![](figure/zh-cn_image_0000001053405727.png) +**图 1** 配置使用流程图 +![](figures/配置使用流程图.png "配置使用流程图") HCS经过HC-GEN编译生成HCB文件,HDF驱动框架中的HCS Parser模块会从HCB文件中重建配置树,HDF驱动模块使用HCS Parser提供的配置读取接口获取配置内容。 @@ -37,7 +37,7 @@ HCS经过HC-GEN编译生成HCB文件,HDF驱动框架中的HCS Parser模块会 HCS的语法介绍如下: -## 关键字 +### 关键字 HCS配置语法保留了以下关键字。 @@ -90,7 +90,7 @@ HCS配置语法保留了以下关键字。
-## 基本结构 +### 基本结构 HCS主要分为属性\(Attribute\)和节点\(Node\)两种结构。 @@ -137,7 +137,7 @@ HCS主要分为属性\(Attribute\)和节点\(Node\)两种结构。 - 节点中可以增加match\_attr属性,其值为一个全局唯一的字符串。在解析配置时可以调用查找接口以该属性的值查找到包含该属性的节点。 -## 数据类型 +### 数据类型 在属性定义中使用自动数据类型,不显式指定类型,属性支持的数据类型如下: @@ -170,7 +170,7 @@ attr_bar = ["hello", "world"]; bool类型中**true**表示真,**false**表示假。 -## 预处理 +### 预处理 **include** @@ -184,7 +184,7 @@ bool类型中**true**表示真,**false**表示假。 - 文件名必须使用双引号\(""\),不在同一目录使用相对路径引用。被include文件也必须是合法的HCS文件。 - 多个include,如果存在相同的节点,后者覆盖前者,其余的节点依次展开。 -## 注释 +### 注释 支持两种注释风格。 @@ -206,7 +206,7 @@ bool类型中**true**表示真,**false**表示假。 >多行注释不支持嵌套。 -## 引用修改 +### 引用修改 引用修改可以实现修改另外任意一个节点的内容,语法为: @@ -258,7 +258,7 @@ root { - 引用同级node,可以直接使用node名称,否则被引用的节点必须使用绝对路径,节点间使用“.”分隔,root表示根节点,格式为root开始的节点路径序列,例如root.foo.bar即为一个合法的绝对路径。 - 如果出现修改冲突(即多处修改同一个属性),编译器将提示warning,因为这种情况下只会生效某一个修改而导致最终结果不确定。 -## 节点复制 +### 节点复制 节点复制可以实现在节点定义时从另一个节点先复制内容,用于定义内容相似的节点。语法为: @@ -297,9 +297,9 @@ root { 在上述示例中,编译后bar节点即包含attr\_0属性也包含attr\_1属性,在bar中对attr\_0的修改不会影响到foo。 -在foo和bar在同级node中可不指定foo的路径,否则需要使用绝对路径引用,参考[引用修改](#section179799204716)。 +在foo和bar在同级node中可不指定foo的路径,否则需要使用绝对路径引用,参考[引用修改](#section193708571145)。 -## 删除 +### 删除 要对include导入的base配置树中不需要的节点或属性进行删除,可以使用delete关键字。下面的举例中sample1.hcs通过include导入了sample2.hcs中的配置内容,并使用delete删除了sample2.hcs中的attribute2属性和foo\_2节点,示例如下: @@ -333,7 +333,7 @@ root { >![](../public_sys-resources/icon-note.gif) **说明:** >在同一个HCS文件中不允许使用delete,建议直接删除不需要的属性。 -## 属性引用 +### 属性引用 为了在解析配置时快速定位到关联的节点,可以把节点作为属性的右值,通过读取属性查找到对应节点。语法为: @@ -353,7 +353,7 @@ node2 { } ``` -## 模板 +### 模板 模板的用途在于生成严格一致的node结构,以便对同类型node进行遍历和管理。 @@ -398,7 +398,7 @@ root { hc-gen是配置生成的工具,可以对HCS配置语法进行检查并把HCS源文件转化成HCB二进制文件。 -## hc-gen介绍 +### hc-gen介绍 hc-gen参数说明: diff --git a/zh-cn/device-dev/driver/driver-hdf-news.md b/zh-cn/device-dev/driver/driver-hdf-message-management.md similarity index 100% rename from zh-cn/device-dev/driver/driver-hdf-news.md rename to zh-cn/device-dev/driver/driver-hdf-message-management.md diff --git a/zh-cn/device-dev/driver/driver-hdf.md b/zh-cn/device-dev/driver/driver-hdf.md index 8c8cb3c3482f81e23937cc64408f039989db86f3..ab9e53aaec4cbbf64fdc75af82412bc847c742b2 100644 --- a/zh-cn/device-dev/driver/driver-hdf.md +++ b/zh-cn/device-dev/driver/driver-hdf.md @@ -6,7 +6,7 @@ - **[驱动服务管理](driver-hdf-servicemanage.md)** -- **[驱动消息机制管理](driver-hdf-news.md)** +- **[驱动消息机制管理](driver-hdf-message-management.md)** - **[配置管理](driver-hdf-manage.md)** diff --git a/zh-cn/device-dev/driver/driver-peripherals-external-des.md b/zh-cn/device-dev/driver/driver-peripherals-external-des.md index 282d5ed4542e43a142e8262b5f3bbefb87510d36..2c2a6fe9d6e99631e69e1935e9f48de9a09b4117 100644 --- a/zh-cn/device-dev/driver/driver-peripherals-external-des.md +++ b/zh-cn/device-dev/driver/driver-peripherals-external-des.md @@ -2,25 +2,21 @@ - [概述](#section729758162218) - [WLAN驱动接口架构](#section178022416377) - - [接口说明](#section149681312202415) - -- [开发指导](#section15957746172412) - - [开发步骤](#section11776186132513) +- [接口说明](#section7331102018815) +- [开发步骤](#section15957746172412) - [开发实例](#section1395253612512) ## 概述 -WLAN是基于HDF(Hardware Driver Foundation)驱动框架开发的模块,该模块可实现跨操作系统迁移,自适应器件差异,模块化拼装编译等功能。各WLAN厂商驱动开发人员可根据WLAN模块提供的向下统一接口适配各自的驱动代码,实现如下能力:建立/关闭WLAN热点、扫描、关联WLAN热点等;对HDI层向上提供能力如下:设置MAC地址、设置发射功率、获取设备的MAC地址等。[WLAN模块框架图](#fig967034316227)如下: - -**图 1** WLAN框架 - +WLAN是基于HDF(Hardware Driver Foundation)驱动框架开发的模块,该模块可实现跨操作系统迁移,自适应器件差异,模块化拼装编译等功能。各WLAN厂商驱动开发人员可根据WLAN模块提供的向下统一接口适配各自的驱动代码,实现如下能力:建立/关闭WLAN热点、扫描、关联WLAN热点等;对HDI层向上提供能力如下:设置MAC地址、设置发射功率、获取设备的MAC地址等。[WLAN模块框架图](#fig4415112614415)如下: -![](figure/zh-cn_image_0000001170383063.png) +**图 1** WLAN框架 +![](figures/WLAN框架.png "WLAN框架") ### WLAN驱动接口架构 -WLAN模块有三部分对外开放的API接口,如[下图2](#fig15016395217)所示: +WLAN模块有三部分对外开放的API接口,如[下图2](#fig1492411431166)所示: 1. 对HDI层提供的能力接口。 @@ -28,12 +24,10 @@ WLAN模块有三部分对外开放的API接口,如[下图2](#fig15016395217) 3. 提供给各厂商实现的能力接口。 -**图 2** WLAN模块开放能力分布图 +**图 2** WLAN模块开放能力分布图 +![](figures/WLAN模块开放能力分布图.png "WLAN模块开放能力分布图") - -![](figure/接口分布图4.png) - -### 接口说明 +## 接口说明 WLAN驱动模块提供给驱动开发人员可直接调用的能力接口,主要功能有:创建/释放WifiModule、关联/取消关联、申请/释放NetBuf、lwip的pbuf和NetBuf的相互转换等。提供的部分接口说明如[表1](#table1521573319472)所示: @@ -232,12 +226,10 @@ WLAN驱动模块对HDI层提供的能力接口,主要功能有:创建/销毁 -## 开发指导 +## 开发步骤 WLAN驱动基于HDF框架和PLATFORM框架开发,不区分OS和芯片平台,为不同厂商的WLAN模组提供统一的驱动模型,各WLAN模组厂商根据如下指导适配WLAN驱动框架。 -### 开发步骤 - 1. 通过wifi\_config.hcs文件,配置硬件参数:module\(不同feature\),芯片等。 2. 解析配置文件, 生成全量配置的结构体对象。 3. Module初始化,创建Module。 diff --git a/zh-cn/device-dev/driver/driver-peripherals-lcd-des.md b/zh-cn/device-dev/driver/driver-peripherals-lcd-des.md index 95b1bfb103250a7e3e7f4d0a0af69c1a62b10dfd..983c1a67604d034f75b102d57359c688dd414adb 100644 --- a/zh-cn/device-dev/driver/driver-peripherals-lcd-des.md +++ b/zh-cn/device-dev/driver/driver-peripherals-lcd-des.md @@ -1,11 +1,8 @@ # LCD - [概述](#section141575391542) - - [接口说明](#section14711163785519) - -- [开发指导](#section12394223125615) - - [开发步骤](#section515923045814) - +- [接口说明](#section53793327396) +- [开发步骤](#section12394223125615) - [开发实例](#section7441155155813) ## 概述 @@ -13,48 +10,43 @@ LCD(Liquid Crystal Display)液晶显示驱动,对LCD进行上电,并通过接口初始化LCD内部寄存器,使LCD正常工作。Display驱动模型基于HDF( Hardware Driver Foundation)[驱动框架](driver-hdf-overview.md)开发,实现跨OS、跨平台,为LCD硬件提供上下电功能、发送初始化序列功能,使LCD进入正常的工作模式,显示芯片平台侧的图像数据,基于HDF驱动框架的Display驱动模型如[图1](#fig69138814229)。 **图 1** 基于HDF驱动框架的Display驱动模型 -![](figure/基于HDF驱动框架的Display驱动模型.png "基于HDF驱动框架的Display驱动模型") - -- **Display驱动模型介绍** +![](figures/基于HDF驱动框架的Display驱动模型.png "基于HDF驱动框架的Display驱动模型") - Display驱动模型主要由平台驱动层、芯片平台适配层、LCD器件驱动层三部分组成。驱动模型基于HDF驱动框架开发,通过Platform层和OSAL层提供的接口,屏蔽内核形态的差异,使得器件驱动可以便利的迁移到不同OS及芯片平台。模型向上对接Display公共hal层,支撑HDI接口的实现,通过Display-HDI(Hardware Display Interface)对图形服务提供各类驱动能力接口。 +**Display驱动模型介绍** - (1)Display平台驱动层:通过HDF提供的IOService数据通道,与公共Hal层对接,集中接收并处理各类上层调用指令; +Display驱动模型主要由平台驱动层、芯片平台适配层、LCD器件驱动层三部分组成。驱动模型基于HDF驱动框架开发,通过Platform层和OSAL层提供的接口,屏蔽内核形态的差异,使得器件驱动可以便利的迁移到不同OS及芯片平台。模型向上对接Display公共hal层,支撑HDI接口的实现,通过Display-HDI(Hardware Display Interface)对图形服务提供各类驱动能力接口。 - (2)SOC平台驱动适配层:借助此SOC适配层,实现Display驱动和SOC侧驱动解耦,主要完成芯片平台相关的参数配置,并传递平台驱动层的调用到器件驱动层; +- (1)Display平台驱动层:通过HDF提供的IOService数据通道,与公共Hal层对接,集中接收并处理各类上层调用指令; +- (2)SOC平台驱动适配层:借助此SOC适配层,实现Display驱动和SOC侧驱动解耦,主要完成芯片平台相关的参数配置,并传递平台驱动层的调用到器件驱动层; +- (3)LCD器件驱动层:在器件驱动层中,主要实现和器件自身强相关的驱动适配接口,例如发送初始化序列、上下电、背光设置等。 - (3)LCD器件驱动层:在器件驱动层中,主要实现和器件自身强相关的驱动适配接口,例如发送初始化序列、上下电、背光设置等。 +基于Display驱动模型开发LCD驱动,可以借助平台提供的各种能力及接口,较大程度的降低器件驱动的开发周期和难度,提升开发效率。 - 基于Display驱动模型开发LCD驱动,可以借助平台提供的各种能力及接口,较大程度的降低器件驱动的开发周期和难度,提升开发效率。 - - -### 接口说明 +## 接口说明 LCD接口通常可分为MIPI DSI接口、TTL接口和LVDS接口,常用的是MIPI DSI接口和TTL接口,下面对常用的MIPI DSI接口和TTL接口作简要介绍。 - MIPI DSI接口 **图 2** MIPI DSI接口 - ![](figure/MIPI-DSI接口.png "MIPI-DSI接口") + ![](figures/MIPI-DSI接口.png "MIPI-DSI接口") MIPI DSI接口是MIPI(移动行业处理器接口)联盟定义的显示接口,主要用于移动终端显示屏接口,接口数据传输遵循MIPI协议,MIPI DSI接口为数据接口,传输图像数据,通常情况下MIPI DSI接口的控制信息以MIPI包形式通过MIPI DSI接口发送到对端IC,不需要额外的外设接口。 - TTL接口 **图 3** TTL接口 - ![](figure/TTL接口.png "TTL接口") + ![](figures/TTL接口.png "TTL接口") TTL(Transistor Transistor Logic)即晶体管-晶体管逻辑,TTL电平信号由TTL器件产生,TTL器件是数字集成电路的一大门类,它采用双极型工艺制造,具有高速度、低功耗和品种多等特点。 TTL接口是并行方式传输数据的接口,有数据信号、时钟信号和控制信号(行同步、帧同步、数据有效信号等),在控制信号控制下完成数据传输。通常TTL接口的LCD,内部寄存器读写需要额外的外设接口,比如SPI接口、I2C接口等。 -## 开发指导 +## 开发步骤 Display驱动模型基于HDF驱动框架、Platform接口及OSAL接口开发,可以做到不区分OS(LiteOS、Linux)和芯片平台(Hi35xx、Hi38xx、V3S等),为LCD器件提供统一的驱动模型。 -### 开发步骤 - 1. 添加LCD驱动相关的设备描述配置。 2. 在SOC平台驱动适配层中适配对应的芯片平台驱动。 3. 添加器件驱动,并在驱动入口函数Init中注册Panel驱动数据,驱动数据接口主要包括如下接口: diff --git a/zh-cn/device-dev/driver/driver-peripherals-sensor-des.md b/zh-cn/device-dev/driver/driver-peripherals-sensor-des.md index a548abe552a26190c342b9f758a681f83861d271..a730125bec3130e4dffbd09e927ae032e0ece215 100644 --- a/zh-cn/device-dev/driver/driver-peripherals-sensor-des.md +++ b/zh-cn/device-dev/driver/driver-peripherals-sensor-des.md @@ -1,11 +1,8 @@ # SENSOR - [概述](#section3634112111) - - [接口说明](#section188213414114) - -- [开发指导](#section1140943382) - - [开发步骤](#section7893102915819) - +- [接口说明](#section20930112117478) +- [开发步骤](#section1140943382) - [开发实例](#section257750691) - [测试指导](#section106021256121219) @@ -14,7 +11,7 @@ Sensor(传感器)驱动模块为上层Sensor服务系统提供稳定的Sensor基础能力API,包括Sensor列表查询、Sensor启停、Sensor订阅及去订阅,Sensor参数配置等功能;基于HDF(**H**ardware **D**river **F**oundation)驱动框架开发的Sensor驱动模型,实现跨操作系统迁移,器件差异配置等功能。Sensor驱动模型如下图1所示: **图 1** Sensor驱动模型图 -![](figure/Sensor驱动模型图.png "Sensor驱动模型图") +![](figures/Sensor驱动模型图.png "Sensor驱动模型图") Sensor驱动模型对外开放的API接口能力如下: @@ -22,7 +19,7 @@ Sensor驱动模型对外开放的API接口能力如下: - 提供Sensor驱动模型能力接口:依赖HDF驱动框架实现Sensor器件驱动的注册,加载,去注册,器件探测等能力,提供同一类型Sensor器件驱动归一接口, 寄存器配置解析操作接口,总线访问抽象接口,平台抽象接口。 - 提供开发者实现的能力接口:依赖HDF驱动框架的HCS\(**H**DF **C**onfiguration **S**ource\)配置管理,根据同类型Sensor差异化配置,实现Sensor器件参数序列化配置和器件部分操作接口,简化Sensor器件驱动开发。 -### 接口说明 +## 接口说明 Sensor驱动模型对HDI开放的API接口功能,参考表1。 @@ -188,7 +185,7 @@ Sensor驱动模型对驱动开发者开放的功能接口,驱动开发者无 -Sensor驱动模型要求驱动开发者实现的接口功能,参考表3 +Sensor驱动模型要求驱动开发者实现的接口功能,参考表3。 **表 3** Sensor驱动模型要求驱动开发者实现的接口列表 @@ -205,22 +202,22 @@ Sensor驱动模型要求驱动开发者实现的接口功能,参考表3

int32_t init(void)

-

传感器器设备探测成功后,需要对传感器器设备初始化配置。

+

传感器设备探测成功后,需要对传感器器设备初始化配置。

int32_t GetInfo(struct SensorBasicInfo *info)

-

从传感器器设备的HCS配置里,获取当前传感器设备的基本信息。

+

从传感器设备的HCS配置里,获取当前传感器设备的基本信息。

int32_t Enable(void)

-

根据当前传感器器设备的HCS配置,下发传感器设备使能操作组的寄存器配置。

+

根据当前传感器设备的HCS配置,下发传感器设备使能操作组的寄存器配置。

int32_t Disable(void)

-

根据当前传感器器设备的HCS配置,下发传感器设备去使能操作组的寄存器配置。

+

根据当前传感器设备的HCS配置,下发传感器设备去使能操作组的寄存器配置。

int32_t SetBatch(int64_t samplingInterval, int64_t reportInterval)

@@ -248,12 +245,10 @@ Sensor驱动模型要求驱动开发者实现的接口功能,参考表3 接口实现参考[SENSOR](#section257750691)章节。 -## 开发指导 +## 开发步骤 Sensor驱动是基于HDF框架、PLATFORM和OSAL基础接口进行开发,不区分操作系统和芯片平台,为不同Sensor器件提供统一的驱动模型。本篇开发指导以加速度计传感器为例,介绍传感器驱动开发。 -### 开发步骤 - 1. 加速度计传感器驱动注册。HDF驱动框架会提供统一的驱动管理模型,通过加速计传感器模块配置信息,识别并加载对应模块驱动。 2. 加速度计传感器驱动初始化和去初始化。HDF驱动框架通过init入口函数,依次启动传感器设备驱动加载和分配传感器设备数据配置资源。HDF驱动框架通过release函数,释放驱动加载的资源和配置。 3. 加速度计传感器寄存器组配置解析。不同类型传感器需要在hcs里配置器件对应的HCS配置文件,然后再设备驱动启动过程中探测器件是否在位,然后加载对应的配置文件,生成配置的结构体对象。 diff --git a/zh-cn/device-dev/driver/driver-peripherals-touch-des.md b/zh-cn/device-dev/driver/driver-peripherals-touch-des.md index d2e35a9c8822e87d3a8bbdec7be37f0994ca72d8..354ba5fd8ff9534bcda398340836968cd9cca440 100644 --- a/zh-cn/device-dev/driver/driver-peripherals-touch-des.md +++ b/zh-cn/device-dev/driver/driver-peripherals-touch-des.md @@ -1,11 +1,8 @@ # TOUCHSCREEN - [概述](#section175431838101617) - - [接口说明](#section17667171301711) - -- [开发指导](#section65745222184) - - [开发步骤](#section865734181916) - +- [接口说明](#section105459441659) +- [开发步骤](#section65745222184) - [开发实例](#section263714411191) - [设备描述配置](#section18249155619195) - [板级配置及器件私有配置](#section3571192072014) @@ -21,13 +18,13 @@ - **Touchscreen驱动层次说明** - 本节主要介绍基于input驱动模型开发touchscreen器件驱动,其整体的框架模型如[图1](#fig6251184817261)。 + 本节主要介绍基于input驱动模型开发touchscreen器件驱动,input模型整体的框架如[图1](#fig6251184817261)。 Input驱动模型基于HDF驱动框架、PLATFORM接口、OSAL接口进行开发,向上对接规范化的驱动接口HDI(Hardware Driver Interface)层,通过Input-HDI层对外提供硬件能力,即上层input service可以通过HDI接口层获取相应的驱动能力,进而操控touchscreen等输入设备。 **图 1** 基于HDF驱动框架的input驱动模型 -![](figure/基于HDF驱动框架的input驱动模型.png "基于HDF驱动框架的input驱动模型") +![](figures/基于HDF驱动框架的input驱动模型.png "基于HDF驱动框架的input驱动模型") - **Input驱动模型介绍** @@ -49,7 +46,7 @@ 在HDF(Hardware Driver Foundation)[驱动管理框架](driver-hdf-development.md)的基础上,input驱动模型调用OSAL接口层和Platfom接口层提供的基础接口进行开发,包括bus通信接口、操作系统原生接口(memory、lock、thread、timer等)。由于OSAL接口和Platform接口屏蔽了芯片平台差异,所以基于input驱动模型实现的touchscreen驱动可以进行跨平台、跨OS迁移,以便逐步实现驱动的一次开发,多端部署。 -### 接口说明 +## 接口说明 Touchscreen器件的硬件接口相对简单,根据PIN脚的属性,可以简单分为如下三类: @@ -58,7 +55,7 @@ Touchscreen器件的硬件接口相对简单,根据PIN脚的属性,可以简 - 通信接口 **图 2** Touchscreen器件常用管脚 -![](figure/Touchscreen器件常用管脚.png "Touchscreen器件常用管脚") +![](figures/Touchscreen器件常用管脚.png "Touchscreen器件常用管脚") 如上图所示的三类接口,分别做简要说明如下: @@ -73,30 +70,29 @@ Touchscreen器件的硬件接口相对简单,根据PIN脚的属性,可以简 - INT:中断管脚,需要在驱动初始化时,配置为输入上拉状态。在驱动IC检测到外部触摸信号后,通过操作中断管脚来触发中断,器件驱动则会在中断处理函数中进行报点数据读取等操作。 3. **通信接口** - - I2C:由于touchscreen的报点数据量相对较少,所以一般选用I2C方式传输数据。I2C的具体协议及对应操作接口,可以参考Platform接口层中的[“I2C”使用指南](driver-platform-i2c-des.md#section1695201514281)。 - - SPI:部分厂商,由于需要传递的数据不止报点坐标,而是需要获取基础容值,数据量较大,所以会选用SPI通信方式。SPI的具体协议及对应操作接口,可以参考Platform接口层中的[“SPI” 使用指南](driver-platform-spi-des.md#section71363452477)。 + - I2C:由于touchscreen的报点数据量相对较少,所以一般选用I2C方式传输数据。I2C的具体协议及对应操作接口,可以参考Platform接口层中的[“I2C”使用指南](driver-platform-i2c-des.md#section5361140416)。 + - SPI:部分厂商,由于需要传递的数据不止报点坐标,而是需要获取基础容值,数据量较大,所以会选用SPI通信方式。SPI的具体协议及对应操作接口,可以参考Platform接口层中的[“SPI” 使用指南](driver-platform-spi-des.md#section193356154511)。 -## 开发指导 +## 开发步骤 Input驱动模型是基于HDF框架、Platform接口和OSAL接口开发,不区分操作系统和芯片平台,为touchscreen等输入器件提供统一的驱动开发架构。 -- 如下以touchscreen器件驱动为例,说明input驱动模型的完整加载流程: - - (1)设备描述配置:由开发者参考已有模板进行设备描述配置,包括驱动加载顺序、板级硬件信息、器件私有数据信息等。 +如下以touchscreen器件驱动为例,说明input驱动模型的完整加载流程: - (2)加载input设备管理驱动:input设备管理驱动由HDF驱动加载,完成设备manager的创建并对其初始化。 +(1)设备描述配置:由开发者参考已有模板进行设备描述配置,包括驱动加载顺序、板级硬件信息、器件私有数据信息等。 - (3)加载平台驱动:平台驱动由HDF框架加载,主要完成板级配置解析及硬件初始化,并提供器件注册接口。 +(2)加载input设备管理驱动:input设备管理驱动由HDF驱动加载,完成设备manager的创建并对其初始化。 - (4)加载器件驱动:器件驱动也由HDF框架加载,完成器件设备的实例化,包括器件私有配置解析和平台预留的差异化接口适配。 +(3)加载平台驱动:平台驱动由HDF框架加载,主要完成板级配置解析及硬件初始化,并提供器件注册接口。 - (5)器件设备向平台驱动注册:将实例化的器件设备向平台驱动注册,实现设备和驱动的绑定,并完成中断注册、上下电等器件初始化工作。 +(4)加载器件驱动:器件驱动也由HDF框架加载,完成器件设备的实例化,包括器件私有配置解析和平台预留的差异化接口适配。 - (6)input设备注册:在器件初始化完成后,实例化input设备,并将其注册到input manager进行管理。 +(5)器件设备向平台驱动注册:将实例化的器件设备向平台驱动注册,实现设备和驱动的绑定,并完成中断注册、上下电等器件初始化工作。 +(6)input设备注册:在器件初始化完成后,实例化input设备,并将其注册到input manager进行管理。 -### 开发步骤 +请参考如下相关步骤: 1. 设备描述配置 @@ -108,7 +104,7 @@ Input驱动模型是基于HDF框架、Platform接口和OSAL接口开发,不区 3. 实现器件差异化适配接口 - 根据硬件单板设计的通信接口,使用Platform接口层提供的管脚操作接口配置对应的复位管脚、中断管脚以及电源操作,对于GPIO的操作,可参考[GPIO操作接口指导](driver-platform-gpio-des.md#section259614242196) + 根据硬件单板设计的通信接口,使用Platform接口层提供的管脚操作接口配置对应的复位管脚、中断管脚以及电源操作,对于GPIO的操作,可参考[GPIO操作接口指导](driver-platform-gpio-des.md#section1635911016188) ## 开发实例 diff --git a/zh-cn/device-dev/driver/driver-peripherals-usb-des.md b/zh-cn/device-dev/driver/driver-peripherals-usb-des.md deleted file mode 100755 index 86a2769f6fe8f0ddb9b28ea37b1d77f841416e63..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/driver/driver-peripherals-usb-des.md +++ /dev/null @@ -1,1572 +0,0 @@ -# USB - -- [概述](#section175431838101617) - - [接口说明](#section17667171301711) - -- [开发指导](#section65745222184) - - [Host DDK API驱动开发步骤](#section865734181916) - - [Host RAW API驱动开发步骤](#section865734181916) - - [Device DDK API驱动开发步骤](#section865734181916) - -- [开发实例](#section263714411191) - - [Host DDK API驱动开发](#section18249155619195) - - [Host RAW API驱动开发](#section3571192072014) - - [Device DDK API驱动开发](#section6356758162015) - - -## 概述 - -USB Host部分,主要包括协议封装、设备管理、驱动安装与卸载等。 - -USB Device部分,支持USB功能设备的开发,提供USB设备相关功能,主要包括设备管理、配置管理、IO管理,实现USB功能设备创建、配置、数据通信等。 - -USB Host驱动模型如下图1所示: - -**图 1** USB Host驱动模型图 -![](figure/USB-Host驱动模型图.png "USB Host驱动模型图") - -**图 2** USB Device驱动模型图 -![](figure/USB-Device驱动模型图.png "USB Device驱动模型图") - -USB驱动模型对外开放的API接口能力如下: - -- Usb Host DDK提供给用户态可直接调用的驱动能力接口,按照功能分类三大类:DDK初始化类、对interface对象操作类、对request对象操作类,可以提供DDK初始化、interface绑定和释放,打开和关闭操作,request的申请和释放,同步和异步传输等。 -- Usb Deivce DDK提供设备管理、IO管理、配置管理,主要功能有:创建和删除设备、获取和打开接口、同步和异步传输等。 - -### 接口说明 - -USB驱动模型Host侧开放的API接口功能,参考表1。 - -**表 1** USB驱动模型Host侧开放的API接口功能介绍 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

头文件

-

接口名称

-

功能描述

-

usb_ddk_interface.h

-

-

-

int32_t UsbInitHostSdk(struct UsbSession **session);

-

USB主机端驱动开发工具包初始化

-

int32_t UsbExitHostSdk(const struct UsbSession *session);

-

USB主机端驱动开发工具包退出

-

const struct UsbInterface *UsbClaimInterface(const struct UsbSession *session, uint8_t busNum, uint8_t usbAddr, uint8_t interfaceIndex);

-

获取USB接口对象

-

int UsbReleaseInterface(const struct UsbInterface *interfaceObj);

-

释放USB接口对象

-

int UsbAddOrRemoveInterface(const struct UsbSession *session, uint8_t busNum, uint8_t usbAddr, uint8_t interfaceIndex, UsbInterfaceStatus status);

-

增加移除接口

-

UsbInterfaceHandle *UsbOpenInterface(const struct UsbInterface *interfaceObj);

-

打开USB对象接口

-

int32_t UsbCloseInterface(const UsbInterfaceHandle *interfaceHandle);

-

关闭USB接口对象

-

int32_t UsbSelectInterfaceSetting(const UsbInterfaceHandle *interfaceHandle, uint8_t settingIndex, struct UsbInterface **interfaceObj);

-

设置可选配置

-

int32_t UsbGetPipeInfo(const UsbInterfaceHandle *interfaceHandle, uint8_t settingIndex, uint8_t pipeId, struct UsbPipeInfo *pipeInfo);

-

获取指定可选设置的管道信息

-

int32_t UsbClearInterfaceHalt(const UsbInterfaceHandle *interfaceHandle, uint8_t pipeAddress);

-

清除指定索引的管道状态

-

struct UsbRequest *UsbAllocRequest(const UsbInterfaceHandle *interfaceHandle, int isoPackets, int length);

-

分配请求对象

-

int UsbFreeRequest(const struct UsbRequest *request);

-

释放请求对象

-

int UsbSubmitRequestAsync(const struct UsbRequest *request);

-

发送异步请求

-

int32_t UsbFillRequest(const struct UsbRequest *request, const UsbInterfaceHandle *interfaceHandle, const struct UsbRequestParams *params);

-

填充请求

-

sint UsbCancelRequest(const struct UsbRequest *request);

-

取消异步请求

-

int UsbSubmitRequestSync(const struct UsbRequest *request);

-

发送同步请求

-

usb_raw_api.h

-

-

-

-

-

-

int UsbRawInit(struct UsbSession **session);

-

USB驱动开发工具包专家模式初始化

-

int UsbRawExit(const struct UsbSession *session);

-

USB驱动开发工具包专家模式退出

-

UsbRawHandle *UsbRawOpenDevice(const struct UsbSession *session, uint8_t busNum, uint8_t usbAddr);

-

打开USB设备对象

-

int UsbRawCloseDevice(const UsbRawHandle *devHandle);

-

关闭USB设备对象

-

int UsbRawSendControlRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbControlRequestData *requestData);

-

执行同步控制传输

-

int UsbRawSendBulkRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRequestData *requestData);

-

执行同步批量传输

-

int UsbRawSendInterruptRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRequestData *requestData);

-

执行同步中断传输

-

int UsbRawGetConfigDescriptor(const UsbRawDevice *rawDev, uint8_t configIndex, struct UsbRawConfigDescriptor **config);

-

获取给定设备指定ID的设备配置描述符

-

void UsbRawFreeConfigDescriptor(const struct UsbRawConfigDescriptor *config);

-

释放配置描述符内存空间

-

int UsbRawGetConfiguration(const UsbRawHandle *devHandle, int *config);

-

获取当前激活配置

-

int UsbRawSetConfiguration(const UsbRawHandle *devHandle, int config);

-

设置当前激活配置

-

int UsbRawGetDescriptor(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRawDescriptorParam *param, const unsigned char *data);

-

获取描述符信息

-

UsbRawDevice *UsbRawGetDevice(const UsbRawHandle *devHandle);

-

由设备句柄获取设备指针

-

int UsbRawGetDeviceDescriptor(const UsbRawDevice *rawDev, struct UsbDeviceDescriptor *desc);

-

获取给定设备的USB设备描述符

-

int UsbRawClaimInterface(const UsbRawHandle *devHandle, int interfaceNumber);

-

声明给定设备句柄上的接口

-

int UsbRawReleaseInterface(const UsbRawHandle *devHandle, int interfaceNumber);

-

释放之前声明的接口

-

int UsbRawResetDevice(const UsbRawHandle *devHandle);

-

复位设备

-

struct UsbRawRequest *UsbRawAllocRequest(const UsbRawHandle *devHandle, int isoPackets, int length);

-

分配一个带有指定数量的同步包描述符的传输请求

-

int UsbRawFreeRequest(const struct UsbRawRequest *request);

-

释放之前分配的传输请求

-

int UsbRawFillBulkRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRawFillRequestData *fillData);

-

填充批量传输请求所需信息

-

int UsbRawFillControlSetup(const unsigned char *setup, const struct UsbControlRequestData *requestData);

-

填充控制传输设置包所需信息

-

int UsbRawFillControlRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRawFillRequestData *fillData);

-

填充控制传输请求所需信息

-

int UsbRawFillInterruptRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRawFillRequestData *fillData);

-

填充中断传输请求所需信息

-

int UsbRawFillIsoRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRawFillRequestData *fillData);

-

填充同步传输(Isochronous Transfers)请求所需信息

-

int UsbRawSubmitRequest(const struct UsbRawRequest *request);

-

提交一个传输请求

-

int UsbRawCancelRequest(const struct UsbRawRequest *request);

-

取消一个传输请求

-

int UsbRawHandleRequests(const UsbRawHandle *devHandle);

-

传输请求事件完成处理

-
- -USB驱动模型Device侧开放的API接口功能,参考表2。 - -**表 2** USB驱动模型Device侧开放的API接口功能介绍 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

头文件

-

接口名称

-

功能描述

-

usbfn_device.h

-

-

-

const struct UsbFnDevice *UsbFnCreateDevice(const char *udcName, const struct UsbFnDescriptorData *descriptor);

-

创建Usb设备

-

int UsbFnRemoveDevice(struct UsbFnDevice *fnDevice);

-

删除Usb设备

-

const struct UsbFnDevice *UsbFnGetDevice(const char *udcName);

-

获取Usb设备

-

usbfn_interface.h

-

-

-

-

-

-

int UsbFnStartRecvInterfaceEvent(struct UsbFnInterface *interface, uint32_t eventMask, UsbFnEventCallback callback, void *context);

-

开始接受Event事件

-

int UsbFnStopRecvInterfaceEvent(struct UsbFnInterface *interface);

-

停止接受Event事件

-

UsbFnInterfaceHandle UsbFnOpenInterface(struct UsbFnInterface *interface);

-

打开一个接口

-

int UsbFnCloseInterface(UsbFnInterfaceHandle handle);

-

关闭一个接口

-

int UsbFnGetInterfacePipeInfo(struct UsbFnInterface *interface, uint8_t pipeId, struct UsbFnPipeInfo *info);

-

获取管道信息

-

int UsbFnSetInterfaceProp(const struct UsbFnInterface *interface, const char *name, const char *value);

-

设置自定义属性

-

usbfn_request.h

-

-

-

-

-

-

-

-

struct UsbFnRequest *UsbFnAllocCtrlRequest(UsbFnInterfaceHandle handle, uint32_t len);

-

申请一个控制请求

-

struct UsbFnRequest *UsbFnAllocRequest(UsbFnInterfaceHandle handle, uint8_t pipe, uint32_t len);

-

申请一个数据请求

-

int UsbFnFreeRequest(struct UsbFnRequest *req);

-

释放一个请求

-

int UsbFnSubmitRequestAsync(struct UsbFnRequest *req);

-

发送异步请求

-

int UsbFnSubmitRequestSync(struct UsbFnRequest *req, uint32_t timeout);

-

发送同步请求

-

int UsbFnCancelRequest(struct UsbFnRequest *req);

-

取消请求

-
- -## 开发指导 - -USB驱动是基于HDF框架、PLATFORM和OSAL基础接口进行开发,不区分操作系统和芯片平台,为不同USB器件提供统一的驱动模型。本篇开发指导以串口为例,分别介绍USB Host和USB Device驱动开发。 - -### 开发步骤 - -### Host DDK API驱动开发步骤 - -1. 驱动匹配表配置。 -2. 初始化Host DDK。 -3. 待步骤2初始化完后获取UsbInterface接口对象。 -4. 打开步骤3获取到的UsbInterface接口对象,获取对应接口的UsbInterfaceHandle对象。 -5. 根据步骤4获取到的UsbInterfaceHandle对象,获取指定索引为pinpeIndex的pipeInfo信息。 -6. 为步骤4获取到的UsbInterfaceHandle预先分配待发送的IO Request对象。 -7. 根据输入参数params填充步骤6预先分配的IO Request。 -8. 提交IO Request对象,可以选择同步或异步两种模式。 - - -### Host RAW API驱动开发步骤 - -1. 驱动匹配表配置。 -2. 初始化Host RAW,并打开USB设备,然后获取描述符,通过描述符获取接口、端点信息。 -3. 分配Request,并根据传输类型使用如下接口对Request进行填充。 -4. 提交IO Request对象,可以选择同步或异步两种模式。 - -### Device DDK API驱动开发步骤 - -1. 构造描述符。 -2. 创建设备,使用步骤1构造的描述符实例化一个USB设备。 -3. 根据创建的设备获取接口(UsbFnDeviceGetInterface),获取Pipe信息(UsbFnInterfaceGetPipeInfo),打开接口获取Handle(UsbFnInterfaceOpen),根据Handle和Pipe号获取Request(UsbFnRequestAlloc)。 -4. 接收Event事件(UsbFnInterfaceStartRecvEvent)如Enable、Setup等事件,回调函数(UsbFnEventCallback)中对Event事件做出响应。 -5. 收发数据,可以选择同步异步发送模式。 - -## 开发实例 - -本实例提供USB串口驱动开发示例,并简要对具体关键点进行开发说明。 - -### Host DDK API驱动开发 - -``` -root { - module = "usb_pnp_device"; - usb_pnp_config { - match_attr = "usb_pnp_match"; - usb_pnp_device_id = "UsbPnpDeviceId"; - UsbPnpDeviceId { - idTableList = [ - "host_acm_table" - ]; - host_acm_table { - //驱动模块名,该字段的值必须和驱动入口结构的moduleName一致 - moduleName = "usbhost_acm"; - //驱动对外发布服务的名称,必须唯一 - serviceName = "usbhost_acm_pnp_service"; - //驱动私有数据匹配关键字 - deviceMatchAttr = "usbhost_acm_pnp_matchAttr"; - //从该字段开始(包含该字段)之后数据长度,以byte为单位 - length = 21; - //USB驱动匹配规则vendorId+productId+interfaceSubClass+interfaceProtocol+interfaceNumber - matchFlag = 0x0303; - //厂商编号 - vendorId = 0x12D1; - //产品编号 - productId = 0x5000; - //设备出厂编号,低16位 - bcdDeviceLow = 0x0000; - //设备出厂编号,高16位 - bcdDeviceHigh = 0x0000; - //USB分配的设备类代码 - deviceClass = 0; - //USB分配的子类代码 - deviceSubClass = 0; - //USB分配的设备协议代码 - deviceProtocol = 0; - //接口类型,根据实际需要可填写多个 - interfaceClass = [0]; - //接口子类型,根据实际需要可填写多个 - interfaceSubClass = [2, 0]; - //接口所遵循的协议,根据实际需要可填写多个 - interfaceProtocol = [1, 2]; - //接口的编号,根据实际需要可填写多个 - interfaceNumber = [2, 3]; - } - } - } -} - -#include "usb_serial.h" -#include "hdf_base.h" -#include "hdf_log.h" -#include "osal_mem.h" -#include "osal_time.h" -#include "securec.h" -#include "usb_ddk_interface.h" -#include "hdf_usb_pnp_manage.h" - -#define HDF_LOG_TAG USB_HOST_ACM -#define STR_LEN 512 - -static struct UsbRequest *g_syncRequest = NULL; -static struct UsbRequest *g_ctrlCmdRequest = NULL; -static bool g_acmReleaseFlag = false; -static uint8_t *g_acmReadBuffer = NULL; -... -static int SerialCtrlMsg(struct AcmDevice *acm, uint8_t request, - uint16_t value, void *buf, uint16_t len) -{ - int ret; - uint16_t index = acm->intPipe->interfaceId; - struct UsbControlParams controlParams = {}; - struct UsbRequestParams parmas = {}; - if (acm == NULL || buf == NULL) { - HDF_LOGE("%{public}s:invalid param", __func__); - return HDF_ERR_IO; - } - if (acm->ctrlReq == NULL) { - acm->ctrlReq = UsbAllocRequest(acm->ctrDevHandle, 0, len); - if (acm->ctrlReq == NULL) { - HDF_LOGE("%{public}s: UsbAllocRequest faild", __func__); - return HDF_ERR_IO; - } - } - - controlParams.request = request; - controlParams.target = USB_REQUEST_TARGET_INTERFACE; - controlParams.reqType = USB_REQUEST_TYPE_CLASS; - controlParams.directon = USB_REQUEST_DIR_TO_DEVICE; - controlParams.value = value; - controlParams.index = index; - controlParams.data = buf; - controlParams.size = len; - - parmas.interfaceId = USB_CTRL_INTERFACE_ID; - parmas.pipeAddress = acm->ctrPipe->pipeAddress; - parmas.pipeId = acm->ctrPipe->pipeId; - parmas.requestType = USB_REQUEST_PARAMS_CTRL_TYPE; - parmas.timeout = USB_CTRL_SET_TIMEOUT; - parmas.ctrlReq = UsbControlSetUp(&controlParams); - ret = UsbFillRequest(acm->ctrlReq, acm->ctrDevHandle, &parmas); - if (HDF_SUCCESS != ret) { - HDF_LOGE("%{public}s: faile, ret=%{public}d ", __func__, ret); - return ret; - } - ret = UsbSubmitRequestSync(acm->ctrlReq); //发送同步IO Request - if (HDF_SUCCESS != ret) { - HDF_LOGE("UsbSubmitRequestSync faile, ret=%{public}d ", ret); - return ret; - } - if (!acm->ctrlReq->compInfo.status) { - HDF_LOGE("%{public}s status=%{public}d ", __func__, acm->ctrlReq->compInfo.status); - } - return HDF_SUCCESS; -} -... -static struct UsbInterface *GetUsbInterfaceById(const struct AcmDevice *acm, - uint8_t interfaceIndex) -{ - struct UsbInterface *tmpIf = NULL; - tmpIf = (struct UsbInterface *)UsbClaimInterface(acm->session, acm->busNum, \ - acm->devAddr, interfaceIndex); //获取UsbInterface接口对象 - return tmpIf; -} -... -static struct UsbPipeInfo *EnumePipe(const struct AcmDevice *acm, - uint8_t interfaceIndex, UsbPipeType pipeType, UsbPipeDirection pipeDirection) -{ - uint8_t i; - int ret; - struct UsbInterfaceInfo *info = NULL; - UsbInterfaceHandle *interfaceHandle = NULL; - if (pipeType == USB_PIPE_TYPE_CONTROL) - { - info = &acm->ctrIface->info; - interfaceHandle = acm->ctrDevHandle; - } - else - { - info = &acm->iface[interfaceIndex]->info; - interfaceHandle = InterfaceIdToHandle(acm, info->interfaceIndex); - } - - for (i = 0; i <= info->pipeNum; i++) { - struct UsbPipeInfo p; - ret = UsbGetPipeInfo(interfaceHandle, info->curAltSetting, i, &p);//获取指定索引为i的pipeInfo信息 - if (ret < 0) { - continue; - } - if ((p.pipeDirection == pipeDirection) && (p.pipeType == pipeType)) { - struct UsbPipeInfo *pi = OsalMemCalloc(sizeof(*pi)); - if (pi == NULL) { - HDF_LOGE("%{public}s: Alloc pipe failed", __func__); - return NULL; - } - p.interfaceId = info->interfaceIndex; - *pi = p; - return pi; - } - } - return NULL; -} - -static struct UsbPipeInfo *GetPipe(const struct AcmDevice *acm, - UsbPipeType pipeType, UsbPipeDirection pipeDirection) -{ - uint8_t i; - if (acm == NULL) { - HDF_LOGE("%{public}s: invalid parmas", __func__); - return NULL; - } - for (i = 0; i < acm->interfaceCnt; i++) { - struct UsbPipeInfo *p = NULL; - if (!acm->iface[i]) { - continue; - } - p = EnumePipe(acm, i, pipeType, pipeDirection); - if (p == NULL) { - continue; - } - return p; - } - return NULL; -} - -/* HdfDriverEntry implementations */ -static int32_t UsbSerialDriverBind(struct HdfDeviceObject *device) -{ - struct UsbPnpNotifyServiceInfo *info = NULL; - errno_t err; - struct AcmDevice *acm = NULL; - if (device == NULL) { - HDF_LOGE("%s: device is null", __func__); - return HDF_ERR_INVALID_OBJECT; - } - acm = (struct AcmDevice *)OsalMemCalloc(sizeof(*acm)); - if (acm == NULL) { - HDF_LOGE("%s: Alloc usb serial device failed", __func__); - return HDF_FAILURE; - } - if (OsalMutexInit(&acm->lock) != HDF_SUCCESS) { - HDF_LOGE("%s:%d OsalMutexInit fail", __func__, __LINE__); - goto error; - } - info = (struct UsbPnpNotifyServiceInfo *)device->priv; - if (info != NULL) { - HDF_LOGD("%s:%d busNum=%d,devAddr=%d,interfaceLength=%d", \ - __func__, __LINE__, info->busNum, info->devNum, info->interfaceLength); - acm->busNum = info->busNum; - acm->devAddr = info->devNum; - acm->interfaceCnt = info->interfaceLength; - err = memcpy_s((void *)(acm->interfaceIndex), USB_MAX_INTERFACES, - (const void*)info->interfaceNumber, info->interfaceLength); - if (err != EOK) { - HDF_LOGE("%s:%d memcpy_s faile err=%d", \ - __func__, __LINE__, err); - goto lock_error; - } - } else { - HDF_LOGE("%s:%d info is NULL!", __func__, __LINE__); - goto lock_error; - } - acm->device = device; - device->service = &(acm->service); - acm->device->service->Dispatch = UsbSerialDeviceDispatch; - HDF_LOGD("UsbSerialDriverBind=========================OK"); - return HDF_SUCCESS; - -lock_error: - if (OsalMutexDestroy(&acm->lock)) { - HDF_LOGE("%s:%d OsalMutexDestroy fail", __func__, __LINE__); - } -error: - OsalMemFree(acm); - acm = NULL; - return HDF_FAILURE; -} -... -static int AcmAllocReadRequests(struct AcmDevice *acm) -{ - int ret; - struct UsbRequestParams readParmas = {}; - for (int i = 0; i < ACM_NR; i++) { - acm->readReq[i] = UsbAllocRequest(InterfaceIdToHandle(acm, acm->dataInPipe->interfaceId), 0, acm->readSize); //分配待发送的readReq IO Request对象 - if (!acm->readReq[i]) { - HDF_LOGE("readReq request faild\n"); - goto error; - } - readParmas.userData = (void *)acm; - readParmas.pipeAddress = acm->dataInPipe->pipeAddress; - readParmas.pipeId = acm->dataInPipe->pipeId; - readParmas.interfaceId = acm->dataInPipe->interfaceId; - readParmas.callback = AcmReadBulk; - readParmas.requestType = USB_REQUEST_PARAMS_DATA_TYPE; - readParmas.timeout = USB_CTRL_SET_TIMEOUT; - readParmas.dataReq.numIsoPackets = 0; - readParmas.dataReq.directon = (acm->dataInPipe->pipeDirection >> USB_PIPE_DIR_OFFSET) & 0x1; - readParmas.dataReq.length = acm->readSize; - ret = UsbFillRequest(acm->readReq[i], InterfaceIdToHandle(acm, acm->dataInPipe->interfaceId), &readParmas); //填充待发送的readReq对象 - if (HDF_SUCCESS != ret) { - HDF_LOGE("%{public}s: UsbFillRequest faile, ret=%{public}d \n", __func__, ret); - goto error; - } - } - return HDF_SUCCESS; - -error: - AcmFreeReadRequests(acm); - return HDF_ERR_MALLOC_FAIL; -} - -static int AcmAllocNotifyRequest(struct AcmDevice *acm) -{ - int ret; - struct UsbRequestParams intParmas = {}; - acm->notifyReq = UsbAllocRequest(InterfaceIdToHandle(acm, acm->intPipe->interfaceId), 0, acm->intSize); //分配待发送的中断IO Request对象 - if (!acm->notifyReq) { - HDF_LOGE("notifyReq request fail\n"); - return HDF_ERR_MALLOC_FAIL; - } - intParmas.userData = (void *)acm; - intParmas.pipeAddress = acm->intPipe->pipeAddress; - intParmas.pipeId = acm->intPipe->pipeId; - intParmas.interfaceId = acm->intPipe->interfaceId; - intParmas.callback = AcmCtrlIrq; - intParmas.requestType = USB_REQUEST_PARAMS_DATA_TYPE; - intParmas.timeout = USB_CTRL_SET_TIMEOUT; - intParmas.dataReq.numIsoPackets = 0; - intParmas.dataReq.directon = (acm->intPipe->pipeDirection >> USB_PIPE_DIR_OFFSET) & DIRECTION_MASK; - intParmas.dataReq.length = acm->intSize; - ret = UsbFillRequest(acm->notifyReq, InterfaceIdToHandle(acm, acm->intPipe->interfaceId), &intParmas); //填充预先分配的中断IO Request - if (HDF_SUCCESS != ret) { - HDF_LOGE("%{public}s: UsbFillRequest faile, ret=%{public}d \n", __func__, ret); - goto error; - } - return HDF_SUCCESS; - -error: - AcmFreeNotifyReqeust(acm); - return ret; -} - -static void AcmReleaseInterfaces(struct AcmDevice *acm) -{ - for (int i = 0; i < acm->interfaceCnt; i++) { - if (acm->iface[i]) { - UsbReleaseInterface(acm->iface[i]); - acm->iface[i] = NULL; - } - } - if (acm->ctrIface) { - UsbReleaseInterface(acm->ctrIface); - acm->ctrIface = NULL; - } -} - -static int32_t AcmClaimInterfaces(struct AcmDevice *acm) -{ - for (int i = 0; i < acm->interfaceCnt; i++) { - acm->iface[i] = GetUsbInterfaceById((const struct AcmDevice *)acm, acm->interfaceIndex[i]); //获取UsbInterface接口对象 - if (acm->iface[i] == NULL) { - HDF_LOGE("%{public}s: interface%{public}d is null", __func__, acm->interfaceIndex[i]); - goto error; - } - } - - acm->ctrIface = GetUsbInterfaceById((const struct AcmDevice *)acm, USB_CTRL_INTERFACE_ID); //获取控制接口对应的UsbInterface接口对象 - if (acm->ctrIface == NULL) { - HDF_LOGE("%{public}s: GetUsbInterfaceById null", __func__); - goto error; - } - - return HDF_SUCCESS; - - error: - AcmReleaseInterfaces(acm); - return HDF_FAILURE; -} - -static void AcmCloseInterfaces(struct AcmDevice *acm) -{ - for (int i = 0; i < acm->interfaceCnt; i++) { - if (acm->devHandle[i]) { - UsbCloseInterface(acm->devHandle[i]); - acm->devHandle[i] = NULL; - } - } - if (acm->ctrDevHandle) { - UsbCloseInterface(acm->ctrDevHandle); - acm->ctrDevHandle = NULL; - } -} - -static int32_t AcmOpenInterfaces(struct AcmDevice *acm) -{ - for (int i = 0; i < acm->interfaceCnt; i++) { - if (acm->iface[i]) { - acm->devHandle[i] = UsbOpenInterface(acm->iface[i]); //打开获取到的UsbInterface接口对象 - if (acm->devHandle[i] == NULL) { - HDF_LOGE("%{public}s: UsbOpenInterface null", __func__); - goto error; - } - } - } - acm->ctrDevHandle = UsbOpenInterface(acm->ctrIface); - if (acm->ctrDevHandle == NULL) { - HDF_LOGE("%{public}s: ctrDevHandle UsbOpenInterface null", __func__); - goto error; - } - - return HDF_SUCCESS; - -error: - AcmCloseInterfaces(acm); - return HDF_FAILURE; -} - -static int32_t AcmGetPipes(struct AcmDevice *acm) -{ - acm->dataInPipe = GetPipe(acm, USB_PIPE_TYPE_BULK, USB_PIPE_DIRECTION_IN);//获取dataInPipe的pipeInfo信息 - if (acm->dataInPipe == NULL) { - HDF_LOGE("dataInPipe is NULL"); - goto error; - } - - acm->dataOutPipe = GetPipe(acm, USB_PIPE_TYPE_BULK, USB_PIPE_DIRECTION_OUT);//获取dataOutPipe的pipeInfo信息 - if (acm->dataOutPipe == NULL) { - HDF_LOGE("dataOutPipe is NULL"); - goto error; - } - - acm->ctrPipe = EnumePipe(acm, acm->ctrIface->info.interfaceIndex, USB_PIPE_TYPE_CONTROL, USB_PIPE_DIRECTION_OUT); //获取控制pipe的pipeInfo信息 - if (acm->ctrPipe == NULL) { - HDF_LOGE("ctrPipe is NULL"); - goto error; - } - - acm->intPipe = GetPipe(acm, USB_PIPE_TYPE_INTERRUPT, USB_PIPE_DIRECTION_IN);//获取中断pipe的pipeInfo信息 - if (acm->intPipe == NULL) { - HDF_LOGE("intPipe is NULL"); - goto error; - } - - acm->readSize = acm->dataInPipe->maxPacketSize; - acm->writeSize = acm->dataOutPipe->maxPacketSize; - acm->ctrlSize = acm->ctrPipe->maxPacketSize; - acm->intSize = acm->intPipe->maxPacketSize; - - return HDF_SUCCESS; - -error: - AcmFreePipes(acm); - return HDF_FAILURE; -} - -static void AcmFreeRequests(struct AcmDevice *acm) -{ - if (g_syncRequest != NULL) { - UsbFreeRequest(g_syncRequest); - g_syncRequest = NULL; - } - AcmFreeReadRequests(acm); - AcmFreeNotifyReqeust(acm); - AcmFreeWriteRequests(acm); - AcmWriteBufFree(acm); -} - -static int32_t AcmAllocRequests(struct AcmDevice *acm) -{ - int32_t ret; - - if (AcmWriteBufAlloc(acm) < 0) { - HDF_LOGE("%{public}s: AcmWriteBufAlloc failed", __func__); - return HDF_ERR_MALLOC_FAIL; - } - - for (int i = 0; i < ACM_NW; i++) { - struct AcmWb *snd = &(acm->wb[i]); - snd->request = UsbAllocRequest(InterfaceIdToHandle(acm, acm->dataOutPipe->interfaceId), 0, acm->writeSize); //分配待发送的IO Request对象 - snd->instance = acm; - if (snd->request == NULL) { - HDF_LOGE("%{public}s:%{public}d snd request fail", __func__, __LINE__); - goto error_alloc_write_req; - } - } - - ret = AcmAllocNotifyRequest(acm); //分配并填充中断IO Request对象 - if (ret != HDF_SUCCESS) { - HDF_LOGE("%{public}s:%{public}d AcmAllocNotifyRequest fail", __func__, __LINE__); - goto error_alloc_int_req; - } - - ret = AcmAllocReadRequests(acm); //分配并填充readReq IO Request对象 - if (ret) { - HDF_LOGE("%{public}s:%{public}d AcmAllocReadRequests fail", __func__, __LINE__); - goto error_alloc_read_req; - } - - return HDF_SUCCESS; - -error_alloc_read_req: - AcmFreeNotifyReqeust(acm); -error_alloc_int_req: - AcmFreeWriteRequests(acm); -error_alloc_write_req: - AcmWriteBufFree(acm); - return HDF_FAILURE; -} - -static int32_t AcmInit(struct AcmDevice *acm) -{ - int32_t ret; - struct UsbSession *session = NULL; - - if (acm->initFlag == true) { - HDF_LOGE("%{public}s:%{public}d: initFlag is true", __func__, __LINE__); - return HDF_SUCCESS; - } - - ret = UsbInitHostSdk(NULL); //初始化Host DDK - if (ret != HDF_SUCCESS) { - HDF_LOGE("%{public}s: UsbInitHostSdk faild", __func__); - return HDF_ERR_IO; - } - acm->session = session; - - ret = AcmClaimInterfaces(acm); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%{public}s: AcmClaimInterfaces faild", __func__); - goto error_claim_interfaces; - } - - ret = AcmOpenInterfaces(acm); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%{public}s: AcmOpenInterfaces faild", __func__); - goto error_open_interfaces; - } - - ret = AcmGetPipes(acm); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%{public}s: AcmGetPipes failed", __func__); - goto error_get_pipes; - } - - ret = AcmAllocRequests(acm); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%{public}s: AcmAllocRequests failed", __func__); - goto error_alloc_reqs; - } - - acm->lineCoding.dwDTERate = CpuToLe32(DATARATE); - acm->lineCoding.bCharFormat = CHARFORMAT; - acm->lineCoding.bParityType = USB_CDC_NO_PARITY; - acm->lineCoding.bDataBits = USB_CDC_1_STOP_BITS; - acm->initFlag = true; - - HDF_LOGD("%{public}s:%{public}d========OK", __func__, __LINE__); - return HDF_SUCCESS; - -error_alloc_reqs: - AcmFreePipes(acm); -error_get_pipes: - AcmCloseInterfaces(acm); -error_open_interfaces: - AcmReleaseInterfaces(acm); -error_claim_interfaces: - UsbExitHostSdk(acm->session); - acm->session = NULL; - return ret; -} - -static void AcmRelease(struct AcmDevice *acm) -{ - if (acm->initFlag == false) { - HDF_LOGE("%{public}s:%{public}d: initFlag is false", __func__, __LINE__); - return; - } - - AcmFreeRequests(acm); - AcmFreePipes(acm); - AcmCloseInterfaces(acm); - AcmReleaseInterfaces(acm); - UsbExitHostSdk(acm->session); - acm->session = NULL; - - acm->initFlag = false; -} - -static int32_t UsbSerialDriverInit(struct HdfDeviceObject *device) -{ - int32_t ret; - struct AcmDevice *acm = NULL; - - if (device == NULL) { - HDF_LOGE("%{public}s: device is null", __func__); - return HDF_ERR_INVALID_OBJECT; - } - acm = (struct AcmDevice *)device->service; - OsalMutexInit(&acm->readLock); - OsalMutexInit(&acm->writeLock); - HDF_LOGD("%{public}s:%{public}d busNum=%{public}d,devAddr=%{public}d", \ - __func__, __LINE__, acm->busNum, acm->devAddr); - - ret = UsbSerialDeviceAlloc(acm); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%{public}s: Serial Device alloc faild", __func__); - } - - acm->initFlag = false; - g_acmReleaseFlag = false; - - HDF_LOGD("%{public}s:%{public}d init ok!", __func__, __LINE__); - - return ret; -} - -static void UsbSerialDriverRelease(struct HdfDeviceObject *device) -{ - struct AcmDevice *acm = NULL; - - if (device == NULL) { - HDF_LOGE("%{public}s: device is NULL", __func__); - return; - } - acm = (struct AcmDevice *)device->service; - if (acm == NULL) { - HDF_LOGE("%{public}s: acm is null", __func__); - return; - } - - g_acmReleaseFlag = true; - - if (acm->initFlag == true) { - HDF_LOGE("%{public}s:%{public}d AcmRelease", __func__, __LINE__); - AcmRelease(acm); - } - UsbSeriaDevicelFree(acm); - OsalMutexDestroy(&acm->writeLock); - OsalMutexDestroy(&acm->readLock); - OsalMutexDestroy(&acm->lock); - OsalMemFree(acm); - acm = NULL; - HDF_LOGD("%{public}s:%{public}d exit", __func__, __LINE__); -} - -struct HdfDriverEntry g_usbSerialDriverEntry = { - .moduleVersion = 1, - .moduleName = "usbhost_acm", //驱动模块名称,必须与hcs文件中配置的名称一致 - .Bind = UsbSerialDriverBind, - .Init = UsbSerialDriverInit, - .Release = UsbSerialDriverRelease, -}; -HDF_INIT(g_usbSerialDriverEntry); -``` - -### Host RAW API驱动开发 - -``` -root { - module = "usb_pnp_device"; - usb_pnp_config { - match_attr = "usb_pnp_match"; - usb_pnp_device_id = "UsbPnpDeviceId"; - UsbPnpDeviceId { - idTableList = [ - "host_acm_rawapi_table" - ]; - host_acm_rawapi_table { //驱动配置匹配表信息 - //驱动模块名,该字段的值必须和驱动入口结构的moduleName一致 - moduleName = "usbhost_acm_rawapi"; - //驱动对外发布服务的名称,必须唯一 - serviceName = "usbhost_acm_rawapi_service"; - //驱动私有数据匹配关键字 - deviceMatchAttr = "usbhost_acm_rawapi_matchAttr"; - //从该字段开始(包含该字段)之后数据长度,以byte为单位 - length = 21; - //USB驱动匹配规则vendorId+productId+interfaceSubClass+interfaceProtocol+interfaceNumber - matchFlag = 0x0303; - //厂商编号 - vendorId = 0x12D1; - //产品编号 - productId = 0x5000; - //设备出厂编号,低16位 - bcdDeviceLow = 0x0000; - //设备出厂编号,高16位 - bcdDeviceHigh = 0x0000; - //USB分配的设备类代码 - deviceClass = 0; - //USB分配的子类代码 - deviceSubClass = 0; - //USB分配的设备协议代码 - deviceProtocol = 0; - //接口类型,根据实际需要可填写多个 - interfaceClass = [0]; - //接口子类型,根据实际需要可填写多个 - interfaceSubClass = [2, 0]; - //接口所遵循的协议,根据实际需要可填写多个 - interfaceProtocol = [1, 2]; - //接口的编号,根据实际需要可填写多个 - interfaceNumber = [2, 3]; - } - } - } -} - -#include "usb_serial_rawapi.h" -#include -#include "osal_mem.h" -#include "osal_time.h" -#include "securec.h" -#include "hdf_base.h" -#include "hdf_log.h" -#include "hdf_usb_pnp_manage.h" - -#define HDF_LOG_TAG USB_HOST_ACM_RAW_API -#define USB_CTRL_REQ_SIZE 64 -#define USB_IO_THREAD_STACK_SIZE 8192 -#define USB_RAW_IO_SLEEP_MS_TIME 100 -#define USB_RAW_IO_STOP_WAIT_MAX_TIME 3 - -static struct UsbRawRequest *g_syncRequest = NULL; -static UsbRawIoProcessStatusType g_stopIoStatus = USB_RAW_IO_PROCESS_RUNNING; -struct OsalMutex g_stopIoLock; -static bool g_rawAcmReleaseFlag = false; -...... - -static int UsbGetConfigDescriptor(UsbRawHandle *devHandle, struct UsbRawConfigDescriptor **config) -{ - UsbRawDevice *dev = NULL; - int activeConfig; - int ret; - - if (devHandle == NULL) { - HDF_LOGE("%{public}s:%{public}d devHandle is NULL", - __func__, __LINE__); - return HDF_ERR_INVALID_PARAM; - } - - ret = UsbRawGetConfiguration(devHandle, &activeConfig); - if (ret) { - HDF_LOGE("%{public}s:%{public}d UsbRawGetConfiguration failed, ret=%{public}d", - __func__, __LINE__, ret); - return HDF_FAILURE; - } - HDF_LOGE("%{public}s:%{public}d activeConfig=%{public}d", __func__, __LINE__, activeConfig); - dev = UsbRawGetDevice(devHandle); - if (dev == NULL) { - HDF_LOGE("%{public}s:%{public}d UsbRawGetDevice failed", - __func__, __LINE__); - return HDF_FAILURE; - } - - ret = UsbRawGetConfigDescriptor(dev, activeConfig, config); - if (ret) { - HDF_LOGE("UsbRawGetConfigDescriptor failed, ret=%{public}d\n", ret); - return HDF_FAILURE; - } - - return HDF_SUCCESS; -} -... -static int UsbAllocWriteRequests(struct AcmDevice *acm) -{ - int i; - - for (i = 0; i < ACM_NW; i++) { - struct AcmWb *snd = &acm->wb[i]; - snd->request = UsbRawAllocRequest(acm->devHandle, 0, acm->dataOutEp->maxPacketSize); - snd->instance = acm; - if (snd->request == NULL) { - HDF_LOGE("%{public}s: UsbRawAllocRequest faild", __func__); - return HDF_ERR_MALLOC_FAIL; - } - } - - return HDF_SUCCESS; -} -... -/* HdfDriverEntry implementations */ -static int32_t UsbSerialDriverBind(struct HdfDeviceObject *device) -{ - struct AcmDevice *acm = NULL; - struct UsbPnpNotifyServiceInfo *info = NULL; - errno_t err; - - if (device == NULL) { - HDF_LOGE("%s: device is null", __func__); - return HDF_ERR_INVALID_OBJECT; - } - - acm = (struct AcmDevice *)OsalMemCalloc(sizeof(*acm)); - if (acm == NULL) { - HDF_LOGE("%s: Alloc usb serial device failed", __func__); - return HDF_FAILURE; - } - if (OsalMutexInit(&acm->lock) != HDF_SUCCESS) { - HDF_LOGE("%s:%d OsalMutexInit fail", __func__, __LINE__); - goto error; - } - - info = (struct UsbPnpNotifyServiceInfo *)device->priv; - if (info != NULL) { - acm->busNum = info->busNum; - acm->devAddr = info->devNum; - acm->interfaceCnt = info->interfaceLength; - err = memcpy_s((void *)(acm->interfaceIndex), USB_MAX_INTERFACES, - (const void*)info->interfaceNumber, info->interfaceLength); - if (err != EOK) { - HDF_LOGE("%s:%d memcpy_s faile err=%d", \ - __func__, __LINE__, err); - goto lock_error; - } - } else { - HDF_LOGE("%s:%d info is NULL!", __func__, __LINE__); - goto lock_error; - } - - device->service = &(acm->service); - device->service->Dispatch = UsbSerialDeviceDispatch; - acm->device = device; - HDF_LOGD("UsbSerialDriverBind=========================OK"); - return HDF_SUCCESS; - -lock_error: - if (OsalMutexDestroy(&acm->lock)) { - HDF_LOGE("%s:%d OsalMutexDestroy fail", __func__, __LINE__); - } -error: - OsalMemFree(acm); - acm = NULL; - return HDF_FAILURE; -} -... -static int UsbAllocReadRequests(struct AcmDevice *acm) -{ - struct UsbRawFillRequestData reqData; - int size = acm->dataInEp->maxPacketSize; - int ret; - - for (int i = 0; i < ACM_NR; i++) { - acm->readReq[i] = UsbRawAllocRequest(acm->devHandle, 0, size); - if (!acm->readReq[i]) { - HDF_LOGE("readReq request faild\n"); - return HDF_ERR_MALLOC_FAIL; - } - - reqData.endPoint = acm->dataInEp->addr; - reqData.numIsoPackets = 0; - reqData.callback = AcmReadBulkCallback; - reqData.userData = (void *)acm; - reqData.timeout = USB_CTRL_SET_TIMEOUT; - reqData.length = size; - - ret = UsbRawFillBulkRequest(acm->readReq[i], acm->devHandle, &reqData); - if (ret) { - HDF_LOGE("%{public}s: FillBulkRequest faile, ret=%{public}d \n", - __func__, ret); - return HDF_FAILURE; - } - } - - return HDF_SUCCESS; -} -... -static int UsbAllocNotifyRequest(struct AcmDevice *acm) -{ - struct UsbRawFillRequestData fillRequestData; - int size = acm->notifyEp->maxPacketSize; - int ret; - - acm->notifyReq = UsbRawAllocRequest(acm->devHandle, 0, size); - if (!acm->notifyReq) { - HDF_LOGE("notifyReq request fail\n"); - return HDF_ERR_MALLOC_FAIL; - } - - fillRequestData.endPoint = acm->notifyEp->addr; - fillRequestData.length = size; - fillRequestData.numIsoPackets = 0; - fillRequestData.callback = AcmNotifyReqCallback; - fillRequestData.userData = (void *)acm; - fillRequestData.timeout = USB_CTRL_SET_TIMEOUT; - - ret = UsbRawFillInterruptRequest(acm->notifyReq, acm->devHandle, &fillRequestData); - if (ret) { - HDF_LOGE("%{public}s: FillInterruptRequest faile, ret=%{public}d", __func__, ret); - return HDF_FAILURE; - } - - return HDF_SUCCESS; -} -... -static int32_t UsbSerialInit(struct AcmDevice *acm) -{ - struct UsbSession *session = NULL; - UsbRawHandle *devHandle = NULL; - int32_t ret; - - if (acm->initFlag == true) { - HDF_LOGE("%{public}s:%{public}d: initFlag is true", __func__, __LINE__); - return HDF_SUCCESS; - } - - ret = UsbRawInit(NULL); - if (ret) { - HDF_LOGE("%{public}s:%{public}d UsbRawInit faild", __func__, __LINE__); - return HDF_ERR_IO; - } - acm->session = session; - - devHandle = UsbRawOpenDevice(session, acm->busNum, acm->devAddr); - if (devHandle == NULL) { - HDF_LOGE("%{public}s:%{public}d UsbRawOpenDevice faild", __func__, __LINE__); - ret = HDF_FAILURE; - goto err_open_device; - } - acm->devHandle = devHandle; - ret = UsbGetConfigDescriptor(devHandle, &acm->config); - if (ret) { - HDF_LOGE("%{public}s:%{public}d UsbGetConfigDescriptor faild", __func__, __LINE__); - ret = HDF_FAILURE; - goto err_get_desc; - } - ret = UsbParseConfigDescriptor(acm, acm->config); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%{public}s:%{public}d UsbParseConfigDescriptor faild", __func__, __LINE__); - ret = HDF_FAILURE; - goto err_parse_desc; - } - - ret = AcmWriteBufAlloc(acm); - if (ret < 0) { - HDF_LOGE("%{public}s:%{public}d AcmWriteBufAlloc faild", __func__, __LINE__); - ret = HDF_FAILURE; - goto err_alloc_write_buf; - } - ret = UsbAllocWriteRequests(acm); - if (ret < 0) { - HDF_LOGE("%{public}s:%{public}d UsbAllocWriteRequests faild", __func__, __LINE__); - ret = HDF_FAILURE; - goto err_alloc_write_reqs; - } - ret = UsbAllocNotifyRequest(acm); - if (ret) { - HDF_LOGE("%{public}s:%{public}d UsbAllocNotifyRequests faild", __func__, __LINE__); - goto err_alloc_notify_req; - } - ret = UsbAllocReadRequests(acm); - if (ret) { - HDF_LOGE("%{public}s:%{public}d UsbAllocReadRequests faild", __func__, __LINE__); - goto err_alloc_read_reqs; - } - ret = UsbStartIo(acm); - if (ret) { - HDF_LOGE("%{public}s:%{public}d UsbAllocReadRequests faild", __func__, __LINE__); - goto err_start_io; - } - - acm->lineCoding.dwDTERate = CpuToLe32(DATARATE); - acm->lineCoding.bCharFormat = CHARFORMAT; - acm->lineCoding.bParityType = USB_CDC_NO_PARITY; - acm->lineCoding.bDataBits = USB_CDC_1_STOP_BITS; - - ret = UsbRawSubmitRequest(acm->notifyReq); - if (ret) { - HDF_LOGE("%{public}s:%{public}d UsbRawSubmitRequest failed", __func__, __LINE__); - goto err_submit_req; - } - - acm->initFlag = true; - - HDF_LOGD("%{public}s:%{public}d=========================OK", __func__, __LINE__); - - return HDF_SUCCESS; - -err_submit_req: - UsbStopIo(acm); -err_start_io: - UsbFreeReadRequests(acm); -err_alloc_read_reqs: - UsbFreeNotifyReqeust(acm); - err_alloc_notify_req: - UsbFreeWriteRequests(acm); -err_alloc_write_reqs: - AcmWriteBufFree(acm); -err_alloc_write_buf: - UsbReleaseInterfaces(acm); -err_parse_desc: - UsbRawFreeConfigDescriptor(acm->config); - acm->config = NULL; -err_get_desc: - (void)UsbRawCloseDevice(devHandle); -err_open_device: - UsbRawExit(acm->session); - - return ret; -} - -static void UsbSerialRelease(struct AcmDevice *acm) -{ - if (acm->initFlag == false) { - HDF_LOGE("%{public}s:%{public}d: initFlag is false", __func__, __LINE__); - return; - } - - /* stop io thread and release all resources */ - UsbStopIo(acm); - if (g_syncRequest != NULL) { - UsbRawFreeRequest(g_syncRequest); - g_syncRequest = NULL; - } - UsbFreeReadRequests(acm); - UsbFreeNotifyReqeust(acm); - UsbFreeWriteRequests(acm); - AcmWriteBufFree(acm); - (void)UsbRawCloseDevice(acm->devHandle); - UsbReleaseInterfaces(acm); - UsbRawFreeConfigDescriptor(acm->config); - acm->config = NULL; - UsbRawExit(acm->session); - - acm->initFlag = false; -} - -static int32_t UsbSerialDriverInit(struct HdfDeviceObject *device) -{ - struct AcmDevice *acm = NULL; - int32_t ret; - - if (device == NULL) { - HDF_LOGE("%{public}s:%{public}d device is null", __func__, __LINE__); - return HDF_ERR_INVALID_OBJECT; - } - acm = (struct AcmDevice *)device->service; - OsalMutexInit(&acm->readLock); - OsalMutexInit(&acm->writeLock); - - ret = UsbSerialDeviceAlloc(acm); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%{public}s:%{public}d UsbSerialDeviceAlloc faild", __func__, __LINE__); - } - - acm->initFlag = false; - g_rawAcmReleaseFlag = false; - - HDF_LOGD("%{public}s:%{public}d init ok!", __func__, __LINE__); - - return ret; -} - -static void UsbSerialDriverRelease(struct HdfDeviceObject *device) -{ - struct AcmDevice *acm = NULL; - if (device == NULL) { - HDF_LOGE("%{public}s: device is NULL", __func__); - return; - } - - acm = (struct AcmDevice *)device->service; - if (acm == NULL) { - HDF_LOGE("%{public}s: acm is null", __func__); - return; - } - - g_rawAcmReleaseFlag = true; - - if (acm->initFlag == true) { - HDF_LOGE("%{public}s:%{public}d UsbSerialRelease", __func__, __LINE__); - UsbSerialRelease(acm); - } - UsbSeriaDevicelFree(acm); - OsalMutexDestroy(&acm->writeLock); - OsalMutexDestroy(&acm->readLock); - OsalMutexDestroy(&acm->lock); - OsalMemFree(acm); - acm = NULL; - HDF_LOGD("%{public}s:%{public}d exit", __func__, __LINE__); -} - -struct HdfDriverEntry g_usbSerialRawDriverEntry = { - .moduleVersion = 1, - .moduleName = "usbhost_acm_rawapi", //驱动模块名称,必须与hcs文件中配置的名称一致 - .Bind = UsbSerialDriverBind, - .Init = UsbSerialDriverInit, - .Release = UsbSerialDriverRelease, -}; -HDF_INIT(g_usbSerialRawDriverEntry); -``` - -### Device DDK API驱动开发 -USB ACM设备核心代码路径为drivers\peripheral\usb\gadget\function\acm\cdcacm.c,其使用示例如下所示,首先根据描述符创建设备,然后获取接口,打开接口,获取Pipe信息,接收Event事件,接着进行USB通信(读写等),设备卸载时候,关闭接口,停止Event接收,删除设备。 - -``` -1、创建设备 -static int32_t AcmCreateFuncDevice(struct UsbAcmDevice *acm, - struct DeviceResourceIface *iface) -{ - struct UsbFnDevice *fnDev = NULL; -struct UsbFnDescriptorData descData; -uint8_t useHcs; - ... -if (useHcs == 0) { - descData.type = USBFN_DESC_DATA_TYPE_DESC; - descData.descriptor = &g_masterFuncDevice; -} else { - descData.type = USBFN_DESC_DATA_TYPE_PROP; - descData.property = device->property; -} -/* 创建设备 */ - fnDev = (struct UsbFnDevice *)UsbFnDeviceCreate(acm->udcName, &descData); - if (fnDev == NULL) { - HDF_LOGE("%{public}s: create usb function device failed", __func__); - return HDF_FAILURE; - } - ... -} -2、获取接口,打开接口,获取Pipe信息 -static int32_t AcmParseEachPipe(struct UsbAcmDevice *acm, struct UsbAcmInterface *iface) -{ - ... - for (i = 0; i < fnIface->info.numPipes; i++) { - struct UsbFnPipeInfo pipeInfo; -/* 获取pipe信息 */ - ret = UsbFnInterfaceGetPipeInfo(fnIface, i, &pipeInfo); - ... - } - return HDF_SUCCESS; -} -/* 获取接口,打开接口获取handle */ -static int32_t AcmParseEachIface(struct UsbAcmDevice *acm, struct UsbFnDevice *fnDev) -{ - ... - for (i = 0; i < fnDev->numInterfaces; i++) { - /* 获取接口 */ - fnIface = (struct UsbFnInterface *)UsbFnDeviceGetInterface(fnDev, i); - ... - /* 打开接口 */ - handle = UsbFnInterfaceOpen(fnIface); - ... - } - return HDF_SUCCESS; -} -3、接收Event事件 -static int32_t AcmAllocCtrlRequests(struct UsbAcmDevice *acm, int num) -{ - ... - req = UsbFnCtrlRequestAlloc(acm->ctrlIface.handle, - sizeof(struct UsbCdcLineCoding) + sizeof(struct UsbCdcLineCoding)); - ... -} -static int32_t AcmDriverInit(struct HdfDeviceObject *device) -{ -... -/* 开始接收Event */ - ret = UsbFnInterfaceStartRecvEvent(acm->ctrlIface.fn, 0xff, UsbAcmEventCallback, acm); - ... -} -4、进行USB通信(读写等) -static int32_t AcmSendNotifyRequest(struct UsbAcmDevice *acm, uint8_t type, - uint16_t value, void *data, uint32_t length) -{ -... -/* 异步发送 */ - ret = UsbFnRequestSubmitAsync(req); - ... -} -5、关闭接口,停止Event接收,删除设备 -static int32_t AcmReleaseFuncDevice(struct UsbAcmDevice *acm) -{ -int32_t ret; -/* 关闭接口 */ - (void)UsbFnInterfaceClose(acm->ctrlIface.handle); -(void)UsbFnInterfaceClose(acm->dataIface.handle); -/* 停止接收Event */ -(void)UsbFnInterfaceStopRecvEvent(acm->ctrlIface.fn); -/* 删除设备 */ - ret = UsbFnDeviceRemove(acm->fnDev); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%{public}s: remove usb function device failed", __func__); - } - return ret; -} -``` - diff --git a/zh-cn/device-dev/driver/driver-peripherals.md b/zh-cn/device-dev/driver/driver-peripherals.md index 8ef4078014c768b384834ecc52071d22ae7fbcda..61a697d04f8ee2ec878fa520879695fc0be5a8c5 100644 --- a/zh-cn/device-dev/driver/driver-peripherals.md +++ b/zh-cn/device-dev/driver/driver-peripherals.md @@ -1,4 +1,4 @@ -# 外设驱动开发 +# 外设驱动使用 - **[LCD](driver-peripherals-lcd-des.md)** 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 084a45ae25196225fac94efb74f7d4aac468217c..c82f0ed7ced87fb97f94629ccb3eace00811ffb6 100755 --- a/zh-cn/device-dev/driver/driver-platform-adc-develop.md +++ b/zh-cn/device-dev/driver/driver-platform-adc-develop.md @@ -1,317 +1,424 @@ -# ADC - -- [概述](#1) -- [开发步骤](#2) -- [开发实例](#3) - -## 概述 - -ADC(Analog to Digital Converter),即模拟-数字转换器,是一种将模拟信号转换成对应数字信号的设备,在HDF框架中,ADC模块接口适配模式采用统一服务模式,这需要一个设备服务来作为ADC模块的管理器,统一处理外部访问,这会在配置文件中有所体现。统一服务模式适合于同类型设备对象较多的情况,如ADC可能同时具备十几个控制器,采用独立服务模式需要配置更多的设备节点,且服务会占据内存资源。 - -![image1](figure/统一服务模式.png) - -## 开发步骤 - -ADC模块适配的三个环节是配置属性文件,实例化驱动入口,以及实例化核心层接口函数。 - -1. **实例化驱动入口:** - - - 实例化HdfDriverEntry结构体成员。 - - 调用HDF_INIT将HdfDriverEntry实例化对象注册到HDF框架中。 - -2. **配置属性文件:** - - - 在device_info.hcs文件中添加deviceNode描述。 - - 【可选】添加adc_config.hcs器件属性文件。 - -3. **实例化ADC控制器对象:** - - - 初始化AdcDevice成员。 - - 实例化AdcDevice成员AdcMethod,其定义和成员说明见下 - -4. **驱动调试:** - - 【可选】针对新增驱动程序,建议验证驱动基本功能,例如挂载后的信息反馈,信号采集的成功与否等。 - -> ![](../public_sys-resources/icon-note.gif) **说明:** -> AdcMethod定义 -> -> ```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); -> }; -> ``` -> -> 表1 AdcMethod结构体成员的回调函数功能说明 -> -> |函数成员|入参|出参|返回值|功能| -> |-|-|-|-|-| -> |read|**device**: 结构体指针,核心层ADC控制器;
**channel**:uint32_t,传入的通道号;|**val**:uint32_t指针,要传出的信号数据;|HDF_STATUS相关状态|读取ADC采样的信号数据| -> |stop |**device**: 结构体指针,核心层ADC控制器;|无|HDF_STATUS相关状态|关闭ADC设备| -> |start |**device**: 结构体指针,核心层ADC控制器;|无|HDF_STATUS相关状态|开启ADC设备| - - -## 开发实例 - -接下来以 adc_hi35xx.c 为示例, 展示需要厂商提供哪些内容来完整实现设备功能 - -1. 驱动开发首先需要实例化驱动入口,驱动入口必须为HdfDriverEntry(在 hdf_device_desc.h 中定义)类型的全局变量,且moduleName要和device_info.hcs中保持一致。HDF框架会将所有加载的驱动的HdfDriverEntry对象首地址汇总,形成一个类似数组的段地址空间,方便上层调用。 - - 一般在加载驱动时HDF会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。 - -- ADC驱动入口参考 - - > ADC模块这种类型的控制器会出现很多个设备挂接的情况,因而在HDF框架中首先会为这类型的设备创建一个管理器对象。这样,需要打开某个设备时,管理器对象会根据指定参数查找到指定设备。 - > - > ADC管理器的驱动由核心层实现,**厂商不需要关注这部分内容的实现,这个但在实现Init函数的时候需要调用核心层的AdcDeviceAdd函数,它会实现相应功能。** - - ```c - 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文件中增加对应的器件属性**。 - -- 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 中 - } - } - } - } - ``` - -- adc_config.hcs 配置参考 - - ```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; - } - } - } - } - ``` - -3. 完成驱动入口注册之后,最后一步就是以核心层AdcDevice对象的初始化为核心,包括初始化厂商自定义结构体(传递参数和数据),实例化AdcDevice成员AdcMethod(让用户可以通过接口来调用驱动底层函数),实现HdfDriverEntry成员函数(Bind,Init,Release) - - -- 自定义结构体参考 - - > 从驱动的角度看,自定义结构体是参数和数据的载体,而且adc_config.hcs文件中的数值会被HDF读入通过DeviceResourceIface来初始化结构体成员,其中一些重要数值也会传递给核心层AdcDevice对象,例如设备号、总线号等。 - - ```c - struct Hi35xxAdcDevice { - 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 delta; - uint32_t deglitch; - uint32_t glitchSample; - uint32_t rate; //【必要】采样率 - }; - - //AdcDevice是核心层控制器结构体,其中的成员在Init函数中会被赋值 - struct AdcDevice { - const struct AdcMethod *ops; - OsalSpinlock spin; - uint32_t devNum; - uint32_t chanNum; - const struct AdcLockMethod *lockOps; - void *priv; - }; - ``` - - -- **【重要】** AdcDevice成员回调函数结构体AdcMethod的实例化,AdcLockMethod回调函数结构体本例未实现,若要实例化,可参考I2C驱动开发,其他成员在Init函数中初始化 - - ```c - static const struct AdcMethod g_method = { - .read = Hi35xxAdcRead, - .stop = Hi35xxAdcStop, - .start = Hi35xxAdcStart, - }; - ``` - -- **init函数参考** - - > **入参:** - > HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息 - > - > **返回值:** - > HDF_STATUS相关状态 (下表为部分展示,如需使用其他状态,可见//drivers/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 |传输失败| - > - > **函数说明:** - > 初始化自定义结构体对象,初始化AdcDevice成员,并调用核心层AdcDeviceAdd函数。 - - ```c - static int32_t Hi35xxAdcInit(struct HdfDeviceObject *device) - { - int32_t ret; - struct DeviceResourceNode *childNode = NULL; - ... - //遍历、解析adc_config.hcs中的所有配置节点,并分别调用Hi35xxAdcParseInit函数来初始化device - DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) { - ret = Hi35xxAdcParseInit(device, childNode);//函数定义见下 - ... - } - return ret; - } - - 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; - - __ERR__: - if (hi35xx != NULL) { //不成功的话,需要反向执行初始化相关函数 - if (hi35xx->regBase != NULL) { - OsalIoUnmap((void *)hi35xx->regBase); - hi35xx->regBase = NULL; - } - AdcDeviceRemove(&hi35xx->device); - OsalMemFree(hi35xx); - } - return ret; - } - ``` - -- **Release 函数参考** - - > **入参:** - > HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息 - > - > **返回值:** - > 无 - > - > **函数说明:** - > 释放内存和删除控制器,该函数需要在驱动入口结构体中赋值给 Release 接口, 当HDF框架调用Init函数初始化驱动失败时,可以调用 Release 释放驱动资源。所有强制转换获取相应对象的操作**前提**是在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);//函数定义见下 - } - } - - 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); - } - return; - } - ``` \ No newline at end of file +# ADC + +- [概述](#section268031773165048) +- [接口说明](#section752964871810) +- [开发步骤](#section100579767165048) +- [开发实例](#section1745221471165048) + +## 概述 + +ADC(Analog to Digital Converter),即模拟-数字转换器,是一种将模拟信号转换成对应数字信号的设备,在HDF框架中,ADC模块接口适配模式采用统一服务模式,这需要一个设备服务来作为ADC模块的管理器,统一处理外部访问,这会在配置文件中有所体现。统一服务模式适合于同类型设备对象较多的情况,如ADC可能同时具备十几个控制器,采用独立服务模式需要配置更多的设备节点,且服务会占据内存资源。 + +**图 1** ADC统一服务 +![](figures/ADC统一服务.png "ADC统一服务") + +## 接口说明 + +AdcMethod定义: + +``` +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); +}; +``` + +**表 1** AdcMethod结构体成员的回调函数功能说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

函数成员

+

入参

+

出参

+

返回值

+

功能

+

read

+

device: 结构体指针,核心层ADC控制器;channel:uint32_t,传入的通道号;

+

val:uint32_t指针,要传出的信号数据;

+

HDF_STATUS相关状态

+

读取ADC采样的信号数据

+

stop

+

device: 结构体指针,核心层ADC控制器;

+

+

HDF_STATUS相关状态

+

关闭ADC设备

+

start

+

device: 结构体指针,核心层ADC控制器;

+

+

HDF_STATUS相关状态

+

开启ADC设备

+
+ +## 开发步骤 + +ADC模块适配的三个环节是配置属性文件,实例化驱动入口,以及实例化核心层接口函数。 + +1. **实例化驱动入口:** + - 实例化HdfDriverEntry结构体成员。 + - 调用HDF\_INIT将HdfDriverEntry实例化对象注册到HDF框架中。 + +2. **配置属性文件:** + - 在device\_info.hcs文件中添加deviceNode描述。 + - 【可选】添加adc\_config.hcs器件属性文件。 + +3. **实例化ADC控制器对象:** + - 初始化AdcDevice成员。 + - 实例化AdcDevice成员AdcMethod。 + + >![](../public_sys-resources/icon-note.gif) **说明:** + >实例化AdcDevice成员AdcMethod,其定义和成员说明见[接口说明](#section752964871810)。 + + +4. **驱动调试:** + + 【可选】针对新增驱动程序,建议验证驱动基本功能,例如挂载后的信息反馈,信号采集的成功与否等。 + + +## 开发实例 + +接下来以 adc\_hi35xx.c 为示例, 展示需要厂商提供哪些内容来完整实现设备功能。 + +1. 驱动开发首先需要实例化驱动入口,驱动入口必须为HdfDriverEntry(在 hdf\_device\_desc.h 中定义)类型的全局变量,且moduleName要和device\_info.hcs中保持一致。HDF框架会将所有加载的驱动的HdfDriverEntry对象首地址汇总,形成一个类似数组的段地址空间,方便上层调用。 + + 一般在加载驱动时HDF会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。 + + 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文件中增加对应的器件属性。 + + - device\_info.hcs 配置参考。 + + ``` + 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 中 + } + } + } + } + ``` + + - adc\_config.hcs 配置参考。 + + ``` + 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; + } + } + } + } + ``` + +3. 完成驱动入口注册之后,最后一步就是以核心层AdcDevice对象的初始化为核心,包括初始化厂商自定义结构体(传递参数和数据),实例化AdcDevice成员AdcMethod(让用户可以通过接口来调用驱动底层函数),实现HdfDriverEntry成员函数(Bind,Init,Release)。 + - 自定义结构体参考。 + + 从驱动的角度看,自定义结构体是参数和数据的载体,而且adc\_config.hcs文件中的数值会被HDF读入通过DeviceResourceIface来初始化结构体成员,其中一些重要数值也会传递给核心层AdcDevice对象,例如设备号、总线号等。 + + ``` + struct Hi35xxAdcDevice { + 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 delta; + uint32_t deglitch; + uint32_t glitchSample; + uint32_t rate; //【必要】采样率 + }; + + //AdcDevice是核心层控制器结构体,其中的成员在Init函数中会被赋值 + struct AdcDevice { + const struct AdcMethod *ops; + OsalSpinlock spin; + uint32_t devNum; + uint32_t chanNum; + const struct AdcLockMethod *lockOps; + void *priv; + }; + ``` + + - AdcDevice成员回调函数结构体AdcMethod的实例化,AdcLockMethod回调函数结构体本例未实现,若要实例化,可参考I2C驱动开发,其他成员在Init函数中初始化。 + + ``` + static const struct AdcMethod g_method = { + .read = Hi35xxAdcRead, + .stop = Hi35xxAdcStop, + .start = Hi35xxAdcStart, + }; + ``` + + - init函数参考 + + 入参: + + HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息。 + + 返回值: + + HDF\_STATUS相关状态 (下表为部分展示,如需使用其他状态,可见//drivers/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

+

传输失败

+
+ + 函数说明: + + 初始化自定义结构体对象,初始化AdcDevice成员,并调用核心层AdcDeviceAdd函数。 + + ``` + static int32_t Hi35xxAdcInit(struct HdfDeviceObject *device) + { + int32_t ret; + struct DeviceResourceNode *childNode = NULL; + ... + //遍历、解析adc_config.hcs中的所有配置节点,并分别调用Hi35xxAdcParseInit函数来初始化device + DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) { + ret = Hi35xxAdcParseInit(device, childNode);//函数定义见下 + ... + } + return ret; + } + + 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; + + __ERR__: + if (hi35xx != NULL) { //不成功的话,需要反向执行初始化相关函数 + if (hi35xx->regBase != NULL) { + OsalIoUnmap((void *)hi35xx->regBase); + hi35xx->regBase = NULL; + } + AdcDeviceRemove(&hi35xx->device); + OsalMemFree(hi35xx); + } + return ret; + } + ``` + + - Release 函数参考 + + 入参: + + HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息。 + + 返回值: + + 无。 + + 函数说明: + + 释放内存和删除控制器,该函数需要在驱动入口结构体中赋值给 Release 接口, 当HDF框架调用Init函数初始化驱动失败时,可以调用 Release 释放驱动资源。所有强制转换获取相应对象的操作**前提**是在Init函数中具备对应赋值的操作。 + + ``` + 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);//函数定义见下 + } + } + + 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); + } + return + ``` + + + diff --git a/zh-cn/device-dev/driver/driver-platform-develop.md b/zh-cn/device-dev/driver/driver-platform-develop.md deleted file mode 100755 index 53685a6ada0c5c400426bd550413589093df75cc..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/driver/driver-platform-develop.md +++ /dev/null @@ -1,12 +0,0 @@ -# 平台驱动开发 - - **[GPIO](driver-platform-gpio-develop.md)** - - **[I2C](driver-platform-i2c-develop.md)** - - **[RTC](driver-platform-rtc-develop.md)** - - **[SDIO](driver-platform-sdio-develop.md)** - - **[SPI](driver-platform-spi-develop.md)** - - **[UART](driver-platform-uart-develop.md)** - - **[WATCHDOG](driver-platform-watchdog-develop.md)** - - **[MIPI_DSI](driver-platform-mipidsi-develop.md)** - - **[MMC](driver-platform-mmc-develop.md)** - - **[PWM](driver-platform-pwm-develop.md)** - - **[ADC](driver-platform-adc-develop.md)** diff --git a/zh-cn/device-dev/driver/driver-platform-gpio-des.md b/zh-cn/device-dev/driver/driver-platform-gpio-des.md index d4e67c7a5167857f6a3091f277b3da9a98c26490..28cc26f4f695d821cc92e153a7c18c65e95fda4b 100644 --- a/zh-cn/device-dev/driver/driver-platform-gpio-des.md +++ b/zh-cn/device-dev/driver/driver-platform-gpio-des.md @@ -1,8 +1,7 @@ -# GPIO +# GPIO - [概述](#section1635911016188) - - [接口说明](#section17715915181611) - +- [接口说明](#section589913442203) - [使用指导](#section259614242196) - [使用流程](#section103477714216) - [确定GPIO管脚号](#section370083272117) @@ -22,63 +21,63 @@ GPIO接口定义了操作GPIO管脚的标准方法集合,包括: - 设置管脚中断服务函数:设置一个管脚的中断响应函数,以及中断触发方式 - 使能和禁止管脚中断:禁止或使能管脚中断 -### 接口说明 +## 接口说明 **表 1** GPIO驱动API接口功能介绍 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -364,7 +318,7 @@ repo sync -c repo forall -c 'git lfs pull' ``` -## 源码目录简介 +## 源码目录 下表是OpenHarmony源码的目录及简单说明: diff --git a/zh-cn/device-dev/guide/Readme-CN.md b/zh-cn/device-dev/guide/Readme-CN.md index ce9d01e0c1e707e51ead27f2c25026118818f59e..29da041335cb35e904727db70752dcf564d4ad1e 100755 --- a/zh-cn/device-dev/guide/Readme-CN.md +++ b/zh-cn/device-dev/guide/Readme-CN.md @@ -2,7 +2,8 @@ - [轻量和小型系统设备](device-lite.md) - [WLAN连接类产品](device-wlan.md) - - [LED外设控制](oem_wifi_sdk_des.md) + - [LED外设控制](device-wlan-led.md) + - [LED外设控制](oem_wifi_sdk_des.md) - [集成三方SDK](device-wlan-sdk.md) - [无屏摄像头类产品](device-iotcamera.md) - [摄像头控制](device-iotcamera-control.md) diff --git a/zh-cn/device-dev/guide/device-camera-control-demo-photoguide.md b/zh-cn/device-dev/guide/device-camera-control-demo-photoguide.md index 0cae9c359bf6c5b036a4f947635d7c2ca289b65a..a55b60504e286f231b135395125d3cc098a5fbe4 100644 --- a/zh-cn/device-dev/guide/device-camera-control-demo-photoguide.md +++ b/zh-cn/device-dev/guide/device-camera-control-demo-photoguide.md @@ -310,7 +310,7 @@ }; ``` -3. 实现相机状态回调的派生类,当相机状态发生变化(配置成功/失败,创建成功/失败\)时,自定义操作。 +3. 实现相机状态回调的派生类,自定义相机状态发生变化(配置成功/失败,创建成功/失败\)时的操作。 ``` class SampleCameraStateMng : public CameraStateCallback { @@ -363,7 +363,7 @@ camKit->CreateCamera(camId, CamStateMng, eventHdlr); ``` -6. 根据[步骤1](#zh-cn_topic_0000001052170554_li378084192111)、[步骤2](#zh-cn_topic_0000001052170554_li8716104682913)、[步骤3](#zh-cn_topic_0000001052170554_li6671035102514)中的回调设计,camera实例创建成功后会进行配置操作,主流程中app需要设计同步机制。 +6. 根据[步骤1](#zh-cn_topic_0000001052170554_li378084192111)、[步骤2](#zh-cn_topic_0000001052170554_li8716104682913)、[步骤3](#zh-cn_topic_0000001052170554_li6671035102514)中的回调设计,同步等待 OnCreated 回调拿到 cam\_ 之后,进行相关操作。 ``` void OnCreated(Camera &c) override diff --git a/zh-cn/device-dev/guide/device-camera-control-example.md b/zh-cn/device-dev/guide/device-camera-control-example.md index b6d605b04e649928de22fc84d90d947128c5dd2e..0c5aafaf121c932471eb5025961474b1aea60587 100644 --- a/zh-cn/device-dev/guide/device-camera-control-example.md +++ b/zh-cn/device-dev/guide/device-camera-control-example.md @@ -1,6 +1,6 @@ # 应用实例 -本示例将运行源码中的camera示例代码,通过本示例可以实现对开发板拍照、录像及预览功能的控制。 +本示例将运行源码中的camera示例代码,通过本示例可以实现使用开发板进行拍照、录像及预览等功能。 - 本示例源码路径为“applications/sample/camera/media/camera\_sample.cpp”。 - 在运行本示例前需先完成编译烧录、运行镜像等步骤,相关操作请参考[Hi3516快速入门](../quick-start/oem_minitinier_des_3516.md#section26131214194212)。 @@ -26,38 +26,38 @@ 1. 通过cd命令进入可执行程序的末端路径,启动camera\_sample,执行命令如下图。 **图 1** 启动示例 - ![](figure/启动示例.png "启动示例") + ![](figures/启动示例.png "启动示例") 运行后的控制命令如串口打印所示,按s键停止当前操作(包括录像和预览),按q键退出示例程序。 2. 按1进行拍照,拍照的文件格式为jpg,存储在/sdcard,文件名Capture\* **图 2** 输入拍照指令后串口打印日志 - ![](figure/输入拍照指令后串口打印日志.png "输入拍照指令后串口打印日志") + ![](figures/输入拍照指令后串口打印日志.png "输入拍照指令后串口打印日志") 若想查看保存文件,可在退出程序后进入文件系统查看,退出后重新进入请回到步骤1。 **图 3** 查看文件图 - ![](figure/查看文件图.png "查看文件图") + ![](figures/查看文件图.png "查看文件图") 3. 按2进行录像,录像的文件格式为mp4,存储在/sdcard,文件名Record\*,按s键停止 **图 4** 输入录像指令后串口打印日志 - ![](figure/输入录像指令后串口打印日志.png "输入录像指令后串口打印日志") + ![](figures/输入录像指令后串口打印日志.png "输入录像指令后串口打印日志") 4. 按3进行预览,预览图像直接送至显示屏,按s键停止。 **图 5** 输入预览指令后串口打印日志 - ![](figure/输入预览指令后串口打印日志.png "输入预览指令后串口打印日志") + ![](figures/输入预览指令后串口打印日志.png "输入预览指令后串口打印日志") 预览效果如下 **图 6** 预览效果 - ![](figure/预览效果.jpg "预览效果") + ![](figures/预览效果.jpg "预览效果") 5. 按q键退出 **图 7** 输出退出指令后串口打印日志 - ![](figure/输出退出指令后串口打印日志.png "输出退出指令后串口打印日志") + ![](figures/输出退出指令后串口打印日志.png "输出退出指令后串口打印日志") diff --git a/zh-cn/device-dev/guide/device-camera-visual-addpage.md b/zh-cn/device-dev/guide/device-camera-visual-addpage.md index 3929ffbf6aee8d1ecf8ff07da1e3ceeadfa7b2db..8733bfb1e6d4795483ae7e763c0e6fed857fdc64 100644 --- a/zh-cn/device-dev/guide/device-camera-visual-addpage.md +++ b/zh-cn/device-dev/guide/device-camera-visual-addpage.md @@ -8,7 +8,7 @@ 空气质量监测App包含两个界面(Page),工程创建完成后会生成一个名为index的Page,可以作为首页。工程目录如下图所示: **图 1** 工程目录 -![](figure/工程目录.png "工程目录") +![](figures/工程目录.png "工程目录") ## 创建详情页 @@ -17,18 +17,18 @@ 1. pages目录右键 ,弹出的菜单中选择New、JS Page。 **图 2** 添加页面 - ![](figure/添加页面.png "添加页面") + ![](figures/添加页面.png "添加页面") 2. 输入Page名称。 **图 3** 输入页面名称 - ![](figure/输入页面名称.png "输入页面名称") + ![](figures/输入页面名称.png "输入页面名称") 3. 确认创建结果。 详情页创建完成后应用工程目录如下图所示,每个Page包括三个文件:布局文件hml、样式文件css、业务逻辑代码js。 **图 4** 完整工程目录 - ![](figure/完整工程目录.png "完整工程目录") + ![](figures/完整工程目录.png "完整工程目录") diff --git a/zh-cn/device-dev/guide/device-camera-visual-faqs.md b/zh-cn/device-dev/guide/device-camera-visual-faqs.md index e595cc85c3a246c0cbea8bbb2a58b8c00da0ad69..a9caab498818cf56c85a73b6ca958d210d0505b1 100755 --- a/zh-cn/device-dev/guide/device-camera-visual-faqs.md +++ b/zh-cn/device-dev/guide/device-camera-visual-faqs.md @@ -1,128 +1,148 @@ # 常见问题 -1. 是否存在一个全局变量,所有的页面都可以访问? - - 当前框架中不存在所有Page都可以访问的全局变量。 - -2. 如何获取dom中的元素? - - 通过ref属性获取dom中的元素,详细示例如下图所示;获取的元素只能使用它的方法,不能改变属性。 - - ``` - -
- - -
- - /* index.js */ - export default { - data: { - images:[ - {src:"common/frame1.png"}, - {src:"common/frame2.png"}, - {src:"common/frame3.png"} - ] - }, - handleClick(){ - //通过$refs属性获取对应的组件,在hml中,组件的ref属性要设置为animator - const animator = this.$refs.animator; - const state = animator.getState(); - if(state == "paused"){ - animator.resume(); - }else if(state == "stopped"){ - animator.start(); - }else{ - animator.pause(); - } +- [视觉应用常见问题](#section147421736145813) + - [是否存在一个全局变量,所有的页面都可以访问?](#section294382614018) + - [如何获取dom中的元素](#section1423713435019) + - [如何在页面间传值?](#section119822143117) + - [list如何滚动到某个item?](#section188663819111) + - [text支持多行吗?](#section205741157418) + - [为什么控件不显示?](#section1345810151025) + - [如何实现页面滑动?](#section1724052813218) + - [Left、Top为什么不生效?](#section34659571520) + - [动态绑定为什么不生效?](#section1758881511313) + - [如何实现相对定位和绝对定位?](#section1378730235) + - [如何控制控件的显示与隐藏?](#section1243424718312) + - [使用Margin时,有什么注意事项?](#section7923357414) + - [使用事件订阅时,有什么注意事项?](#section91641925548) + - [使用动态绑定时,有什么注意事项?](#section1292412431744) + - [swiper loop属性如何生效?](#section1136434952) + - [使用数组时,有什么注意事项?](#section1979819133510) + + +## 视觉应用常见问题 + +### 是否存在一个全局变量,所有的页面都可以访问? + +当前框架中不存在所有Page都可以访问的全局变量。 + +### 如何获取dom中的元素 + +通过ref属性获取dom中的元素,详细示例如下图所示;获取的元素只能使用它的方法,不能改变属性。 + +``` + +
+ + +
+ +/* index.js */ +export default { + data: { + images:[ + {src:"common/frame1.png"}, + {src:"common/frame2.png"}, + {src:"common/frame3.png"} + ] + }, + handleClick(){ + //通过$refs属性获取对应的组件,在hml中,组件的ref属性要设置为animator + const animator = this.$refs.animator; + const state = animator.getState(); + if(state == "paused"){ + animator.resume(); + }else if(state == "stopped"){ + animator.start(); + }else{ + animator.pause(); } } - ``` +} +``` -3. 如何在页面间传值? +### 如何在页面间传值? - 通过router.replace方法中的params参数来传递,参考代码如下: +通过router.replace方法中的params参数来传递,参考代码如下: - 第一个页面传递数据: +第一个页面传递数据: - ``` - router.replace({ - uri:'pages/detail/detail', //要跳转的页面uri - params:{transferData:this.data} //传递的数据,数据个数和名称开发者自己定义, - }); - ``` +``` +router.replace({ + uri:'pages/detail/detail', //要跳转的页面uri + params:{transferData:this.data} //传递的数据,数据个数和名称开发者自己定义, +}); +``` - 第二个界面接受数据: +第二个界面接受数据: - ``` - onInit(){ - const data = this.transferData; //在onInit函数中接受传递的数据 - } - ``` +``` +onInit(){ + const data = this.transferData; //在onInit函数中接受传递的数据 +} +``` -4. list如何滚动到某个item? +### list如何滚动到某个item? - 通过list的scrollTo方法滚动到指定的item,参数是目标item的index。Index参数可以通过scrollend事件获取或者开发者指定。 +通过list的scrollTo方法滚动到指定的item,参数是目标item的index。Index参数可以通过scrollend事件获取或者开发者指定。 -5. text支持多行吗? +### text支持多行吗? - text支持多行。通过回车键换行或者是不设置text的高度属性,由控件自动根据内容换行。 +text支持多行。通过回车键换行或者是不设置text的高度属性,由控件自动根据内容换行。 -6. 为什么控件不显示? +### 为什么控件不显示? - **现象描述** +**现象描述** - 开发者在hml文件中添加的控件无法显示 +开发者在hml文件中添加的控件无法显示 - **可能原因** +**可能原因** - - 未设置width和height值; - - 样式设置错误。 +- 未设置width和height值; +- 样式设置错误。 - **处理步骤** +**处理步骤** - \(1\)检查是否设置width和height值,组件必须显式设置width和height值; +\(1\)检查是否设置width和height值,组件必须显式设置width和height值; - \(2\)检查组件的样式设置是否正确。 +\(2\)检查组件的样式设置是否正确。 -7. 如何实现页面滑动? +### 如何实现页面滑动? - 实现页面滑动目前有三种方式:scroll(根组件大小超过屏幕的大小即自动实现scroll效果)、list、swiper。开发者可以参考开发文档查看三者的区别,并加以使用。 +实现页面滑动目前有三种方式:scroll(根组件大小超过屏幕的大小即自动实现scroll效果)、list、swiper。开发者可以参考开发文档查看三者的区别,并加以使用。 -8. Left、Top为什么不生效? +### Left、Top为什么不生效? - 除根节点外,Left、Top配合Stack组件使用才有效果。 +除根节点外,Left、Top配合Stack组件使用才有效果。 -9. 动态绑定为什么不生效? +### 动态绑定为什么不生效? - 在进行绑定时,必须先将要绑定的对象或者对象的属性进行定义,不能先绑定后定义。 +在进行绑定时,必须先将要绑定的对象或者对象的属性进行定义,不能先绑定后定义 -10. 如何实现相对定位和绝对定位? +### 如何实现相对定位和绝对定位? - 使用div、stack(top left属性)来实现相对和绝对定位。 +使用div、stack(top left属性)来实现相对和绝对定位。 -11. 如何控制控件的显示与隐藏? +### 如何控制控件的显示与隐藏? - 通过display、show和if来控制控件的显示与隐藏。区别在于:if为false时,组件会从VDOM中移除,而show仅是渲染时不可见,组件依然存在于VDOM中。 +通过display、show和if来控制控件的显示与隐藏。区别在于:if为false时,组件会从VDOM中移除,而show仅是渲染时不可见,组件依然存在于VDOM中。 -12. 使用Margin时,有什么注意事项? +### 使用Margin时,有什么注意事项? - Stack组件不支持其子组件设置margin属性。 +Stack组件不支持其子组件设置margin属性。 -13. 使用事件订阅时,有什么注意事项? +### 使用事件订阅时,有什么注意事项? - 在应用运行期间只存在一个page,所以router.replace跳转是先销毁前一个页面,然后在新创建一个界面。因此,如果涉及到事件订阅的页面,每次页面创建时要进行事件订阅,跳转离开界面前取消事件订阅。 +在应用运行期间只存在一个page,所以router.replace跳转是先销毁前一个页面,然后在新创建一个界面。因此,如果涉及到事件订阅的页面,每次页面创建时要进行事件订阅,跳转离开界面前取消事件订阅。 -14. 使用动态绑定时,有什么注意事项? +### 使用动态绑定时,有什么注意事项? - 过多的动态绑定会消耗较多的内存,若非业务需要,尽量不要使用太多的动态绑定。 +过多的动态绑定会消耗较多的内存,若非业务需要,尽量不要使用太多的动态绑定。 -15. swiper loop属性如何生效? +### swiper loop属性如何生效? - 去掉第一个组件或者去掉最后一个组件,剩余的长度大于swiper长度,loop生效。 +去掉第一个组件或者去掉最后一个组件,剩余的长度大于swiper长度,loop生效。 -16. 使用数组时,有什么注意事项? - - 数组元素不宜过多,尽量避免对大数组进行频繁操作。 +### 使用数组时,有什么注意事项? +数组元素不宜过多,尽量避免对大数组进行频繁操作。 diff --git a/zh-cn/device-dev/guide/device-camera-visual-firstpage.md b/zh-cn/device-dev/guide/device-camera-visual-firstpage.md index bbfa60c30d6d6a901aa1e190145711955b69af50..0e2d0cd3cff4ded0aef4f91258cb363c01a69bb9 100644 --- a/zh-cn/device-dev/guide/device-camera-visual-firstpage.md +++ b/zh-cn/device-dev/guide/device-camera-visual-firstpage.md @@ -2,7 +2,7 @@ 应用首页主要展示城市的空气质量概况。首页总共有两屏(可以根据需求设置多屏),每屏显示一个城市的空气质量信息:主要包括AQI指数、城市名称、污染物指数、更新时间和信息来源等数据。 -从第一章节中的[显示效果图](device-camera-visual-overview.md#fig18250512195914)分析可知,首页由三部分组成: +从第一章节中的[显示效果图](device-camera-visual-overview.md)分析可知,首页由三部分组成: - 标题栏:位于页面正上方,位置固定,包括应用退出按钮和页面标题。 - 信息栏:主要展示城市的空气信息指标等内容;该页面根据用户需求可设置多屏,且能循环滑动。 @@ -83,7 +83,7 @@ 代码编写完成后,在模拟器中运行项目,显示效果如下图所示: **图 1** 标题栏效果 - ![](figure/标题栏效果.png "标题栏效果") + ![](figures/标题栏效果.png "标题栏效果") 3. 实现城市空气质量信息的多屏左右滑动,需要使用“swiper”组件。 @@ -175,7 +175,7 @@ 代码编写完成后,模拟器运行效果如下: **图 2** 标题栏和信息栏效果 - ![](figure/标题栏和信息栏效果.png "标题栏和信息栏效果") + ![](figures/标题栏和信息栏效果.png "标题栏和信息栏效果") 5. 添加页面位置指示器:由于当前swiper不支持设置indicator,需要开发者自己来实现该效果。在根节点中添加一个子组件div,并设置相应样式;然后在该div中添加两个子组件div,设置两个div的border-radius,并在swiper滑动事件中动态改变对应div的背景色来实现该效果。 @@ -187,7 +187,7 @@ ``` **图 3** 页面位置指示器效果图 - ![](figure/页面位置指示器效果图.png "页面位置指示器效果图") + ![](figures/页面位置指示器效果图.png "页面位置指示器效果图") 6. 所有组件设置样式、动画效果和数据动态绑定,完整代码如下所示: diff --git a/zh-cn/device-dev/guide/device-camera-visual-overview.md b/zh-cn/device-dev/guide/device-camera-visual-overview.md index a7e9895e2dceb1911879973ef697791cc59e649d..3f9b8cde1f8bf951302522a824c50862168a7026 100644 --- a/zh-cn/device-dev/guide/device-camera-visual-overview.md +++ b/zh-cn/device-dev/guide/device-camera-visual-overview.md @@ -8,8 +8,6 @@ 空气质量监测App是一款展示城市空气质量信息的应用,有两个页面组成:首页和详情页,在DevEco Studio模拟器中的显示效果如下图所示: -**图 1** 空气质量监测 App显示效果图 - - -![](figure/Video_2020-07-25_173141.gif) +**图 1** 空气质量监测 App显示效果图 +![](figures/空气质量监测-App显示效果图.gif "空气质量监测-App显示效果图") diff --git a/zh-cn/device-dev/guide/device-camera-visual-prepare.md b/zh-cn/device-dev/guide/device-camera-visual-prepare.md index 55ed7451c0ecdf7d2ab9fd9f896374287a1c5efb..d9dce9afe76703bc0554c5f75ae705f26e35e943 100644 --- a/zh-cn/device-dev/guide/device-camera-visual-prepare.md +++ b/zh-cn/device-dev/guide/device-camera-visual-prepare.md @@ -15,7 +15,7 @@ 2. 选择“Smart Vision”下的“Empty Feature Ability”模板。 - ![](figure/zh-cn_image_0000001082434703.png) + ![](figures/empty-feature-ability.png) 3. 点击**Next**,进入到工程配置阶段,需要根据向导配置工程的基本信息。 - **Project Name**:工程的名称,可以自定义。 diff --git a/zh-cn/device-dev/guide/device-camera-visual-run.md b/zh-cn/device-dev/guide/device-camera-visual-run.md index 59cea7e09931c4aff998255917c9ec2804d5eb3a..dfbdc4472ce32fff064a3dd720db102152ce1477 100644 --- a/zh-cn/device-dev/guide/device-camera-visual-run.md +++ b/zh-cn/device-dev/guide/device-camera-visual-run.md @@ -20,7 +20,7 @@ 4. 应用安装完成后,可点击桌面应用图标启动应用,进行操作。 **图 1** 桌面 - ![](figure/桌面.png "桌面") + ![](figures/桌面.png "桌面") 5. 卸载应用(可选)。 diff --git a/zh-cn/device-dev/guide/device-clock-guide.md b/zh-cn/device-dev/guide/device-clock-guide.md index 8df6da73488802189b88e132e1d28c3845996403..a29494b1407d890eb135708eef3cba271565608e 100644 --- a/zh-cn/device-dev/guide/device-clock-guide.md +++ b/zh-cn/device-dev/guide/device-clock-guide.md @@ -16,10 +16,8 @@ 时钟App是一款显示实时时间的应用,显示效果如下图所示: -**图 1** 时钟应用显示效果图 - - -![](figure/Clock.png) +**图 1** 时钟应用显示效果图 +![](figures/时钟应用显示效果图.png "时钟应用显示效果图") ## 开发准备 @@ -29,7 +27,7 @@ 应用的功能是通过表盘和数字显示实时时间。 -从[显示效果图](device-clock-guide.md#fig7763172132019)分析可知,页面由两个部分组成: +从[显示效果图](#fig176772511186)分析可知,页面由两个部分组成: - 表盘栏:主要展示一个动态的钟表,且钟表指针能准确转动。 - 数字时间栏:主要以数字形式显示当前时间。 diff --git a/zh-cn/device-dev/guide/device-driver-demo.md b/zh-cn/device-dev/guide/device-driver-demo.md index 1220e92265d08302120f54b3173db207529d966f..6345e8ccf46f3c2ce265f60647ba45dc5499e1f5 100644 --- a/zh-cn/device-dev/guide/device-driver-demo.md +++ b/zh-cn/device-dev/guide/device-driver-demo.md @@ -19,18 +19,10 @@ HDF驱动框架为常用外围设备提供了标准的驱动框架,驱动开发者只需将驱动适配至HDF驱动框架,即可通过HDF驱动框架提供的接口操作外围设备。 -本文以I2C为例。其时序流程如[图1](#fig148041484161)所示。 +本文以I2C为例。其时序流程如[图1](#fig9596628607)所示。 -**图 1** I2C时序流程图 - - -![](figure/zh-cn_image_0000001169991055.png) - -- User Business:用户业务驱动。 -- i2cManagerEntry:I2C管理器入口,注册I2cManager到HDF驱动框架。 -- I2cManager:I2C管理器,管理I2C控制器。 -- I2cCntlr:I2C控制器。 -- i2cDriverEntry:I2C控制器入口,注册I2cCntlr到HDF驱动框架。 +**图 1** I2C时序流程图 +![](figures/I2C时序流程图.png "I2C时序流程图") ## 环境准备 diff --git a/zh-cn/device-dev/guide/device-iotcamera-control-demo-photodevguide.md b/zh-cn/device-dev/guide/device-iotcamera-control-demo-photodevguide.md index 31edc27814baddb754614c87ca0225979ef408ff..f317784dbd25862f4752c69d6526335f03069fc9 100644 --- a/zh-cn/device-dev/guide/device-iotcamera-control-demo-photodevguide.md +++ b/zh-cn/device-dev/guide/device-iotcamera-control-demo-photodevguide.md @@ -310,7 +310,7 @@ }; ``` -3. 实现相机状态回调的派生类,当相机状态发生变化(配置成功/失败,创建成功/失败\)时,自定义操作。 +3. 实现相机状态回调的派生类,自定义相机状态发生变化(配置成功/失败,创建成功/失败\)时的操作。 ``` class SampleCameraStateMng : public CameraStateCallback { @@ -363,7 +363,7 @@ camKit->CreateCamera(camId, CamStateMng, eventHdlr); ``` -6. 根据[步骤1](#zh-cn_topic_0000001052170554_li378084192111)、[步骤2](#zh-cn_topic_0000001052170554_li8716104682913)、[步骤3](#zh-cn_topic_0000001052170554_li6671035102514)中的回调设计,camera实例创建成功后会进行配置操作,主流程中app需要设计同步机制。 +6. 根据[步骤1](#zh-cn_topic_0000001052170554_li378084192111)、[步骤2](#zh-cn_topic_0000001052170554_li8716104682913)、[步骤3](#zh-cn_topic_0000001052170554_li6671035102514)中的回调设计,同步等待 OnCreated 回调拿到 cam\_ 之后,进行相关操作。 ``` void OnCreated(Camera &c) override diff --git a/zh-cn/device-dev/guide/device-iotcamera-control-example.md b/zh-cn/device-dev/guide/device-iotcamera-control-example.md index 56bd5df7ff309943182b86a5da61732f251f9fdd..c5dfe01f028576b13feb79575245731c1876f9d3 100644 --- a/zh-cn/device-dev/guide/device-iotcamera-control-example.md +++ b/zh-cn/device-dev/guide/device-iotcamera-control-example.md @@ -18,28 +18,28 @@ 1. 通过cd命令进入可执行程序的末端路径,启动camera\_sample,执行命令如下图。 **图 1** 启动示例 - ![](figure/启动示例.png "启动示例") + ![](figures/启动示例.png "启动示例") 运行后的控制命令如串口打印所示,按s键停止当前操作(包括录像和预览),按q键退出示例程序。 2. 按1进行拍照,拍照的文件格式为jpg,存储在/sdcard,文件名Capture\* **图 2** 输入拍照指令后串口打印日志 - ![](figure/输入拍照指令后串口打印日志.png "输入拍照指令后串口打印日志") + ![](figures/输入拍照指令后串口打印日志.png "输入拍照指令后串口打印日志") 若想查看保存文件,可在退出程序后进入文件系统查看,退出后重新进入请回到步骤1。 **图 3** 查看文件图 - ![](figure/查看文件图.png "查看文件图") + ![](figures/查看文件图.png "查看文件图") 3. 按2进行录像,录像的文件格式为mp4,存储在/sdcard,文件名Record\*,按s键停止 **图 4** 输入录像指令后串口打印日志 - ![](figure/输入录像指令后串口打印日志.png "输入录像指令后串口打印日志") + ![](figures/输入录像指令后串口打印日志.png "输入录像指令后串口打印日志") 4. 按q键退出 **图 5** 输出退出指令后串口打印日志 - ![](figure/输出退出指令后串口打印日志.png "输出退出指令后串口打印日志") + ![](figures/输出退出指令后串口打印日志.png "输出退出指令后串口打印日志") diff --git a/zh-cn/device-dev/guide/device-outerdriver-demo.md b/zh-cn/device-dev/guide/device-outerdriver-demo.md index 523d084d55a16489d99fe4c2816d9beb13e77433..0e74ff079e4d4eb0131359eb3ac9d1aa477cb7f9 100644 --- a/zh-cn/device-dev/guide/device-outerdriver-demo.md +++ b/zh-cn/device-dev/guide/device-outerdriver-demo.md @@ -28,7 +28,7 @@ Hi3516DV300开发板套件所提供的触摸屏器件IC为GT911,该器件采用标准I2C与主机通信,通过6pin软排线与主板连接。6pin分布以及实物连接图如下图所示: -![](figure/绘图1.png) +![](figures/6-pin-distribution-and-physical-connection.png) ### Input模型简介 diff --git a/zh-cn/device-dev/guide/device-wlan-led.md b/zh-cn/device-dev/guide/device-wlan-led.md new file mode 100644 index 0000000000000000000000000000000000000000..5486cf40030d5bf1de2b54d8e5aafb4e0b8f6cb3 --- /dev/null +++ b/zh-cn/device-dev/guide/device-wlan-led.md @@ -0,0 +1,5 @@ +# LED外设控制 + +- **[LED外设控制](oem_wifi_sdk_des.md)** + + diff --git a/zh-cn/device-dev/guide/device-wlan-sdk.md b/zh-cn/device-dev/guide/device-wlan-sdk.md index 8106f68cd6202a165547b6db59ae734fe01e6e6b..745d8ec4ae5e62110365bbd8647cd9e46b667980 100644 --- a/zh-cn/device-dev/guide/device-wlan-sdk.md +++ b/zh-cn/device-dev/guide/device-wlan-sdk.md @@ -121,7 +121,7 @@ OpenHarmony已规划用于编译业务libs的目录domains/iot/link/libbuild/ 完成以上3点后,需在代码根目录下执行命令“hb build -T //domains/iot/link:iot”,等待执行完成,检查out/hispark\_pegasus/wifiiot\_hispark\_pegasus/libs/目录下是否生成了目标库文件。 -![](figure/zh-cn_image_0000001078563230.png) +![](figures/device-wlan-sdk-files.png) 将库文件拷贝到device/hisilicon/hispark\_pegasus/sdk\_liteos/3rd\_sdk/demolink/libs/ 目录下,并将domains/iot/link/libbuild/ 目录中的.c和.h文件清除。 diff --git a/zh-cn/device-dev/guide/device-wlan-touch.md b/zh-cn/device-dev/guide/device-wlan-touch.md new file mode 100644 index 0000000000000000000000000000000000000000..2736daf4e21899d4fdc083b852d1869a70e57343 --- /dev/null +++ b/zh-cn/device-dev/guide/device-wlan-touch.md @@ -0,0 +1,19 @@ +# 碰一碰 + +- **[碰一碰概述](onehop-overview.md)** + +- **[准备工作](onehop-dev-prerequisites.md)** + +- **[开发Hi3861设备侧功能](onehop-dev-hi3861.md)** + +- **[开发原子化服务](onehop-dev-atomic-service.md)** + +- **[写入NFC标签信息](onehop-write-nfc-info.md)** + +- **[配置服务关联意图](onehop-configuration-device-tag.md)** + +- **[碰一碰拉起原子化服务](onehop-open-atomic-service.md)** + +- **[参考信息](onehop-reference-info.md)** + + diff --git a/zh-cn/device-dev/guide/device-wlan.md b/zh-cn/device-dev/guide/device-wlan.md index ece3a35d670fe43de2892f4eae35b6d8f25a4e29..026cb3d7e593b8578addb252afe33907c223e1a0 100644 --- a/zh-cn/device-dev/guide/device-wlan.md +++ b/zh-cn/device-dev/guide/device-wlan.md @@ -1,6 +1,8 @@ # WLAN连接类产品 -- **[LED外设控制](oem_wifi_sdk_des.md)** +- **[碰一碰](device-wlan-touch.md)** + +- **[LED外设控制](device-wlan-led.md)** - **[集成三方SDK](device-wlan-sdk.md)** diff --git a/zh-cn/device-dev/guide/figures/2021-01-27_170334-4.png b/zh-cn/device-dev/guide/figures/2021-01-27_170334-4.png new file mode 100644 index 0000000000000000000000000000000000000000..5b573a4ddfe89fe25cb1b567736823244fdb9e97 Binary files /dev/null and b/zh-cn/device-dev/guide/figures/2021-01-27_170334-4.png differ diff --git "a/zh-cn/device-dev/guide/figure/\347\273\230\345\233\2761.png" b/zh-cn/device-dev/guide/figures/6-pin-distribution-and-physical-connection.png similarity index 100% rename from "zh-cn/device-dev/guide/figure/\347\273\230\345\233\2761.png" rename to zh-cn/device-dev/guide/figures/6-pin-distribution-and-physical-connection.png diff --git a/zh-cn/device-dev/guide/figure/zh-cn_image_0000001169991055.png "b/zh-cn/device-dev/guide/figures/I2C\346\227\266\345\272\217\346\265\201\347\250\213\345\233\276.png" similarity index 100% rename from zh-cn/device-dev/guide/figure/zh-cn_image_0000001169991055.png rename to "zh-cn/device-dev/guide/figures/I2C\346\227\266\345\272\217\346\265\201\347\250\213\345\233\276.png" diff --git "a/zh-cn/device-dev/guide/figure/LED\351\227\252\347\203\201\345\233\276.gif" "b/zh-cn/device-dev/guide/figures/LED\351\227\252\347\203\201\345\233\276.gif" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/guide/figure/LED\351\227\252\347\203\201\345\233\276.gif" rename to "zh-cn/device-dev/guide/figures/LED\351\227\252\347\203\201\345\233\276.gif" diff --git a/zh-cn/device-dev/guide/figures/ability-gallery-service.png b/zh-cn/device-dev/guide/figures/ability-gallery-service.png new file mode 100644 index 0000000000000000000000000000000000000000..63fb6627393fc1a8a2bca6964fa2900d0dd308bc Binary files /dev/null and b/zh-cn/device-dev/guide/figures/ability-gallery-service.png differ diff --git a/zh-cn/device-dev/guide/figures/ability-test.png b/zh-cn/device-dev/guide/figures/ability-test.png new file mode 100644 index 0000000000000000000000000000000000000000..cafda84ac7195a758ae8526ab747ef8483f56129 Binary files /dev/null and b/zh-cn/device-dev/guide/figures/ability-test.png differ diff --git a/zh-cn/device-dev/guide/figures/add_tools.png b/zh-cn/device-dev/guide/figures/add_tools.png new file mode 100644 index 0000000000000000000000000000000000000000..8737e531e2536d7e7e485af539ace34ea747da8d Binary files /dev/null and b/zh-cn/device-dev/guide/figures/add_tools.png differ diff --git a/zh-cn/device-dev/guide/figures/build-project.png b/zh-cn/device-dev/guide/figures/build-project.png new file mode 100644 index 0000000000000000000000000000000000000000..24c23b9f35a4a1edaf57f6dd983c32138adf8594 Binary files /dev/null and b/zh-cn/device-dev/guide/figures/build-project.png differ diff --git a/zh-cn/device-dev/guide/figures/build-success.png b/zh-cn/device-dev/guide/figures/build-success.png new file mode 100644 index 0000000000000000000000000000000000000000..26d93f832bef054618d31d8e2cecf6684ecdb891 Binary files /dev/null and b/zh-cn/device-dev/guide/figures/build-success.png differ diff --git a/zh-cn/device-dev/guide/figures/burn_settings.png b/zh-cn/device-dev/guide/figures/burn_settings.png new file mode 100644 index 0000000000000000000000000000000000000000..a510dcecc23495dc515a8deecce580a660cf721b Binary files /dev/null and b/zh-cn/device-dev/guide/figures/burn_settings.png differ diff --git a/zh-cn/device-dev/guide/figures/choose-nfc.png b/zh-cn/device-dev/guide/figures/choose-nfc.png new file mode 100644 index 0000000000000000000000000000000000000000..ca1ab3357646a62189296995c1319c6bff1ad28e Binary files /dev/null and b/zh-cn/device-dev/guide/figures/choose-nfc.png differ diff --git a/zh-cn/device-dev/guide/figures/choose-product-id.png b/zh-cn/device-dev/guide/figures/choose-product-id.png new file mode 100644 index 0000000000000000000000000000000000000000..7c91963c5c582b87df8129619dbec2613e97a81e Binary files /dev/null and b/zh-cn/device-dev/guide/figures/choose-product-id.png differ diff --git a/zh-cn/device-dev/guide/figures/choose-requested-product-id.png b/zh-cn/device-dev/guide/figures/choose-requested-product-id.png new file mode 100644 index 0000000000000000000000000000000000000000..ae19e372316109341eeb80ca452c2252c994c59b Binary files /dev/null and b/zh-cn/device-dev/guide/figures/choose-requested-product-id.png differ diff --git a/zh-cn/device-dev/guide/figures/choose-template.png b/zh-cn/device-dev/guide/figures/choose-template.png new file mode 100644 index 0000000000000000000000000000000000000000..2932ec5fd69fc4e786c698afdbf95ab64e23be1d Binary files /dev/null and b/zh-cn/device-dev/guide/figures/choose-template.png differ diff --git a/zh-cn/device-dev/guide/figures/component-reference-code.png b/zh-cn/device-dev/guide/figures/component-reference-code.png new file mode 100644 index 0000000000000000000000000000000000000000..21b9b6e4cb88a620d07cf7c37a3795b9adc87397 Binary files /dev/null and b/zh-cn/device-dev/guide/figures/component-reference-code.png differ diff --git a/zh-cn/device-dev/guide/figures/configure-project.png b/zh-cn/device-dev/guide/figures/configure-project.png new file mode 100644 index 0000000000000000000000000000000000000000..f1f80f3a77db74d3f730e13b165a1113e699c04f Binary files /dev/null and b/zh-cn/device-dev/guide/figures/configure-project.png differ diff --git a/zh-cn/device-dev/guide/figures/console.png b/zh-cn/device-dev/guide/figures/console.png new file mode 100644 index 0000000000000000000000000000000000000000..f7cbec3ffbad85fe4449d0cbc1ce754c84001e74 Binary files /dev/null and b/zh-cn/device-dev/guide/figures/console.png differ diff --git a/zh-cn/device-dev/guide/figures/control-module-icon.png b/zh-cn/device-dev/guide/figures/control-module-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..45f126abf60662d98f881d884d8483557a5ea831 Binary files /dev/null and b/zh-cn/device-dev/guide/figures/control-module-icon.png differ diff --git a/zh-cn/device-dev/guide/figures/control-module.png b/zh-cn/device-dev/guide/figures/control-module.png new file mode 100644 index 0000000000000000000000000000000000000000..a515a1739fe19fbce722621e26b39cc1239a11d4 Binary files /dev/null and b/zh-cn/device-dev/guide/figures/control-module.png differ diff --git a/zh-cn/device-dev/guide/figures/copy-hals-and-winder.png b/zh-cn/device-dev/guide/figures/copy-hals-and-winder.png new file mode 100644 index 0000000000000000000000000000000000000000..966e00018189222882bb6b1ef13c8599e75eadbf Binary files /dev/null and b/zh-cn/device-dev/guide/figures/copy-hals-and-winder.png differ diff --git a/zh-cn/device-dev/guide/figures/date-and-time-picker.png b/zh-cn/device-dev/guide/figures/date-and-time-picker.png new file mode 100644 index 0000000000000000000000000000000000000000..2259c361916fc0590c53faf47e006c7639d73725 Binary files /dev/null and b/zh-cn/device-dev/guide/figures/date-and-time-picker.png differ diff --git a/zh-cn/device-dev/guide/figures/date-picker.png b/zh-cn/device-dev/guide/figures/date-picker.png new file mode 100644 index 0000000000000000000000000000000000000000..204e40fa8aa4c8f3ab9196b2f0e2f2e178cdeaed Binary files /dev/null and b/zh-cn/device-dev/guide/figures/date-picker.png differ diff --git a/zh-cn/device-dev/guide/figure/zh-cn_image_0000001078563230.png b/zh-cn/device-dev/guide/figures/device-wlan-sdk-files.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/guide/figure/zh-cn_image_0000001078563230.png rename to zh-cn/device-dev/guide/figures/device-wlan-sdk-files.png diff --git a/zh-cn/device-dev/guide/figures/display-component.png b/zh-cn/device-dev/guide/figures/display-component.png new file mode 100644 index 0000000000000000000000000000000000000000..b4b7a38ccb93bf2583539382beb7e8e68dd97b7d Binary files /dev/null and b/zh-cn/device-dev/guide/figures/display-component.png differ diff --git a/zh-cn/device-dev/guide/figures/edit-configurations.png b/zh-cn/device-dev/guide/figures/edit-configurations.png new file mode 100644 index 0000000000000000000000000000000000000000..a9657f5b25dd269d6189ad9308b05da2c8c55e40 Binary files /dev/null and b/zh-cn/device-dev/guide/figures/edit-configurations.png differ diff --git a/zh-cn/device-dev/guide/figure/zh-cn_image_0000001082434703.png b/zh-cn/device-dev/guide/figures/empty-feature-ability.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/guide/figure/zh-cn_image_0000001082434703.png rename to zh-cn/device-dev/guide/figures/empty-feature-ability.png diff --git a/zh-cn/device-dev/guide/figures/enum-component.png b/zh-cn/device-dev/guide/figures/enum-component.png new file mode 100644 index 0000000000000000000000000000000000000000..05c06aa0a7939700fc0128d6a20eacc6cce0dd4d Binary files /dev/null and b/zh-cn/device-dev/guide/figures/enum-component.png differ diff --git a/zh-cn/device-dev/guide/figures/enum-dialog.png b/zh-cn/device-dev/guide/figures/enum-dialog.png new file mode 100644 index 0000000000000000000000000000000000000000..e0f09313354c53ebd068201f702318746022c489 Binary files /dev/null and b/zh-cn/device-dev/guide/figures/enum-dialog.png differ diff --git a/zh-cn/device-dev/guide/figures/fa-information.png b/zh-cn/device-dev/guide/figures/fa-information.png new file mode 100644 index 0000000000000000000000000000000000000000..d5cedb3ccefbbe62f97896918d464a0c2bd33d0e Binary files /dev/null and b/zh-cn/device-dev/guide/figures/fa-information.png differ diff --git a/zh-cn/device-dev/guide/figures/harmonyos-tag.png b/zh-cn/device-dev/guide/figures/harmonyos-tag.png new file mode 100644 index 0000000000000000000000000000000000000000..459a69f9ef8a469b0b44ca6f68be6cf4aef27275 Binary files /dev/null and b/zh-cn/device-dev/guide/figures/harmonyos-tag.png differ diff --git a/zh-cn/device-dev/guide/figures/harmonyos-test-ability-model.png b/zh-cn/device-dev/guide/figures/harmonyos-test-ability-model.png new file mode 100644 index 0000000000000000000000000000000000000000..725d1c24c440f3f1c8a63750015184089c15e043 Binary files /dev/null and b/zh-cn/device-dev/guide/figures/harmonyos-test-ability-model.png differ diff --git a/zh-cn/device-dev/guide/figures/harmonyos-test-ability.png b/zh-cn/device-dev/guide/figures/harmonyos-test-ability.png new file mode 100644 index 0000000000000000000000000000000000000000..5fc3dd6e556fd7bfcfd02f7438c92907e4e670e5 Binary files /dev/null and b/zh-cn/device-dev/guide/figures/harmonyos-test-ability.png differ diff --git a/zh-cn/device-dev/guide/figures/hi3861-burning-succeeded-7.png b/zh-cn/device-dev/guide/figures/hi3861-burning-succeeded-7.png new file mode 100644 index 0000000000000000000000000000000000000000..3628f3f4778012a577d4ee28c703669eb5533594 Binary files /dev/null and b/zh-cn/device-dev/guide/figures/hi3861-burning-succeeded-7.png differ diff --git a/zh-cn/device-dev/guide/figures/hi3861-record-the-serial-port-number-5.png b/zh-cn/device-dev/guide/figures/hi3861-record-the-serial-port-number-5.png new file mode 100644 index 0000000000000000000000000000000000000000..43496f076a463ec6fbf320b358a32505284ff40f Binary files /dev/null and b/zh-cn/device-dev/guide/figures/hi3861-record-the-serial-port-number-5.png differ diff --git a/zh-cn/device-dev/guide/figures/hi3861-restart-the-development-board.png b/zh-cn/device-dev/guide/figures/hi3861-restart-the-development-board.png new file mode 100644 index 0000000000000000000000000000000000000000..e6b632288105421a07bd4f8d542293deb0d35fd2 Binary files /dev/null and b/zh-cn/device-dev/guide/figures/hi3861-restart-the-development-board.png differ diff --git a/zh-cn/device-dev/guide/figures/hi3861-upload-6.png b/zh-cn/device-dev/guide/figures/hi3861-upload-6.png new file mode 100644 index 0000000000000000000000000000000000000000..8dde7632636856203030c2abf0867f03abaafcba Binary files /dev/null and b/zh-cn/device-dev/guide/figures/hi3861-upload-6.png differ diff --git a/zh-cn/device-dev/guide/figures/import-project-confirm.png b/zh-cn/device-dev/guide/figures/import-project-confirm.png new file mode 100644 index 0000000000000000000000000000000000000000..27fe1d133a31b275a2788cab1f5b37dd3450a7df Binary files /dev/null and b/zh-cn/device-dev/guide/figures/import-project-confirm.png differ diff --git a/zh-cn/device-dev/guide/figures/import-project-setting.png b/zh-cn/device-dev/guide/figures/import-project-setting.png new file mode 100644 index 0000000000000000000000000000000000000000..b522b9b1e490b5ba65a0afd021cd5f472110136c Binary files /dev/null and b/zh-cn/device-dev/guide/figures/import-project-setting.png differ diff --git a/zh-cn/device-dev/guide/figures/import-project.png b/zh-cn/device-dev/guide/figures/import-project.png new file mode 100644 index 0000000000000000000000000000000000000000..5ba534eaf39165891a31c7837ae7ff4126f6414c Binary files /dev/null and b/zh-cn/device-dev/guide/figures/import-project.png differ diff --git a/zh-cn/device-dev/guide/figures/increase-decrease-component.png b/zh-cn/device-dev/guide/figures/increase-decrease-component.png new file mode 100644 index 0000000000000000000000000000000000000000..c3071b280090668be88dec25ab2b2dc1dbf8f0d7 Binary files /dev/null and b/zh-cn/device-dev/guide/figures/increase-decrease-component.png differ diff --git a/zh-cn/device-dev/guide/figures/info-dialog.png b/zh-cn/device-dev/guide/figures/info-dialog.png new file mode 100644 index 0000000000000000000000000000000000000000..4278ae472f7a8cff0b96b79ac5d45f2f0719e8e2 Binary files /dev/null and b/zh-cn/device-dev/guide/figures/info-dialog.png differ diff --git a/zh-cn/device-dev/guide/figures/launch-atomic-service-procedure.png b/zh-cn/device-dev/guide/figures/launch-atomic-service-procedure.png new file mode 100644 index 0000000000000000000000000000000000000000..76ce1f3a2ec4dde0bdffc9d172a281810a7c1f69 Binary files /dev/null and b/zh-cn/device-dev/guide/figures/launch-atomic-service-procedure.png differ diff --git a/zh-cn/device-dev/guide/figures/multi-column-picker.png b/zh-cn/device-dev/guide/figures/multi-column-picker.png new file mode 100644 index 0000000000000000000000000000000000000000..de0593b498af83a865fa9097d86dd07967ddcdaa Binary files /dev/null and b/zh-cn/device-dev/guide/figures/multi-column-picker.png differ diff --git a/zh-cn/device-dev/guide/figures/multifunction-component.png b/zh-cn/device-dev/guide/figures/multifunction-component.png new file mode 100644 index 0000000000000000000000000000000000000000..ac18eff592c4b0b64f8527a98cf3257be9b9cb87 Binary files /dev/null and b/zh-cn/device-dev/guide/figures/multifunction-component.png differ diff --git a/zh-cn/device-dev/guide/figures/onehop-develop-procedure.png b/zh-cn/device-dev/guide/figures/onehop-develop-procedure.png new file mode 100644 index 0000000000000000000000000000000000000000..e27414c7a920a45629071565c24464fa58055b30 Binary files /dev/null and b/zh-cn/device-dev/guide/figures/onehop-develop-procedure.png differ diff --git a/zh-cn/device-dev/guide/figures/onehop-procedure.png b/zh-cn/device-dev/guide/figures/onehop-procedure.png new file mode 100644 index 0000000000000000000000000000000000000000..11f12f6d18e849d13b0a63be07f1d58296035257 Binary files /dev/null and b/zh-cn/device-dev/guide/figures/onehop-procedure.png differ diff --git a/zh-cn/device-dev/guide/figures/place-product-diagram.png b/zh-cn/device-dev/guide/figures/place-product-diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..b7fe68aadf4a045bd8657054a07d3d4328b004ca Binary files /dev/null and b/zh-cn/device-dev/guide/figures/place-product-diagram.png differ diff --git a/zh-cn/device-dev/guide/figures/process-component.png b/zh-cn/device-dev/guide/figures/process-component.png new file mode 100644 index 0000000000000000000000000000000000000000..f6b0fbe0aa28be6d9c39fe45cafb63d87d809659 Binary files /dev/null and b/zh-cn/device-dev/guide/figures/process-component.png differ diff --git a/zh-cn/device-dev/guide/figures/project-structure.png b/zh-cn/device-dev/guide/figures/project-structure.png new file mode 100644 index 0000000000000000000000000000000000000000..67c7a082f6fd2dc4e160567a2bc6735bba4fe2b8 Binary files /dev/null and b/zh-cn/device-dev/guide/figures/project-structure.png differ diff --git a/zh-cn/device-dev/guide/figures/project_settings.png b/zh-cn/device-dev/guide/figures/project_settings.png new file mode 100644 index 0000000000000000000000000000000000000000..f869bc8e66050bd10c558724fa210fb1a84163f4 Binary files /dev/null and b/zh-cn/device-dev/guide/figures/project_settings.png differ diff --git a/zh-cn/device-dev/guide/figures/prototype-test.png b/zh-cn/device-dev/guide/figures/prototype-test.png new file mode 100644 index 0000000000000000000000000000000000000000..d4568aa761be14e665667fcfa5c95bad8613f2a1 Binary files /dev/null and b/zh-cn/device-dev/guide/figures/prototype-test.png differ diff --git a/zh-cn/device-dev/guide/figures/radio-dialog.png b/zh-cn/device-dev/guide/figures/radio-dialog.png new file mode 100644 index 0000000000000000000000000000000000000000..097edb23307ec360d2757e2ea99368b71ba124af Binary files /dev/null and b/zh-cn/device-dev/guide/figures/radio-dialog.png differ diff --git a/zh-cn/device-dev/guide/figures/request-product-id.png b/zh-cn/device-dev/guide/figures/request-product-id.png new file mode 100644 index 0000000000000000000000000000000000000000..97a69009db01ebb605958a67b75ada00abb635ba Binary files /dev/null and b/zh-cn/device-dev/guide/figures/request-product-id.png differ diff --git a/zh-cn/device-dev/guide/figures/reversal-component.png b/zh-cn/device-dev/guide/figures/reversal-component.png new file mode 100644 index 0000000000000000000000000000000000000000..182da8bd6953af4884ceb7aaffee88d8e5022ecd Binary files /dev/null and b/zh-cn/device-dev/guide/figures/reversal-component.png differ diff --git a/zh-cn/device-dev/guide/figures/run-entry.png b/zh-cn/device-dev/guide/figures/run-entry.png new file mode 100644 index 0000000000000000000000000000000000000000..7cd572c6ebbb57e8d33b38df67c0fd0bb26fc4cc Binary files /dev/null and b/zh-cn/device-dev/guide/figures/run-entry.png differ diff --git a/zh-cn/device-dev/guide/figures/set-config-i2c-support.png b/zh-cn/device-dev/guide/figures/set-config-i2c-support.png new file mode 100644 index 0000000000000000000000000000000000000000..1921ee61abb7bf05674558121ebb6c812dc627df Binary files /dev/null and b/zh-cn/device-dev/guide/figures/set-config-i2c-support.png differ diff --git a/zh-cn/device-dev/guide/figures/set-sn-number.png b/zh-cn/device-dev/guide/figures/set-sn-number.png new file mode 100644 index 0000000000000000000000000000000000000000..a11388839398cfc8aa2ff14a989ef2e12e36ea07 Binary files /dev/null and b/zh-cn/device-dev/guide/figures/set-sn-number.png differ diff --git a/zh-cn/device-dev/guide/figures/text-picker.png b/zh-cn/device-dev/guide/figures/text-picker.png new file mode 100644 index 0000000000000000000000000000000000000000..60a1be0310ef2f7fc5ccfbbc7a09479650b1b77f Binary files /dev/null and b/zh-cn/device-dev/guide/figures/text-picker.png differ diff --git a/zh-cn/device-dev/guide/figures/time-picker.png b/zh-cn/device-dev/guide/figures/time-picker.png new file mode 100644 index 0000000000000000000000000000000000000000..b68a0fb2725be2da70aa09680028071f8acc7eef Binary files /dev/null and b/zh-cn/device-dev/guide/figures/time-picker.png differ diff --git a/zh-cn/device-dev/guide/figures/write-to-buffer.png b/zh-cn/device-dev/guide/figures/write-to-buffer.png new file mode 100644 index 0000000000000000000000000000000000000000..cc3e9353cd011bdbf23089ed0a857cbafb5aab40 Binary files /dev/null and b/zh-cn/device-dev/guide/figures/write-to-buffer.png differ diff --git a/zh-cn/device-dev/guide/figures/written-to-tag.png b/zh-cn/device-dev/guide/figures/written-to-tag.png new file mode 100644 index 0000000000000000000000000000000000000000..3e3b0d15d509b30cbdc96faaecadc8553cbe1e37 Binary files /dev/null and b/zh-cn/device-dev/guide/figures/written-to-tag.png differ diff --git "a/zh-cn/device-dev/guide/figure/\345\220\257\345\212\250\347\244\272\344\276\213.png" "b/zh-cn/device-dev/guide/figures/\345\220\257\345\212\250\347\244\272\344\276\213.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/guide/figure/\345\220\257\345\212\250\347\244\272\344\276\213.png" rename to "zh-cn/device-dev/guide/figures/\345\220\257\345\212\250\347\244\272\344\276\213.png" diff --git "a/zh-cn/device-dev/guide/figure/\345\256\214\346\225\264\345\267\245\347\250\213\347\233\256\345\275\225.png" "b/zh-cn/device-dev/guide/figures/\345\256\214\346\225\264\345\267\245\347\250\213\347\233\256\345\275\225.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/guide/figure/\345\256\214\346\225\264\345\267\245\347\250\213\347\233\256\345\275\225.png" rename to "zh-cn/device-dev/guide/figures/\345\256\214\346\225\264\345\267\245\347\250\213\347\233\256\345\275\225.png" diff --git "a/zh-cn/device-dev/guide/figure/\345\267\245\347\250\213\347\233\256\345\275\225.png" "b/zh-cn/device-dev/guide/figures/\345\267\245\347\250\213\347\233\256\345\275\225.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/guide/figure/\345\267\245\347\250\213\347\233\256\345\275\225.png" rename to "zh-cn/device-dev/guide/figures/\345\267\245\347\250\213\347\233\256\345\275\225.png" diff --git a/zh-cn/device-dev/guide/figure/Clock.png "b/zh-cn/device-dev/guide/figures/\346\227\266\351\222\237\345\272\224\347\224\250\346\230\276\347\244\272\346\225\210\346\236\234\345\233\276.png" similarity index 100% rename from zh-cn/device-dev/guide/figure/Clock.png rename to "zh-cn/device-dev/guide/figures/\346\227\266\351\222\237\345\272\224\347\224\250\346\230\276\347\244\272\346\225\210\346\236\234\345\233\276.png" diff --git "a/zh-cn/device-dev/guide/figure/\346\237\245\347\234\213\346\226\207\344\273\266\345\233\276.png" "b/zh-cn/device-dev/guide/figures/\346\237\245\347\234\213\346\226\207\344\273\266\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/guide/figure/\346\237\245\347\234\213\346\226\207\344\273\266\345\233\276.png" rename to "zh-cn/device-dev/guide/figures/\346\237\245\347\234\213\346\226\207\344\273\266\345\233\276.png" diff --git "a/zh-cn/device-dev/guide/figure/\346\240\207\351\242\230\346\240\217\345\222\214\344\277\241\346\201\257\346\240\217\346\225\210\346\236\234.png" "b/zh-cn/device-dev/guide/figures/\346\240\207\351\242\230\346\240\217\345\222\214\344\277\241\346\201\257\346\240\217\346\225\210\346\236\234.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/guide/figure/\346\240\207\351\242\230\346\240\217\345\222\214\344\277\241\346\201\257\346\240\217\346\225\210\346\236\234.png" rename to "zh-cn/device-dev/guide/figures/\346\240\207\351\242\230\346\240\217\345\222\214\344\277\241\346\201\257\346\240\217\346\225\210\346\236\234.png" diff --git "a/zh-cn/device-dev/guide/figure/\346\240\207\351\242\230\346\240\217\346\225\210\346\236\234.png" "b/zh-cn/device-dev/guide/figures/\346\240\207\351\242\230\346\240\217\346\225\210\346\236\234.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/guide/figure/\346\240\207\351\242\230\346\240\217\346\225\210\346\236\234.png" rename to "zh-cn/device-dev/guide/figures/\346\240\207\351\242\230\346\240\217\346\225\210\346\236\234.png" diff --git "a/zh-cn/device-dev/guide/figure/\346\241\214\351\235\242.png" "b/zh-cn/device-dev/guide/figures/\346\241\214\351\235\242.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/guide/figure/\346\241\214\351\235\242.png" rename to "zh-cn/device-dev/guide/figures/\346\241\214\351\235\242.png" diff --git "a/zh-cn/device-dev/guide/figure/\346\267\273\345\212\240\351\241\265\351\235\242.png" "b/zh-cn/device-dev/guide/figures/\346\267\273\345\212\240\351\241\265\351\235\242.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/guide/figure/\346\267\273\345\212\240\351\241\265\351\235\242.png" rename to "zh-cn/device-dev/guide/figures/\346\267\273\345\212\240\351\241\265\351\235\242.png" diff --git a/zh-cn/device-dev/guide/figure/Video_2020-07-25_173141.gif "b/zh-cn/device-dev/guide/figures/\347\251\272\346\260\224\350\264\250\351\207\217\347\233\221\346\265\213-App\346\230\276\347\244\272\346\225\210\346\236\234\345\233\276.gif" old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/guide/figure/Video_2020-07-25_173141.gif rename to "zh-cn/device-dev/guide/figures/\347\251\272\346\260\224\350\264\250\351\207\217\347\233\221\346\265\213-App\346\230\276\347\244\272\346\225\210\346\236\234\345\233\276.gif" diff --git "a/zh-cn/device-dev/guide/figure/\350\276\223\345\205\245\345\275\225\345\203\217\346\214\207\344\273\244\345\220\216\344\270\262\345\217\243\346\211\223\345\215\260\346\227\245\345\277\227.png" "b/zh-cn/device-dev/guide/figures/\350\276\223\345\205\245\345\275\225\345\203\217\346\214\207\344\273\244\345\220\216\344\270\262\345\217\243\346\211\223\345\215\260\346\227\245\345\277\227.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/guide/figure/\350\276\223\345\205\245\345\275\225\345\203\217\346\214\207\344\273\244\345\220\216\344\270\262\345\217\243\346\211\223\345\215\260\346\227\245\345\277\227.png" rename to "zh-cn/device-dev/guide/figures/\350\276\223\345\205\245\345\275\225\345\203\217\346\214\207\344\273\244\345\220\216\344\270\262\345\217\243\346\211\223\345\215\260\346\227\245\345\277\227.png" diff --git "a/zh-cn/device-dev/guide/figure/\350\276\223\345\205\245\346\213\215\347\205\247\346\214\207\344\273\244\345\220\216\344\270\262\345\217\243\346\211\223\345\215\260\346\227\245\345\277\227.png" "b/zh-cn/device-dev/guide/figures/\350\276\223\345\205\245\346\213\215\347\205\247\346\214\207\344\273\244\345\220\216\344\270\262\345\217\243\346\211\223\345\215\260\346\227\245\345\277\227.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/guide/figure/\350\276\223\345\205\245\346\213\215\347\205\247\346\214\207\344\273\244\345\220\216\344\270\262\345\217\243\346\211\223\345\215\260\346\227\245\345\277\227.png" rename to "zh-cn/device-dev/guide/figures/\350\276\223\345\205\245\346\213\215\347\205\247\346\214\207\344\273\244\345\220\216\344\270\262\345\217\243\346\211\223\345\215\260\346\227\245\345\277\227.png" diff --git "a/zh-cn/device-dev/guide/figure/\350\276\223\345\205\245\351\241\265\351\235\242\345\220\215\347\247\260.png" "b/zh-cn/device-dev/guide/figures/\350\276\223\345\205\245\351\241\265\351\235\242\345\220\215\347\247\260.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/guide/figure/\350\276\223\345\205\245\351\241\265\351\235\242\345\220\215\347\247\260.png" rename to "zh-cn/device-dev/guide/figures/\350\276\223\345\205\245\351\241\265\351\235\242\345\220\215\347\247\260.png" diff --git "a/zh-cn/device-dev/guide/figure/\350\276\223\345\205\245\351\242\204\350\247\210\346\214\207\344\273\244\345\220\216\344\270\262\345\217\243\346\211\223\345\215\260\346\227\245\345\277\227.png" "b/zh-cn/device-dev/guide/figures/\350\276\223\345\205\245\351\242\204\350\247\210\346\214\207\344\273\244\345\220\216\344\270\262\345\217\243\346\211\223\345\215\260\346\227\245\345\277\227.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/guide/figure/\350\276\223\345\205\245\351\242\204\350\247\210\346\214\207\344\273\244\345\220\216\344\270\262\345\217\243\346\211\223\345\215\260\346\227\245\345\277\227.png" rename to "zh-cn/device-dev/guide/figures/\350\276\223\345\205\245\351\242\204\350\247\210\346\214\207\344\273\244\345\220\216\344\270\262\345\217\243\346\211\223\345\215\260\346\227\245\345\277\227.png" diff --git "a/zh-cn/device-dev/guide/figure/\350\276\223\345\207\272\351\200\200\345\207\272\346\214\207\344\273\244\345\220\216\344\270\262\345\217\243\346\211\223\345\215\260\346\227\245\345\277\227.png" "b/zh-cn/device-dev/guide/figures/\350\276\223\345\207\272\351\200\200\345\207\272\346\214\207\344\273\244\345\220\216\344\270\262\345\217\243\346\211\223\345\215\260\346\227\245\345\277\227.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/guide/figure/\350\276\223\345\207\272\351\200\200\345\207\272\346\214\207\344\273\244\345\220\216\344\270\262\345\217\243\346\211\223\345\215\260\346\227\245\345\277\227.png" rename to "zh-cn/device-dev/guide/figures/\350\276\223\345\207\272\351\200\200\345\207\272\346\214\207\344\273\244\345\220\216\344\270\262\345\217\243\346\211\223\345\215\260\346\227\245\345\277\227.png" diff --git "a/zh-cn/device-dev/guide/figure/\351\241\265\351\235\242\344\275\215\347\275\256\346\214\207\347\244\272\345\231\250\346\225\210\346\236\234\345\233\276.png" "b/zh-cn/device-dev/guide/figures/\351\241\265\351\235\242\344\275\215\347\275\256\346\214\207\347\244\272\345\231\250\346\225\210\346\236\234\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/guide/figure/\351\241\265\351\235\242\344\275\215\347\275\256\346\214\207\347\244\272\345\231\250\346\225\210\346\236\234\345\233\276.png" rename to "zh-cn/device-dev/guide/figures/\351\241\265\351\235\242\344\275\215\347\275\256\346\214\207\347\244\272\345\231\250\346\225\210\346\236\234\345\233\276.png" diff --git "a/zh-cn/device-dev/guide/figure/\351\242\204\350\247\210\346\225\210\346\236\234.jpg" "b/zh-cn/device-dev/guide/figures/\351\242\204\350\247\210\346\225\210\346\236\234.jpg" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/guide/figure/\351\242\204\350\247\210\346\225\210\346\236\234.jpg" rename to "zh-cn/device-dev/guide/figures/\351\242\204\350\247\210\346\225\210\346\236\234.jpg" diff --git a/zh-cn/device-dev/guide/oem_wifi_sdk_des.md b/zh-cn/device-dev/guide/oem_wifi_sdk_des.md index 03d75354c30d9f2f2b6ae3642486ad5a98162960..add96b6c88418f5fa8e5a87ea7daee4f55c22427 100644 --- a/zh-cn/device-dev/guide/oem_wifi_sdk_des.md +++ b/zh-cn/device-dev/guide/oem_wifi_sdk_des.md @@ -106,5 +106,5 @@ OpenHarmony WLAN模组基于Hi3861平台提供了丰富的外设操作能力, 完成以上两步后,按下RST键复位模组,可发现LED在周期性闪烁,与预期相符,验证完毕。 **图 1** LED闪烁图 -![](figure/LED闪烁图.gif "LED闪烁图") +![](figures/LED闪烁图.gif "LED闪烁图") diff --git a/zh-cn/device-dev/kernel/Readme-CN.md b/zh-cn/device-dev/kernel/Readme-CN.md index ad85f2b2a7f98dd16dfe9bfead16c12a78d2f18a..b63423d773efc9efdb195e0bd5a5bf548736e90f 100755 --- a/zh-cn/device-dev/kernel/Readme-CN.md +++ b/zh-cn/device-dev/kernel/Readme-CN.md @@ -109,7 +109,6 @@ - [cpup](kernel-small-debug-shell-cmd-cpup.md) - [date](kernel-small-debug-shell-cmd-date.md) - [dmesg](kernel-small-debug-shell-cmd-dmesg.md) - - [du](kernel-small-debug-shell-file-du.md) - [exec](kernel-small-debug-shell-cmd-exec.md) - [free](kernel-small-debug-shell-cmd-free.md) - [help](kernel-small-debug-shell-cmd-help.md) @@ -119,7 +118,6 @@ - [memcheck](kernel-small-debug-shell-cmd-memcheck.md) - [oom](kernel-small-debug-shell-cmd-oom.md) - [pmm](kernel-small-debug-shell-cmd-pmm.md) - - [reboot](kernel-small-debug-shell-cmd-reboot.md) - [reset](kernel-small-debug-shell-cmd-reset.md) - [sem](kernel-small-debug-shell-cmd-sem.md) - [stack](kernel-small-debug-shell-cmd-stack.md) @@ -127,7 +125,6 @@ - [swtmr](kernel-small-debug-shell-cmd-swtmr.md) - [systeminfo](kernel-small-debug-shell-cmd-sysinfo.md) - [task](kernel-small-debug-shell-cmd-task.md) - - [top](kernel-small-debug-shell-cmd-top.md) - [uname](kernel-small-debug-shell-cmd-uname.md) - [vmm](kernel-small-debug-shell-cmd-vmm.md) - [watch](kernel-small-debug-shell-cmd-watch.md) @@ -143,7 +140,6 @@ - [lsfd](kernel-small-debug-shell-file-lsfd.md) - [mkdir](kernel-small-debug-shell-file-mkdir.md) - [mount](kernel-small-debug-shell-file-mount.md) - - [mv](kernel-small-debug-shell-file-mv.md) - [partinfo](kernel-small-debug-shell-file-partinfo.md) - [partition](kernel-small-debug-shell-file-partition.md) - [pwd](kernel-small-debug-shell-file-pwd.md) @@ -157,6 +153,7 @@ - [网络命令](kernel-small-debug-shell-net.md) - [arp](kernel-small-debug-shell-net-arp.md) - [dhclient](kernel-small-debug-shell-net-dhclient.md) + - [dns](kernel-small-debug-shell-net-dns.md) - [ifconfig](kernel-small-debug-shell-net-ifconfig.md) - [ipdebug](kernel-small-debug-shell-net-ipdebug.md) - [netstat](kernel-small-debug-shell-net-netstat.md) @@ -174,6 +171,15 @@ - [内存信息统计](kernel-small-debug-memory-info.md) - [内存泄漏检测](kernel-small-debug-memory-leak.md) - [踩内存检测](kernel-small-debug-memory-corrupt.md) + - [用户态内存调测](kernel-small-debug-user.md) + - [基本概念](kernel-small-debug-user-concept.md) + - [运行机制](kernel-small-debug-user-function.md) + - [使用指导](kernel-small-debug-user-guide.md) + - [接口说明](kernel-small-debug-user-guide-api.md) + - [使用说明](kernel-small-debug-user-guide-use.md) + - [接口调用方式](kernel-small-debug-user-guide-use-api.md) + - [命令行参数方式](kernel-small-debug-user-guide-use-cli.md) + - [常见问题场景](kernel-small-debug-user-faqs.md) - [其他内核调测手段](kernel-small-debug-other.md) - [临终遗言](kernel-small-debug-trace-other-lastwords.md) - [常见问题定位方法](kernel-small-debug-trace-other-faqs.md) diff --git "a/zh-cn/device-dev/kernel/figure/free\346\265\201\347\250\213\345\233\276.png" "b/zh-cn/device-dev/kernel/figure/free\346\265\201\347\250\213\345\233\276.png" new file mode 100644 index 0000000000000000000000000000000000000000..a8e6e991fc5a81574ad92c44d45bff71c450bbc3 Binary files /dev/null and "b/zh-cn/device-dev/kernel/figure/free\346\265\201\347\250\213\345\233\276.png" differ diff --git "a/zh-cn/device-dev/kernel/figure/malloc\351\200\232\350\277\207mmap\346\234\272\345\210\266\347\224\263\350\257\267\345\206\205\345\255\230\347\232\204\345\206\205\345\255\230\345\270\203\345\261\200.png" "b/zh-cn/device-dev/kernel/figure/malloc\351\200\232\350\277\207mmap\346\234\272\345\210\266\347\224\263\350\257\267\345\206\205\345\255\230\347\232\204\345\206\205\345\255\230\345\270\203\345\261\200.png" new file mode 100644 index 0000000000000000000000000000000000000000..ff50b0e8ef50063df83834091a8d0c0992372599 Binary files /dev/null and "b/zh-cn/device-dev/kernel/figure/malloc\351\200\232\350\277\207mmap\346\234\272\345\210\266\347\224\263\350\257\267\345\206\205\345\255\230\347\232\204\345\206\205\345\255\230\345\270\203\345\261\200.png" differ diff --git "a/zh-cn/device-dev/kernel/figure/node\350\212\202\347\202\271\345\244\264\344\277\241\346\201\257\346\267\273\345\212\240\346\240\241\351\252\214\345\200\274.png" "b/zh-cn/device-dev/kernel/figure/node\350\212\202\347\202\271\345\244\264\344\277\241\346\201\257\346\267\273\345\212\240\346\240\241\351\252\214\345\200\274.png" new file mode 100644 index 0000000000000000000000000000000000000000..9a49391cd3d662305134251f4ee4261c10852106 Binary files /dev/null and "b/zh-cn/device-dev/kernel/figure/node\350\212\202\347\202\271\345\244\264\344\277\241\346\201\257\346\267\273\345\212\240\346\240\241\351\252\214\345\200\274.png" differ diff --git "a/zh-cn/device-dev/kernel/figure/\345\240\206\345\206\205\345\255\230\350\212\202\347\202\271\344\277\241\346\201\257.png" "b/zh-cn/device-dev/kernel/figure/\345\240\206\345\206\205\345\255\230\350\212\202\347\202\271\344\277\241\346\201\257.png" new file mode 100644 index 0000000000000000000000000000000000000000..131519e92cadb00d4ae33f180fba7e410120f98f Binary files /dev/null and "b/zh-cn/device-dev/kernel/figure/\345\240\206\345\206\205\345\255\230\350\212\202\347\202\271\344\277\241\346\201\257.png" differ diff --git "a/zh-cn/device-dev/kernel/figure/\345\240\206\345\206\205\345\255\230\350\212\202\347\202\271\344\277\241\346\201\257\351\223\276\350\241\250.png" "b/zh-cn/device-dev/kernel/figure/\345\240\206\345\206\205\345\255\230\350\212\202\347\202\271\344\277\241\346\201\257\351\223\276\350\241\250.png" new file mode 100644 index 0000000000000000000000000000000000000000..17c3d03c4b35ad7b8d31e9ec091d683d498a0d90 Binary files /dev/null and "b/zh-cn/device-dev/kernel/figure/\345\240\206\345\206\205\345\255\230\350\212\202\347\202\271\344\277\241\346\201\257\351\223\276\350\241\250.png" differ diff --git "a/zh-cn/device-dev/kernel/figure/\346\263\204\346\274\217\347\202\271\344\273\243\347\240\201\350\241\214\345\256\232\344\275\215\346\265\201\347\250\213.png" "b/zh-cn/device-dev/kernel/figure/\346\263\204\346\274\217\347\202\271\344\273\243\347\240\201\350\241\214\345\256\232\344\275\215\346\265\201\347\250\213.png" new file mode 100644 index 0000000000000000000000000000000000000000..0b882d1347c0aa55aa855808847bfb2fad8d8693 Binary files /dev/null and "b/zh-cn/device-dev/kernel/figure/\346\263\204\346\274\217\347\202\271\344\273\243\347\240\201\350\241\214\345\256\232\344\275\215\346\265\201\347\250\213.png" differ diff --git "a/zh-cn/device-dev/kernel/figure/\350\275\273\351\207\217\347\263\273\347\273\237\345\212\250\346\200\201\345\206\205\345\255\230\346\240\270\345\277\203\347\256\227\346\263\225.png" "b/zh-cn/device-dev/kernel/figure/\350\275\273\351\207\217\347\263\273\347\273\237\345\212\250\346\200\201\345\206\205\345\255\230\346\240\270\345\277\203\347\256\227\346\263\225.png" new file mode 100644 index 0000000000000000000000000000000000000000..bd73700c41d62b47005ad0612c74f2823a1921a9 Binary files /dev/null and "b/zh-cn/device-dev/kernel/figure/\350\275\273\351\207\217\347\263\273\347\273\237\345\212\250\346\200\201\345\206\205\345\255\230\346\240\270\345\277\203\347\256\227\346\263\225.png" differ diff --git a/zh-cn/device-dev/kernel/kernel-mini-basic-memory-dynamic.md b/zh-cn/device-dev/kernel/kernel-mini-basic-memory-dynamic.md index 64cccc6f91955f7bcea0a30fc581c94e86bb95ff..5dfdb5bab67a1e03b3fb3b5e8e91e84be5a82631 100644 --- a/zh-cn/device-dev/kernel/kernel-mini-basic-memory-dynamic.md +++ b/zh-cn/device-dev/kernel/kernel-mini-basic-memory-dynamic.md @@ -16,7 +16,7 @@ OpenHarmony LiteOS-M动态内存在TLSF算法的基础上,对区间的划分进行了优化,获得更优的性能,降低了碎片率。动态内存核心算法框图如下: **图 1** 动态内存核心算法 -![](figure/动态内存核心算法.png "动态内存核心算法") +![](figure/轻量系统动态内存核心算法.png "动态内存核心算法") 根据空闲内存块的大小,使用多个空闲链表来管理。根据内存空闲块大小分为两个部分:\[4, 127\]和\[27, 231\],如上图size class所示: diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-user-concept.md b/zh-cn/device-dev/kernel/kernel-small-debug-user-concept.md new file mode 100644 index 0000000000000000000000000000000000000000..5266e039bf2804a3b0c564af61a486dda14fcfa6 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-small-debug-user-concept.md @@ -0,0 +1,6 @@ +# 基本概念 + +Debug版本的musl-libc库为用户提供内存泄漏检测、堆内存统计、踩内存分析以及backtrace功能等维测手段,可以提高用户态内存相关问题的定位效率。 + +采用了对malloc/free接口进行插桩,保存关键节点信息,然后程序在申请和释放内存时进行内存节点完整性校验,最后在程序结束时通过统计节点信息得到内存统计信息并根据统计信息判断内存是否泄漏的设计思想。 + diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-user-faqs.md b/zh-cn/device-dev/kernel/kernel-small-debug-user-faqs.md new file mode 100644 index 0000000000000000000000000000000000000000..064b627e16376bc316754ed0b2046cfda7d2bf7d --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-small-debug-user-faqs.md @@ -0,0 +1,52 @@ +# 常见问题场景 + +- [UAF\(Use after free\)](#section4427132815445) +- [Double free](#section827194818458) +- [堆内存节点被踩](#section1763741216461) + +## UAF\(Use after free\) + +- 申请小块内存(不大于0x1c000字节) + + free之后: + + 读操作:读取free之后的内存大概率是魔术数字\(0xFEFEFEFE\) + + >![](../public_sys-resources/icon-note.gif) **说明:** + >free之后的堆内存不会立即释放进堆内存池,会先放至固定长度的队列中,并置魔术数字0xFE,队列满后会将先放至队列中的内存块释放进堆内存池 + + 写操作:无法校验。 + + +- 申请大块内存(大于0x1c000) + + 堆内存由malloc通过调用mmap接口申请,free之后若仍访问该内存,则用户程序异常(该内存区间已被unmap)。 + + +## Double free + +Double free时,用户程序将会异常退出。 + +## 堆内存节点被踩 + +- 申请小块内存(不大于0x1c000) + + 堆内存节点被踩时,用户程序将会异常退出,并输出破坏被踩节点的可能的堆内存申请调用栈,对于野指针踩内存情况无法校验出来。例如用户程序mem\_check中存在堆内存越界踩的情况,利用命令行方式可以获得踩内存的可能的具体位置。 + + ``` + OHOS # ./mem_check --mwatch + OHOS # + ==PID:6== Memory integrity information: + [TID:28 allocated addr: 0x272e1ea0, size: 0x120] The possible attacker was allocated from: + #00: [0x640e8] -> /lib/libc.so + #01: [0x21d0] -> mem_check + ``` + + 可以通过调用栈解析脚本对调用栈信息进行解析。 + + +- 申请大块内存(大于0x1c000) + + 堆内存由malloc通过mmap接口申请,申请得到的堆内存块前后各置一个size为PAGE\_SIZE大小的区间,设置无读写权限,读写操作会触发用户程序异常。 + + diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-user-function.md b/zh-cn/device-dev/kernel/kernel-small-debug-user-function.md new file mode 100644 index 0000000000000000000000000000000000000000..96783b00693d4c85e2f82aed7e5cfb49444d07da --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-small-debug-user-function.md @@ -0,0 +1,58 @@ +# 运行机制 + +- [内存泄漏检查](#section142061581018) +- [堆内存统计](#section136902041337) +- [内存完整性检查](#section196491231761) + +## 内存泄漏检查 + +对于每个进程,内存调测模块维护了128个链表(当前系统的线程最大数量为128个),每个链表的索引为线程ID。 + +申请内存时:保存关键信息到内存节点控制块,根据当前线程ID将内存节点控制块挂到对应链表; + +释放内存时:根据需要释放的内存地址匹配内存节点控制块并将该控制块删除。 + +**图 1** 堆内存节点信息链表 +![](figure/堆内存节点信息链表.png "堆内存节点信息链表") + +申请内存时,返回地址会被保存到LR寄存器中。进程运行过程中,系统会在内存节点控制块中添加疑似泄漏点对应的lr等信息。如下图所示: + +**图 2** 堆内存节点信息 +![](figure/堆内存节点信息.png "堆内存节点信息") + +其中,TID表示线程ID;PID表示进程ID;ptr表示申请的内存地址;size表示申请的内存大小;lr\[n\]表示函数调用栈地址,变量n可以根据具体场景的需要进行配置。 + +释放内存时,将free等接口的入参指针与node的ptr字段进行匹配,如果相同则删除该内存节点控制块信息。 + +用户通过串口或文件等方式,将各个进程内存调测信息导出,利用addr2line工具将导出的信息转换成导致内存泄漏的代码行,便可以解决内存泄露问题。 + +**图 3** 泄漏点代码行定位流程 +![](figure/泄漏点代码行定位流程.png "泄漏点代码行定位流程") + +## 堆内存统计 + +用户态线程堆内存使用统计具有一定的实际意义,统计线程申请的堆内存占比,为用户程序的内存使用优化提供数据支持。用户态堆内存统计模块主要涉及的接口为malloc和free。如[图1](#fig4294145810543),每个进程维护128个链表,链表索引即线程ID,申请内存时系统将ptr和size信息记录在内存节点控制块中并将节点控制块挂在以线程ID为头信息的链表上,堆内存释放时根据ptr从对应的链表上移除相应的堆内存块信息;同时计算出当前线程所持有的堆内存总的使用量,并更新当前进程的堆内存使用量和堆内存使用峰值。 + +## 内存完整性检查 + +- 使用malloc申请内存(小于等于0x1c000bytes时通过堆分配算法分配) + + 用户程序申请堆内存时,在堆内存节点处添加校验值等信息,如果校验值异常,则很有可能是前一块堆内存使用越界导致的(目前无法识别校验值被野指针破坏的场景)。在内存申请、释放时校验内存节点校验值的正确性,若内存节点被破坏,校验失败时则输出tid、pid及当前被踩节点前一块堆内存申请时保存的调用栈信息,通过addr2line工具可获得具体的代码行信息,辅助用户解决问题。 + + **图 4** node节点头信息添加校验值 + ![](figure/node节点头信息添加校验值.png "node节点头信息添加校验值") + + free堆内存时,不会立即把该内存块释放掉,而是在内存中写入魔术数字0xFE,并放到free队列中\(保证在一定时间内不会再被malloc函数分配\),当有野指针或use-after-free的情况对该内存进行读取的操作时,能够发现数据异常,但是对于写操作则无法判断出来。 + + **图 5** free流程图 + ![](figure/free流程图.png "free流程图") + + +- 使用malloc申请内存(大于0x1c000bytes时通过mmap申请) + + 当malloc通过mmap申请大块内存时,在返回给用户使用的内存区间头和尾分别多申请一个页,一个页PAGE\_SIZE当前为0x1000,这两个页分别通过mprotect接口设置权限为PROT\_NONE(无可读可写权限),可以有效防止内存越界读写问题:越界读写数据时由于无读写权限而导致用户程序异常,根据异常调用栈信息可找到相应的代码逻辑。 + + **图 6** malloc通过mmap机制申请内存的内存布局 + ![](figure/malloc通过mmap机制申请内存的内存布局.png "malloc通过mmap机制申请内存的内存布局") + + diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-user-guide-api.md b/zh-cn/device-dev/kernel/kernel-small-debug-user-guide-api.md new file mode 100644 index 0000000000000000000000000000000000000000..d87b20aeba05abcdccfc0e8f9a4ad6bf9513996e --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-small-debug-user-guide-api.md @@ -0,0 +1,55 @@ +# 接口说明 + +**表 1** 内存调测模块接口 + + +

功能分类

+ + - - - - - - - - - - - - - - - - - - - - - @@ -91,12 +90,10 @@ GPIO接口定义了操作GPIO管脚的标准方法集合,包括: ### 使用流程 -GPIO标准API通过GPIO管脚号来操作指定管脚,使用GPIO的一般流程如[图1](#fig1399416053717)所示。 - -**图 1** GPIO使用流程图 - +GPIO标准API通过GPIO管脚号来操作指定管脚,使用GPIO的一般流程如[图1](#fig16151101653713)所示。 -![](figure/zh-cn_image_0000001170187071.png) +**图 1** GPIO使用流程图 +![](figures/GPIO使用流程图.png "GPIO使用流程图") ### 确定GPIO管脚号 diff --git a/zh-cn/device-dev/driver/driver-platform-gpio-develop.md b/zh-cn/device-dev/driver/driver-platform-gpio-develop.md index 7f587b81c15f62a0e6e91ef97b80bc1a4263bec5..5d4d63ac1f17b61d2fbec88f74129c8b4aac61d4 100755 --- a/zh-cn/device-dev/driver/driver-platform-gpio-develop.md +++ b/zh-cn/device-dev/driver/driver-platform-gpio-develop.md @@ -1,285 +1,418 @@ -# GPIO - -- [概述](#1) -- [开发步骤](#2) -- [开发实例](#3) - -## 概述 - -GPIO(General-purpose input/output)即通用型输入输出,在HDF框架中, -GPIO的接口适配模式采用无服务模式,用于不需要在用户态提供API的设备类型,或者没有用户态和内核区分的OS系统,其关联方式是DevHandle直接指向设备对象内核态地址(DevHandle是一个void类型指针)。 - -图 1 无服务模式结构图 -![image1](figure/无服务模式.png) - -## 开发步骤 - -GPIO模块适配的三个环节是配置属性文件,实例化驱动入口,以及实例化核心层接口函数。GPIO控制器分组管理所有管脚,相关参数会在属性文件中有所体现;驱动入口和接口函数的实例化环节是厂商驱动接入HDF的核心环节。 - -1. **实例化驱动入口:** - - 实例化HdfDriverEntry结构体成员。 - - 调用HDF_INIT将HdfDriverEntry实例化对象注册到HDF框架中。 - -2. **配置属性文件:** - - - 在device_info.hcs文件中添加deviceNode描述。 - - 【可选】添加gpio_config.hcs器件属性文件。 - -3. **实例化GPIO控制器对象:** - - - 初始化GpioCntlr成员。 - - 实例化GpioCntlr成员GpioMethod,其定义和成员**说明**见下 - -4. **驱动调试:** - - 【可选】针对新增驱动程序,建议验证驱动基本功能,例如GPIO控制状态,中断响应情况等。 - -> ![](../public_sys-resources/icon-note.gif) **说明:** -> -> GpioMethod定义 -> -> ```c -> struct GpioMethod { -> int32_t (*request)(struct GpioCntlr *cntlr, uint16_t local);// 【可选】 -> int32_t (*release)(struct GpioCntlr *cntlr, uint16_t local);// 【可选】 -> int32_t (*write)(struct GpioCntlr *cntlr, uint16_t local, uint16_t val); -> int32_t (*read)(struct GpioCntlr *cntlr, uint16_t local, uint16_t *val); -> int32_t (*setDir)(struct GpioCntlr *cntlr, uint16_t local, uint16_t dir); -> int32_t (*getDir)(struct GpioCntlr *cntlr, uint16_t local, uint16_t *dir); -> int32_t (*toIrq)(struct GpioCntlr *cntlr, uint16_t local, uint16_t *irq);// 【可选】 -> int32_t (*setIrq)(struct GpioCntlr *cntlr, uint16_t local, uint16_t mode, GpioIrqFunc func, void *arg); -> int32_t (*unsetIrq)(struct GpioCntlr *cntlr, uint16_t local); -> int32_t (*enableIrq)(struct GpioCntlr *cntlr, uint16_t local); -> int32_t (*disableIrq)(struct GpioCntlr *cntlr, uint16_t local); -> }; -> ``` -> -> 表1 GpioMethod结构体成员的回调函数功能说明 -> -> |函数成员|入参|出参|返回值|功能| -> |-|-|-|-|-| -> |write |**cntlr**:结构体指针,核心层GPIO控制器;
**local**:uint16_t,GPIO端口标识号 ;
**val**:uint16_t,电平传入值; |无| HDF_STATUS相关状态 | GPIO引脚写入电平值 | -> |read |**cntlr**:结构体指针,核心层GPIO控制器;
**local**:uint16_t,GPIO端口标识; |**val**:uint16_t 指针,
用于传出电平值 ;| HDF_STATUS相关状态 | GPIO引脚读取电平值 | -> |setDir |**cntlr**:结构体指针,核心层GPIO控制器;
**local**:uint16_t,GPIO端口标识号 ;
**dir**:uint16_t,管脚方向传入值; |无| HDF_STATUS相关状态 | 设置GPIO引脚输入/输出方向 | -> |getDir |**cntlr**:结构体指针,核心层GPIO控制器;
**local**:uint16_t,GPIO端口标识号 ; |**dir**:uint16_t 指针,
用于传出管脚方向值 ;| HDF_STATUS相关状态 | 读GPIO引脚输入/输出方向 | -> |setIrq |**cntlr**:结构体指针,核心层GPIO控制器;
**local**:uint16_t,GPIO端口标识号;
**mode**:uint16_t,表示触发模式(边沿或电平);
**func**:函数指针,中断服务程序 ;
**arg**:void指针,中断服务程序入参;|无| HDF_STATUS相关状态 |将GPIO引脚设置为中断模式 | -> |unsetIrq |**cntlr**:结构体指针,核心层GPIO控制器;
**local**:uint16_t,GPIO端口标识号 ; |无| HDF_STATUS相关状态 |取消GPIO中断设置 | -> |enableIrq |**cntlr**:结构体指针,核心层GPIO控制器;
**local**:uint16_t,GPIO端口标识号; |无| HDF_STATUS相关状态 |使能GPIO管脚中断 | -> |disableIrq|**cntlr**:结构体指针,核心层GPIO控制器;
**local**:uint16_t,GPIO端口标识号; |无| HDF_STATUS相关状态 |禁止GPIO管脚中断 | - - - - -## 开发实例 -下方将以gpio_hi35xx.c为示例,展示需要厂商提供哪些内容来完整实现设备功能。 - -1. 驱动开发首先需要实例化驱动入口,驱动入口必须为HdfDriverEntry(在 hdf_device_desc.h 中定义)类型的全局变量,且moduleName要和device_info.hcs中保持一致。HDF框架会将所有加载的驱动的HdfDriverEntry对象首地址汇总,形成一个类似数组的段地址空间,方便上层调用。 - - 一般在加载驱动时HDF会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。 - -- GPIO 驱动入口参考 - - ```c - struct HdfDriverEntry g_gpioDriverEntry = { - .moduleVersion = 1, - .Bind = Pl061GpioBind, //GPIO不需要实现Bind,本例是一个空实现,厂商可根据自身需要添加相关操作 - .Init = Pl061GpioInit, //见Init参考 - .Release = Pl061GpioRelease, //见Release参考 - .moduleName = "hisi_pl061_driver",//【必要且需要与HCS文件中里面的moduleName匹配】 - }; - //调用HDF_INIT将驱动入口注册到HDF框架中 - HDF_INIT(g_gpioDriverEntry); - ``` - -2. 完成驱动入口注册之后,下一步请在device_info.hcs文件中添加deviceNode信息,并在 gpio_config.hcs 中配置器件属性。deviceNode信息与驱动入口注册相关,器件属性值与核心层GpioCntlr 成员的默认值或限制范围有密切关系。 - - **本例只有一个GPIO控制器,如有多个器件信息,则需要在device_info文件增加deviceNode信息,以及在gpio_config文件中增加对应的器件属性**。 - -- device_info.hcs 配置参考 - - ```c - root { - device_info { - platform :: host { - hostName = "platform_host"; - priority = 50; - device_gpio :: device { - device0 :: deviceNode { - policy = 0; // 等于0,不需要发布服务 - priority = 10; // 驱动启动优先级 - permission = 0644; // 驱动创建设备节点权限 - moduleName = "hisi_pl061_driver"; //【必要】用于指定驱动名称,需要与期望的驱动Entry中的moduleName一致; - deviceMatchAttr = "hisilicon_hi35xx_pl061";//【必要】用于配置控制器私有数据,要与 gpio_config.hcs 中 - //对应控制器保持一致,其他控制器信息也在文件中 - } - } - } - } - } - ``` - -- gpio_config.hcs 配置参考 - - ```c - root { - platform { - gpio_config { - controller_0x120d0000 { - match_attr = "hisilicon_hi35xx_pl061"; //【必要】必须和device_info.hcs中的deviceMatchAttr值一致 - groupNum = 12; //【必要】GPIO组索引 需要根据设备情况填写 - bitNum = 8; //【必要】每组GPIO管脚数 - regBase = 0x120d0000;//【必要】物理基地址 - regStep = 0x1000; //【必要】寄存器偏移步进 - irqStart = 48; //【必要】开启中断 - irqShare = 0; //【必要】共享中断 - } - } - } - } - ``` - -3. 完成驱动入口注册之后,最后一步就是以核心层GpioCntlr对象的初始化为核心,包括厂商自定义结构体(传递参数和数据),实例化GpioCntlr成员GpioMethod(让用户可以通过接口来调用驱动底层函数),实现HdfDriverEntry成员函数(Bind,Init,Release) - - -- 自定义结构体参考 - - > 从驱动的角度看,自定义结构体是参数和数据的载体,而且gpio_config.hcs文件中的数值会被HDF读入通过DeviceResourceIface来初始化结构体成员,其中一些重要数值也会传递给核心层GpioCntlr对象,例如索引、管脚数等。 - - ```c - struct Pl061GpioCntlr { - struct GpioCntlr cntlr;//【必要】 是核心层控制对象,其成员定义见下面 - volatile unsigned char *regBase; //【必要】寄存器基地址 - uint32_t phyBase; //【必要】 物理基址 - uint32_t regStep; //【必要】 寄存器偏移步进 - uint32_t irqStart; //【必要】 中断开启 - uint16_t groupNum; //【必要】 用于描述厂商的GPIO端口号的参数 - uint16_t bitNum; //【必要】 用于描述厂商的GPIO端口号的参数 - uint8_t irqShare; //【必要】 共享中断 - struct Pl061GpioGroup *groups; //【可选】 根据厂商需要设置 - }; - struct Pl061GpioGroup { //包括寄存器地址,中断号,中断函数和和锁 - volatile unsigned char *regBase; - unsigned int index; - unsigned int irq; - OsalIRQHandle irqFunc; - OsalSpinlock lock; - }; - - // GpioCntlr是核心层控制器结构体,其中的成员在Init函数中会被赋值 - struct GpioCntlr { - struct IDeviceIoService service; - struct HdfDeviceObject *device; - struct GpioMethod *ops; - struct DListHead list; - OsalSpinlock spin; - uint16_t start; - uint16_t count; - struct GpioInfo *ginfos; - void *priv; - }; - ``` - -- **【重要】** GpioCntlr成员回调函数结构体GpioMethod的实例化,其他成员在Init函数中初始化 - - ```c - //GpioMethod结构体成员都是回调函数,厂商需要根据表1完成相应的函数功能。 - static struct GpioMethod g_method = { - .request = NULL, - .release = NULL, - .write = Pl061GpioWrite, //写管脚 - .read = Pl061GpioRead, //读管脚 - .setDir = Pl061GpioSetDir, //设置管脚方向 - .getDir = Pl061GpioGetDir, //获取管脚方向 - .toIrq = NULL, - .setIrq = Pl061GpioSetIrq, //设置管脚中断,如不具备此能力可忽略 - .unsetIrq = Pl061GpioUnsetIrq, //取消管脚中断设置,如不具备此能力可忽略 - .enableIrq = Pl061GpioEnableIrq, //使能管脚中断,如不具备此能力可忽略 - .disableIrq = Pl061GpioDisableIrq,//禁止管脚中断,如不具备此能力可忽略 - }; - ``` - - -- **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 |初始化失败| - > - > **函数说明:** - > 初始化自定义结构体对象,初始化GpioCntlr成员,调用核心层GpioCntlrAdd函数,【可选】接入VFS - - ```c - static int32_t Pl061GpioInit(struct HdfDeviceObject *device) - { - ... - struct Pl061GpioCntlr *pl061 = &g_pl061;//利用静态全局变量完成初始化 - //static struct Pl061GpioCntlr g_pl061 = { - // .groups = NULL, - // .groupNum = PL061_GROUP_MAX, - // .bitNum = PL061_BIT_MAX, - //}; - ret = Pl061GpioReadDrs(pl061, device->property);//利用从gpio_config.HCS文件读取的属性值来初始化自定义结构体对象成员 - ... - pl061->regBase = OsalIoRemap(pl061->phyBase, pl061->groupNum * pl061->regStep);//地址映射 - ... - ret = Pl061GpioInitCntlrMem(pl061); // 内存分配 - ... - pl061->cntlr.count = pl061->groupNum * pl061->bitNum;//【必要】管脚数量计算 - pl061->cntlr.priv = (void *)device->property; //【必要】存储设备属性 - pl061->cntlr.ops = &g_method; // 【必要】GpioMethod的实例化对象的挂载 - pl061->cntlr.device = device; // 【必要】使HdfDeviceObject与GpioCntlr可以相互转化的前提 - ret = GpioCntlrAdd(&pl061->cntlr); // 【必要】调用此函数填充核心层结构体,返回成功信号后驱动才完全接入平台核心层 - ... - Pl061GpioDebugCntlr(pl061); - #ifdef PL061_GPIO_USER_SUPPORT //【可选】若支持用户级的虚拟文件系统,则接入 - if (GpioAddVfs(pl061->bitNum) != HDF_SUCCESS) { - HDF_LOGE("%s: add vfs fail!", __func__); - } - #endif - ... - } - ``` - -- **Release 函数参考** - - > **入参:** - > HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息 - > - > **返回值:** - > 无 - > - > **函数说明:** - > 释放内存和删除控制器,该函数需要在驱动入口结构体中赋值给 Release 接口, 当HDF框架调用Init函数初始化驱动失败时,可以调用 Release 释放驱动资源。所有强制转换获取相应对象的操作**前提**是在Init函数中具备对应赋值的操作。 - - ```c - static void Pl061GpioRelease(struct HdfDeviceObject *device) - { - struct GpioCntlr *cntlr = NULL; - struct Pl061GpioCntlr *pl061 = NULL; - ... - cntlr = GpioCntlrFromDevice(device);//【必要】通过强制转换获取核心层控制对象 - //return (device == NULL) ? NULL : (struct GpioCntlr *)device->service; - ... - #ifdef PL061_GPIO_USER_SUPPORT - GpioRemoveVfs();//与Init中GpioAddVfs相反 - #endif - GpioCntlrRemove(cntlr); //【必要】取消设备信息、服务等内容在核心层上的挂载 - pl061 = ToPl061GpioCntlr(cntlr); //return (struct Pl061GpioCntlr *)cntlr; - Pl061GpioRleaseCntlrMem(pl061); //【必要】锁和内存的释放 - OsalIoUnmap((void *)pl061->regBase);//【必要】解除地址映射 - pl061->regBase = NULL; - } - ``` - - - +# GPIO + +- [概述](#section1826197354103451) +- [接口说明](#section752964871810) +- [开发步骤](#section731175315103451) +- [开发实例](#section800425816103451) + +## 概述 + +GPIO(General-purpose input/output)即通用型输入输出,在HDF框架中, + +GPIO的接口适配模式采用无服务模式,用于不需要在用户态提供API的设备类型,或者没有用户态和内核区分的OS系统,其关联方式是DevHandle直接指向设备对象内核态地址(DevHandle是一个void类型指针)。 + +**图 1** GPIO无服务模式结构图 +![](figures/GPIO无服务模式结构图.png "GPIO无服务模式结构图") + +## 接口说明 + +GpioMethod定义: + +``` +struct GpioMethod { + int32_t (*request)(struct GpioCntlr *cntlr, uint16_t local);// 【可选】 + int32_t (*release)(struct GpioCntlr *cntlr, uint16_t local);// 【可选】 + int32_t (*write)(struct GpioCntlr *cntlr, uint16_t local, uint16_t val); + int32_t (*read)(struct GpioCntlr *cntlr, uint16_t local, uint16_t *val); + int32_t (*setDir)(struct GpioCntlr *cntlr, uint16_t local, uint16_t dir); + int32_t (*getDir)(struct GpioCntlr *cntlr, uint16_t local, uint16_t *dir); + int32_t (*toIrq)(struct GpioCntlr *cntlr, uint16_t local, uint16_t *irq);// 【可选】 + int32_t (*setIrq)(struct GpioCntlr *cntlr, uint16_t local, uint16_t mode, GpioIrqFunc func, void *arg); + int32_t (*unsetIrq)(struct GpioCntlr *cntlr, uint16_t local); + int32_t (*enableIrq)(struct GpioCntlr *cntlr, uint16_t local); + int32_t (*disableIrq)(struct GpioCntlr *cntlr, uint16_t local); +} +``` + +**表 1** GpioMethod结构体成员的回调函数功能说明 + + +

功能分类

接口名

+

接口名

描述

+

描述

GPIO读写

+

GPIO读写

GpioRead

+

GpioRead

读管脚电平值

+

读管脚电平值

GpioWrite

+

GpioWrite

写管脚电平值

+

写管脚电平值

GPIO配置

+

GPIO配置

GpioSetDir

+

GpioSetDir

设置管脚方向

+

设置管脚方向

GpioGetDir

+

GpioGetDir

获取管脚方向

+

获取管脚方向

GPIO中断设置

+

GPIO中断设置

GpioSetIrq

+

GpioSetIrq

设置管脚对应的中断服务函数

+

设置管脚对应的中断服务函数

GpioUnSetIrq

+

GpioUnSetIrq

取消管脚对应的中断服务函数

+

取消管脚对应的中断服务函数

GpioEnableIrq

+

GpioEnableIrq

使能管脚中断

+

使能管脚中断

GpioDisableIrq

+

GpioDisableIrq

禁止管脚中断

+

禁止管脚中断

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

函数成员

+

入参

+

出参

+

返回值

+

功能

+

write

+

cntlr:结构体指针,核心层GPIO控制器;local:uint16_t,GPIO端口标识号 ;val:uint16_t,电平传入值;

+

+

HDF_STATUS相关状态

+

GPIO引脚写入电平值

+

read

+

cntlr:结构体指针,核心层GPIO控制器;local:uint16_t,GPIO端口标识;

+

val:uint16_t 指针,用于传出电平值 ;

+

HDF_STATUS相关状态

+

GPIO引脚读取电平值

+

setDir

+

cntlr:结构体指针,核心层GPIO控制器;local:uint16_t,GPIO端口标识号 ;dir:uint16_t,管脚方向传入值;

+

+

HDF_STATUS相关状态

+

设置GPIO引脚输入/输出方向

+

getDir

+

cntlr:结构体指针,核心层GPIO控制器;local:uint16_t,GPIO端口标识号 ;

+

dir:uint16_t 指针,用于传出管脚方向值 ;

+

HDF_STATUS相关状态

+

读GPIO引脚输入/输出方向

+

setIrq

+

cntlr:结构体指针,核心层GPIO控制器;local:uint16_t,GPIO端口标识号;mode:uint16_t,表示触发模式(边沿或电平);func:函数指针,中断服务程序 ;arg:void指针,中断服务程序入参;

+

+

HDF_STATUS相关状态

+

将GPIO引脚设置为中断模式

+

unsetIrq

+

cntlr:结构体指针,核心层GPIO控制器;local:uint16_t,GPIO端口标识号 ;

+

+

HDF_STATUS相关状态

+

取消GPIO中断设置

+

enableIrq

+

cntlr:结构体指针,核心层GPIO控制器;local:uint16_t,GPIO端口标识号;

+

+

HDF_STATUS相关状态

+

使能GPIO管脚中断

+

disableIrq

+

cntlr:结构体指针,核心层GPIO控制器;local:uint16_t,GPIO端口标识号;

+

+

HDF_STATUS相关状态

+

禁止GPIO管脚中断

+
+ +## 开发步骤 + +GPIO模块适配的三个环节是配置属性文件,实例化驱动入口,以及实例化核心层接口函数。GPIO控制器分组管理所有管脚,相关参数会在属性文件中有所体现;驱动入口和接口函数的实例化环节是厂商驱动接入HDF的核心环节。 + +1. **实例化驱动入口:** + - 实例化HdfDriverEntry结构体成员。 + - 调用HDF\_INIT将HdfDriverEntry实例化对象注册到HDF框架中。 + +2. **配置属性文件:** + - 在device\_info.hcs文件中添加deviceNode描述。 + - 【可选】添加gpio\_config.hcs器件属性文件。 + +3. **实例化GPIO控制器对象:** + - 初始化GpioCntlr成员。 + - 实例化GpioCntlr成员GpioMethod。 + + >![](../public_sys-resources/icon-note.gif) **说明:** + >实例化GpioCntlr成员GpioMethod,详见[接口说明](#section752964871810)。 + + +4. **驱动调试:** + + 【可选】针对新增驱动程序,建议验证驱动基本功能,例如GPIO控制状态,中断响应情况等。 + + +## 开发实例 + +下方将以gpio\_hi35xx.c为示例,展示需要厂商提供哪些内容来完整实现设备功能。 + +1. 驱动开发首先需要实例化驱动入口,驱动入口必须为HdfDriverEntry(在 hdf\_device\_desc.h 中定义)类型的全局变量,且moduleName要和device\_info.hcs中保持一致。HDF框架会将所有加载的驱动的HdfDriverEntry对象首地址汇总,形成一个类似数组的段地址空间,方便上层调用。 + + 一般在加载驱动时HDF会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。 + + GPIO 驱动入口参考: + + ``` + struct HdfDriverEntry g_gpioDriverEntry = { + .moduleVersion = 1, + .Bind = Pl061GpioBind, //GPIO不需要实现Bind,本例是一个空实现,厂商可根据自身需要添加相关操作 + .Init = Pl061GpioInit, //见Init参考 + .Release = Pl061GpioRelease, //见Release参考 + .moduleName = "hisi_pl061_driver",//【必要且需要与HCS文件中里面的moduleName匹配】 + }; + //调用HDF_INIT将驱动入口注册到HDF框架中 + HDF_INIT(g_gpioDriverEntry); + ``` + +2. 完成驱动入口注册之后,下一步请在device\_info.hcs文件中添加deviceNode信息,并在 gpio\_config.hcs 中配置器件属性。deviceNode信息与驱动入口注册相关,器件属性值与核心层GpioCntlr 成员的默认值或限制范围有密切关系。 + + 本例只有一个GPIO控制器,如有多个器件信息,则需要在device\_info文件增加deviceNode信息,以及在gpio\_config文件中增加对应的器件属性。 + + - device\_info.hcs 配置参考。 + + ``` + root { + device_info { + platform :: host { + hostName = "platform_host"; + priority = 50; + device_gpio :: device { + device0 :: deviceNode { + policy = 0; // 等于0,不需要发布服务 + priority = 10; // 驱动启动优先级 + permission = 0644; // 驱动创建设备节点权限 + moduleName = "hisi_pl061_driver"; //【必要】用于指定驱动名称,需要与期望的驱动Entry中的moduleName一致; + deviceMatchAttr = "hisilicon_hi35xx_pl061";//【必要】用于配置控制器私有数据,要与 gpio_config.hcs 中 + //对应控制器保持一致,其他控制器信息也在文件中 + } + } + } + } + } + ``` + + - gpio\_config.hcs 配置参考。 + + ``` + root { + platform { + gpio_config { + controller_0x120d0000 { + match_attr = "hisilicon_hi35xx_pl061"; //【必要】必须和device_info.hcs中的deviceMatchAttr值一致 + groupNum = 12; //【必要】GPIO组索引 需要根据设备情况填写 + bitNum = 8; //【必要】每组GPIO管脚数 + regBase = 0x120d0000;//【必要】物理基地址 + regStep = 0x1000; //【必要】寄存器偏移步进 + irqStart = 48; //【必要】开启中断 + irqShare = 0; //【必要】共享中断 + } + } + } + } + ``` + +3. 完成驱动入口注册之后,最后一步就是以核心层GpioCntlr对象的初始化为核心,包括厂商自定义结构体(传递参数和数据),实例化GpioCntlr成员GpioMethod(让用户可以通过接口来调用驱动底层函数),实现HdfDriverEntry成员函数(Bind,Init,Release)。 + - 自定义结构体参考。 + + 从驱动的角度看,自定义结构体是参数和数据的载体,而且gpio\_config.hcs文件中的数值会被HDF读入通过DeviceResourceIface来初始化结构体成员,其中一些重要数值也会传递给核心层GpioCntlr对象,例如索引、管脚数等。 + + ``` + struct Pl061GpioCntlr { + struct GpioCntlr cntlr;//【必要】 是核心层控制对象,其成员定义见下面 + volatile unsigned char *regBase; //【必要】寄存器基地址 + uint32_t phyBase; //【必要】 物理基址 + uint32_t regStep; //【必要】 寄存器偏移步进 + uint32_t irqStart; //【必要】 中断开启 + uint16_t groupNum; //【必要】 用于描述厂商的GPIO端口号的参数 + uint16_t bitNum; //【必要】 用于描述厂商的GPIO端口号的参数 + uint8_t irqShare; //【必要】 共享中断 + struct Pl061GpioGroup *groups; //【可选】 根据厂商需要设置 + }; + struct Pl061GpioGroup { //包括寄存器地址,中断号,中断函数和和锁 + volatile unsigned char *regBase; + unsigned int index; + unsigned int irq; + OsalIRQHandle irqFunc; + OsalSpinlock lock; + }; + + // GpioCntlr是核心层控制器结构体,其中的成员在Init函数中会被赋值 + struct GpioCntlr { + struct IDeviceIoService service; + struct HdfDeviceObject *device; + struct GpioMethod *ops; + struct DListHead list; + OsalSpinlock spin; + uint16_t start; + uint16_t count; + struct GpioInfo *ginfos; + void *priv; + }; + ``` + + - GpioCntlr成员回调函数结构体GpioMethod的实例化,其他成员在Init函数中初始化。 + + ``` + //GpioMethod结构体成员都是回调函数,厂商需要根据表1完成相应的函数功能。 + static struct GpioMethod g_method = { + .request = NULL, + .release = NULL, + .write = Pl061GpioWrite, //写管脚 + .read = Pl061GpioRead, //读管脚 + .setDir = Pl061GpioSetDir, //设置管脚方向 + .getDir = Pl061GpioGetDir, //获取管脚方向 + .toIrq = NULL, + .setIrq = Pl061GpioSetIrq, //设置管脚中断,如不具备此能力可忽略 + .unsetIrq = Pl061GpioUnsetIrq, //取消管脚中断设置,如不具备此能力可忽略 + .enableIrq = Pl061GpioEnableIrq, //使能管脚中断,如不具备此能力可忽略 + .disableIrq = Pl061GpioDisableIrq,//禁止管脚中断,如不具备此能力可忽略 + }; + ``` + + - Init函数参考 + + 入参: + + HdfDeviceObject这个是整个驱动对外暴露的接口参数,具备HCS配置文件的信息。 + + 返回值: + + HDF\_STATUS相关状态(下表为部分展示,如需使用其他状态,可见//drivers/framework/include/utils/hdf\_base.h中HDF\_STATUS 定义)。 + + **表 2** Init函数说明 + + + + + + + + + + + + + + + + + + + + + + + + + +

状态(值)

+

问题描述

+

HDF_ERR_INVALID_OBJECT

+

控制器对象非法

+

HDF_ERR_MALLOC_FAIL

+

内存分配失败

+

HDF_ERR_INVALID_PARAM

+

参数非法

+

HDF_ERR_IO

+

I/O 错误

+

HDF_SUCCESS

+

初始化成功

+

HDF_FAILURE

+

初始化失败

+
+ + 函数说明: + + 初始化自定义结构体对象,初始化GpioCntlr成员,调用核心层GpioCntlrAdd函数,【可选】接入VFS。 + + ``` + static int32_t Pl061GpioInit(struct HdfDeviceObject *device) + { + ... + struct Pl061GpioCntlr *pl061 = &g_pl061;//利用静态全局变量完成初始化 + //static struct Pl061GpioCntlr g_pl061 = { + // .groups = NULL, + // .groupNum = PL061_GROUP_MAX, + // .bitNum = PL061_BIT_MAX, + //}; + ret = Pl061GpioReadDrs(pl061, device->property);//利用从gpio_config.HCS文件读取的属性值来初始化自定义结构体对象成员 + ... + pl061->regBase = OsalIoRemap(pl061->phyBase, pl061->groupNum * pl061->regStep);//地址映射 + ... + ret = Pl061GpioInitCntlrMem(pl061); // 内存分配 + ... + pl061->cntlr.count = pl061->groupNum * pl061->bitNum;//【必要】管脚数量计算 + pl061->cntlr.priv = (void *)device->property; //【必要】存储设备属性 + pl061->cntlr.ops = &g_method; // 【必要】GpioMethod的实例化对象的挂载 + pl061->cntlr.device = device; // 【必要】使HdfDeviceObject与GpioCntlr可以相互转化的前提 + ret = GpioCntlrAdd(&pl061->cntlr); // 【必要】调用此函数填充核心层结构体,返回成功信号后驱动才完全接入平台核心层 + ... + Pl061GpioDebugCntlr(pl061); + #ifdef PL061_GPIO_USER_SUPPORT //【可选】若支持用户级的虚拟文件系统,则接入 + if (GpioAddVfs(pl061->bitNum) != HDF_SUCCESS) { + HDF_LOGE("%s: add vfs fail!", __func__); + } + #endif + ... + } + ``` + + - Release 函数参考 + + 入参: + + HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息。 + + 返回值: + + 无。 + + 函数说明: + + 释放内存和删除控制器,该函数需要在驱动入口结构体中赋值给 Release 接口, 当HDF框架调用Init函数初始化驱动失败时,可以调用 Release 释放驱动资源。所有强制转换获取相应对象的操作**前提**是在Init函数中具备对应赋值的操作。 + + ``` + static void Pl061GpioRelease(struct HdfDeviceObject *device) + { + struct GpioCntlr *cntlr = NULL; + struct Pl061GpioCntlr *pl061 = NULL; + ... + cntlr = GpioCntlrFromDevice(device);//【必要】通过强制转换获取核心层控制对象 + //return (device == NULL) ? NULL : (struct GpioCntlr *)device->service; + ... + #ifdef PL061_GPIO_USER_SUPPORT + GpioRemoveVfs();//与Init中GpioAddVfs相反 + #endif + GpioCntlrRemove(cntlr); //【必要】取消设备信息、服务等内容在核心层上的挂载 + pl061 = ToPl061GpioCntlr(cntlr); //return (struct Pl061GpioCntlr *)cntlr; + Pl061GpioRleaseCntlrMem(pl061); //【必要】锁和内存的释放 + OsalIoUnmap((void *)pl061->regBase);//【必要】解除地址映射 + pl061->regBase = NULL; + } + ``` + + + 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 ec00c3728c1015b057c0424337e80e1fa350ffe2..535b49a332609ead27020ebe764726d1b8551095 100644 --- a/zh-cn/device-dev/driver/driver-platform-i2c-des.md +++ b/zh-cn/device-dev/driver/driver-platform-i2c-des.md @@ -1,8 +1,7 @@ -# I2C +# I2C - [概述](#section5361140416) - - [接口说明](#section459052019177) - +- [接口说明](#section545869122317) - [使用指导](#section1695201514281) - [使用流程](#section1338373417288) - [打开I2C控制器](#section13751110132914) @@ -25,10 +24,10 @@ - I2C消息传输:通过消息传输结构体数组进行自定义传输 **图 1** I2C物理连线示意图 - ![](figure/I2C物理连线示意图.png "I2C物理连线示意图") + ![](figures/I2C物理连线示意图.png "I2C物理连线示意图") -### 接口说明 +## 接口说明 **表 1** I2C驱动API接口功能介绍 @@ -70,12 +69,10 @@ ### 使用流程 -使用I2C设备的一般流程如[图2](#fig166181128151112)所示。 - -**图 2** I2C设备使用流程图 - +使用I2C设备的一般流程如[图2](#fig183017194234)所示。 -![](figure/zh-cn_image_0000001123509750.png) +**图 2** I2C设备使用流程图 +![](figures/I2C设备使用流程图.png "I2C设备使用流程图") ### 打开I2C控制器 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 b62b1a3d3708b749888a146a38d2d70f2ee914cd..a056cf3e1b7dd380288879309cf7ac5621676a3c 100755 --- a/zh-cn/device-dev/driver/driver-platform-i2c-develop.md +++ b/zh-cn/device-dev/driver/driver-platform-i2c-develop.md @@ -1,309 +1,401 @@ -# I2C - -- [概述](#1) -- [开发步骤](#2) -- [开发实例](#3) - - -## 概述 - -I2C(Inter Integrated Circuit)总线是由Philips公司开发的一种简单、双向二线制同步串行总线,在HDF框架中,I2C模块接口适配模式采用统一服务模式,这需要一个设备服务来作为I2C模块的管理器,统一处理外部访问,这会在配置文件中有所体现。统一服务模式适合于同类型设备对象较多的情况,如I2C可能同时具备十几个控制器,采用独立服务模式需要配置更多的设备节点,且服务会占据内存资源。 - -图 1 统一服务模式结构图 -![image1](figure/统一服务模式.png) - -## 开发步骤 - -I2C模块适配的三个环节是配置属性文件,实例化驱动入口,以及实例化核心层接口函数。 - -1. **实例化驱动入口:** - - - 实例化HdfDriverEntry结构体成员。 - - 调用HDF_INIT将HdfDriverEntry实例化对象注册到HDF框架中。 - -2. **配置属性文件:** - - - 在device_info.hcs文件中添加deviceNode描述。 - - 【可选】添加i2c_config.hcs器件属性文件。 - -3. **实例化I2C控制器对象:** - - - 初始化I2cCntlr成员。 - - 实例化I2cCntlr成员I2cMethod和I2cLockMethod,其定义和成员说明见下 - -4. **驱动调试:** - - 【可选】针对新增驱动程序,建议验证驱动基本功能,例如挂载后的信息反馈,消息传输的成功与否等。 - -> ![](../public_sys-resources/icon-note.gif) **说明:** -> I2cMethod和I2cLockMethod定义 -> -> ```c -> struct I2cMethod { -> 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); //解锁 -> }; -> ``` -> 表1 I2cMethod结构体成员的回调函数功能说明 -> |函数成员|入参|出参|返回值|功能| -> |-|-|-|-|-| -> |transfer |**cntlr**:结构体指针,核心层I2C控制器;
**msgs**:结构体指针,用户消息 ;
**count**:uint16_t,消息数量 |无|HDF_STATUS相关状态| 传递用户消息| - -## 开发实例 - -下方将以i2c_hi35xx.c为示例,展示需要厂商提供哪些内容来完整实现设备功能。 - -1. 驱动开发首先需要实例化驱动入口,驱动入口必须为HdfDriverEntry(在 hdf_device_desc.h 中定义)类型的全局变量,且moduleName要和device_info.hcs中保持一致。HDF框架会将所有加载的驱动的HdfDriverEntry对象首地址汇总,形成一个类似数组的段地址空间,方便上层调用。 - - 一般在加载驱动时HDF会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。 - -- I2C驱动入口参考 - - > I2C模块这种类型的控制器会出现很多个设备挂接的情况,因而在HDF框架中首先会为这类型的设备创建一个管理器对象,并同时对外发布一个管理器服务来统一处理外部访问。这样,用户需要打开某个设备时,会先获取到管理器服务,然后管理器服务根据用户指定参数查找到指定设备。 - > - > I2C管理器服务的驱动由核心层实现,**厂商不需要关注这部分内容的实现,这个但在实现Init函数的时候需要调用核心层的I2cCntlrAdd函数,它会实现相应功能。** - - - ```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 = { - .moduleVersion = 1, - .Bind = I2cManagerBind, - .Init = I2cManagerInit, - .Release = I2cManagerRelease, - .moduleName = "HDF_PLATFORM_I2C_MANAGER",//这与device_info文件中device0对应 - }; - HDF_INIT(g_i2cManagerEntry); - ``` - -2. 完成驱动入口注册之后,下一步请在device_info.hcs文件中添加deviceNode信息,并在i2c_config.hcs中配置器件属性。deviceNode信息与驱动入口注册相关,器件属性值对于厂商驱动的实现以及核心层I2cCntlr相关成员的默认值或限制范围有密切关系。 - - **统一服务模式**的特点是device_info文件中第一个设备节点必须为I2C管理器,其各项参数必须如下设置: - - |成员名|值| - |-|-| - |moduleName | 固定为 HDF_PLATFORM_I2C_MANAGER| - |serviceName| 固定为 HDF_PLATFORM_I2C_MANAGER| - |policy| 具体配置为1或2取决于是否对用户态可见| - |deviceMatchAttr| 没有使用,可忽略| - - **从第二个节点开始配置具体I2C控制器信息**,此节点并不表示某一路I2C控制器,而是代表一个资源性质设备,用于描述一类I2C控制器的信息。多个控制器之间相互区分的参数是busID和reg_pbase,这在i2c_config文件中有所体现。 - -- device_info.hcs 配置参考 - - ```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; - } - ... - } - } - } - ``` - -3. 完成驱动入口注册之后,最后一步就是以核心层I2cCntlr对象的初始化为核心,包括厂商自定义结构体(传递参数和数据),实例化I2cCntlr成员I2cMethod(让用户可以通过接口来调用驱动底层函数),实现HdfDriverEntry成员函数(Bind,Init,Release) - - -- 自定义结构体参考 - - > 从驱动的角度看,自定义结构体是参数和数据的载体,而且i2c_config.hcs文件中的数值会被HDF读入通过DeviceResourceIface来初始化结构体成员,其中一些重要数值也会传递给核心层I2cCntlr对象,例如设备号、总线号等。 - - ```c - // 厂商自定义功能结构体 - struct Hi35xxI2cCntlr { - struct I2cCntlr cntlr; //【必要】是核心层控制对象,具体描述见下面 - 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 regBasePhy; //【必要】寄存器物理基地址 - }; - - // I2cCntlr是核心层控制器结构体,其中的成员在Init函数中会被赋值 - struct I2cCntlr { - struct OsalMutex lock; - void *owner; - int16_t busId; - void *priv; - const struct I2cMethod *ops; - const struct I2cLockMethod *lockOps; - }; - ``` - -- **【重要】** 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,//解锁函数 - }; - ``` - -- **init函数参考** - - > **入参:** - > HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息 - > - > **返回值:** - > HDF_STATUS相关状态 (下表为部分展示,如需使用其他状态,可见//drivers/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 |传输失败| - > - > **函数说明:** - > 初始化自定义结构体对象,初始化I2cCntlr成员,调用核心层I2cCntlrAdd函数,【可选】接入VFS - - ```c - static int32_t Hi35xxI2cInit(struct HdfDeviceObject *device) - { - ... - //遍历、解析 i2c_config.hcs 中的所有配置节点,并分别进行初始化,需要调用Hi35xxI2cParseAndInit函数 - DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) { - ret = Hi35xxI2cParseAndInit(device, childNode);//函数定义见下 - ... - } - ... - } - - 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; //【必要】存储设备属性 - hi35xx->cntlr.busId = hi35xx->bus; //【必要】初始化I2cCntlr成员busId - hi35xx->cntlr.ops = &g_method; //【必要】I2cMethod的实例化对象的挂载 - hi35xx->cntlr.lockOps = &g_lockOps; //【必要】I2cLockMethod的实例化对象的挂载 - (void)OsalSpinInit(&hi35xx->spin); //【必要】锁的初始化 - ret = I2cCntlrAdd(&hi35xx->cntlr); //【必要】调用此函数填充核心层结构体,返回成功信号后驱动才完全接入平台核心层 - ... - #ifdef USER_VFS_SUPPORT - (void)I2cAddVfsById(hi35xx->cntlr.busId);//【可选】若支持用户级的虚拟文件系统,则接入 - #endif - return HDF_SUCCESS; - __ERR__: //不成功的话,需要反向执行初始化相关函数 - if (hi35xx != NULL) { - if (hi35xx->regBase != NULL) { - OsalIoUnmap((void *)hi35xx->regBase); - hi35xx->regBase = NULL; - } - OsalMemFree(hi35xx); - hi35xx = NULL; - } - return ret; - } - ``` - -- **Release 函数参考** - - > **入参:** - > HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息 - > - > **返回值:** - > 无 - > - > **函数说明:** - > 释放内存和删除控制器,该函数需要在驱动入口结构体中赋值给 Release 接口, 当HDF框架调用Init函数初始化驱动失败时,可以调用 Release 释放驱动资源。 - - ```c - static void Hi35xxI2cRelease(struct HdfDeviceObject *device) - { - ... - //与Hi35xxI2cInit一样,需要将对每个节点分别进行释放 - DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) { - Hi35xxI2cRemoveByNode(childNode);//函数定义见下 - } - } - - static void Hi35xxI2cRemoveByNode(const struct DeviceResourceNode *node) - { - ... - //【必要】可以调用 I2cCntlrGet 函数通过设备的 busid 获取 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); - OsalMemFree(hi35xx); - } - return; - } - ``` - +# I2C + +- [概述](#section2040078630114257) +- [接口说明](#section752964871810) +- [开发步骤](#section1085786591114257) +- [开发实例](#section1773332551114257) + +## 概述 + +I2C\(Inter Integrated Circuit\)总线是由Philips公司开发的一种简单、双向二线制同步串行总线,在HDF框架中,I2C模块接口适配模式采用统一服务模式,这需要一个设备服务来作为I2C模块的管理器,统一处理外部访问,这会在配置文件中有所体现。统一服务模式适合于同类型设备对象较多的情况,如I2C可能同时具备十几个控制器,采用独立服务模式需要配置更多的设备节点,且服务会占据内存资源。 + +**图 1** I2C统一服务模式结构图 +![](figures/I2C统一服务模式结构图.png "I2C统一服务模式结构图") + +## 接口说明 + +I2cMethod和I2cLockMethod定义: + +``` +struct I2cMethod { +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); //解锁 +}; +``` + +**表 1** I2cMethod结构体成员的回调函数功能说明 + + + + + + + + + + + + + + + + +

函数成员

+

入参

+

出参

+

返回值

+

功能

+

transfer

+

cntlr:结构体指针,核心层I2C控制器;msgs:结构体指针,用户消息 ;count:uint16_t,消息数量

+

+

HDF_STATUS相关状态

+

传递用户消息

+
+ +## 开发步骤 + +I2C模块适配的三个环节是配置属性文件,实例化驱动入口,以及实例化核心层接口函数。 + +1. **实例化驱动入口:** + - 实例化HdfDriverEntry结构体成员。 + - 调用HDF\_INIT将HdfDriverEntry实例化对象注册到HDF框架中。 + +2. **配置属性文件:** + - 在device\_info.hcs文件中添加deviceNode描述。 + - 【可选】添加i2c\_config.hcs器件属性文件。 + +3. **实例化I2C控制器对象:** + - 初始化I2cCntlr成员。 + - 实例化I2cCntlr成员I2cMethod和I2cLockMethod。 + + >![](../public_sys-resources/icon-note.gif) **说明:** + >实例化I2cCntlr成员I2cMethod和I2cLockMethod,详见[接口说明](#section752964871810)。 + + +4. **驱动调试:** + + 【可选】针对新增驱动程序,建议验证驱动基本功能,例如挂载后的信息反馈,消息传输的成功与否等。 + + +## 开发实例 + +下方将以i2c\_hi35xx.c为示例,展示需要厂商提供哪些内容来完整实现设备功能。 + +1. 驱动开发首先需要实例化驱动入口,驱动入口必须为HdfDriverEntry(在 hdf\_device\_desc.h 中定义)类型的全局变量,且moduleName要和device\_info.hcs中保持一致。HDF框架会将所有加载的驱动的HdfDriverEntry对象首地址汇总,形成一个类似数组的段地址空间,方便上层调用。 + + 一般在加载驱动时HDF会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。 + + I2C驱动入口参考: + + I2C模块这种类型的控制器会出现很多个设备挂接的情况,因而在HDF框架中首先会为这类型的设备创建一个管理器对象,并同时对外发布一个管理器服务来统一处理外部访问。这样,用户需要打开某个设备时,会先获取到管理器服务,然后管理器服务根据用户指定参数查找到指定设备。 + + I2C管理器服务的驱动由核心层实现,厂商不需要关注这部分内容的实现,这个但在实现Init函数的时候需要调用核心层的I2cCntlrAdd函数,它会实现相应功能。 + + ``` + 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 = { + .moduleVersion = 1, + .Bind = I2cManagerBind, + .Init = I2cManagerInit, + .Release = I2cManagerRelease, + .moduleName = "HDF_PLATFORM_I2C_MANAGER",//这与device_info文件中device0对应 + }; + HDF_INIT(g_i2cManagerEntry); + ``` + +2. 完成驱动入口注册之后,下一步请在device\_info.hcs文件中添加deviceNode信息,并在i2c\_config.hcs中配置器件属性。deviceNode信息与驱动入口注册相关,器件属性值对于厂商驱动的实现以及核心层I2cCntlr相关成员的默认值或限制范围有密切关系。 + + 统一服务模式的特点是device\_info文件中第一个设备节点必须为I2C管理器,其各项参数必须如[表2](#table96651915911)设置: + + **表 2** 统一服务模式的特点 + + + + + + + + + + + + + + + + + + + +

成员名

+

+

moduleName

+

固定为 HDF_PLATFORM_I2C_MANAGER

+

serviceName

+

固定为 HDF_PLATFORM_I2C_MANAGER

+

policy

+

具体配置为1或2取决于是否对用户态可见

+

deviceMatchAttr

+

没有使用,可忽略

+
+ + 从第二个节点开始配置具体I2C控制器信息,此节点并不表示某一路I2C控制器,而是代表一个资源性质设备,用于描述一类I2C控制器的信息。多个控制器之间相互区分的参数是busID和reg\_pbase,这在i2c\_config文件中有所体现。 + + - 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)。 + - 自定义结构体参考 + + 从驱动的角度看,自定义结构体是参数和数据的载体,而且i2c\_config.hcs文件中的数值会被HDF读入通过DeviceResourceIface来初始化结构体成员,其中一些重要数值也会传递给核心层I2cCntlr对象,例如设备号、总线号等。 + + ``` + // 厂商自定义功能结构体 + struct Hi35xxI2cCntlr { + struct I2cCntlr cntlr; //【必要】是核心层控制对象,具体描述见下面 + 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 regBasePhy; //【必要】寄存器物理基地址 + }; + + // I2cCntlr是核心层控制器结构体,其中的成员在Init函数中会被赋值 + struct I2cCntlr { + struct OsalMutex lock; + void *owner; + int16_t busId; + void *priv; + const struct I2cMethod *ops; + const struct I2cLockMethod *lockOps; + }; + ``` + + - I2cCntlr成员回调函数结构体I2cMethod的实例化,和锁机制回调函数结构体I2cLockMethod实例化,其他成员在Init函数中初始化。 + + ``` + // i2c_hi35xx.c 中的示例 + static const struct I2cMethod g_method = { + .transfer = Hi35xxI2cTransfer, + }; + + static const struct I2cLockMethod g_lockOps = { + .lock = Hi35xxI2cLock, //加锁函数 + .unlock = Hi35xxI2cUnlock,//解锁函数 + }; + ``` + + - init函数参考 + + 入参: + + HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息。 + + 返回值: + + HDF\_STATUS相关状态 (下表为部分展示,如需使用其他状态,可见//drivers/framework/include/utils/hdf\_base.h中HDF\_STATUS 定义)。 + + **表 3** init函数入参及返回值参考 + + + + + + + + + + + + + + + + + + + + + + + + + +

状态(值)

+

问题描述

+

HDF_ERR_INVALID_OBJECT

+

控制器对象非法

+

HDF_ERR_INVALID_PARAM

+

参数非法

+

HDF_ERR_MALLOC_FAIL

+

内存分配失败

+

HDF_ERR_IO

+

I/O 错误

+

HDF_SUCCESS

+

传输成功

+

HDF_FAILURE

+

传输失败

+
+ + 函数说明: + + 初始化自定义结构体对象,初始化I2cCntlr成员,调用核心层I2cCntlrAdd函数,【可选】接入VFS。 + + ``` + static int32_t Hi35xxI2cInit(struct HdfDeviceObject *device) + { + ... + //遍历、解析 i2c_config.hcs 中的所有配置节点,并分别进行初始化,需要调用Hi35xxI2cParseAndInit函数 + DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) { + ret = Hi35xxI2cParseAndInit(device, childNode);//函数定义见下 + ... + } + ... + } + + 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; //【必要】存储设备属性 + hi35xx->cntlr.busId = hi35xx->bus; //【必要】初始化I2cCntlr成员busId + hi35xx->cntlr.ops = &g_method; //【必要】I2cMethod的实例化对象的挂载 + hi35xx->cntlr.lockOps = &g_lockOps; //【必要】I2cLockMethod的实例化对象的挂载 + (void)OsalSpinInit(&hi35xx->spin); //【必要】锁的初始化 + ret = I2cCntlrAdd(&hi35xx->cntlr); //【必要】调用此函数填充核心层结构体,返回成功信号后驱动才完全接入平台核心层 + ... + #ifdef USER_VFS_SUPPORT + (void)I2cAddVfsById(hi35xx->cntlr.busId);//【可选】若支持用户级的虚拟文件系统,则接入 + #endif + return HDF_SUCCESS; + __ERR__: //不成功的话,需要反向执行初始化相关函数 + if (hi35xx != NULL) { + if (hi35xx->regBase != NULL) { + OsalIoUnmap((void *)hi35xx->regBase); + hi35xx->regBase = NULL; + } + OsalMemFree(hi35xx); + hi35xx = NULL; + } + return ret; + } + ``` + + - Release 函数参考 + + 入参: + + HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息。 + + 返回值: + + 无。 + + 函数说明: + + 释放内存和删除控制器,该函数需要在驱动入口结构体中赋值给 Release 接口, 当HDF框架调用Init函数初始化驱动失败时,可以调用 Release 释放驱动资源。 + + ``` + static void Hi35xxI2cRelease(struct HdfDeviceObject *device) + { + ... + //与Hi35xxI2cInit一样,需要将对每个节点分别进行释放 + DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) { + Hi35xxI2cRemoveByNode(childNode);//函数定义见下 + } + } + + static void Hi35xxI2cRemoveByNode(const struct DeviceResourceNode *node) + { + ... + //【必要】可以调用 I2cCntlrGet 函数通过设备的 busid 获取 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); + OsalMemFree(hi35xx); + } + return; + } + ``` + + + 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 c7cf01ca02d5c96f9c97447abf11a0d7bdb79ee7..3e8de1b4db84629edeaffe83ff0a3f02ab05ea89 100644 --- a/zh-cn/device-dev/driver/driver-platform-mipidsi-des.md +++ b/zh-cn/device-dev/driver/driver-platform-mipidsi-des.md @@ -1,8 +1,7 @@ -# MIPI DSI +# MIPI DSI - [概述](#section16806142183217) - - [接口说明](#section129611916132011) - +- [接口说明](#section12720125432316) - [使用指导](#section037231715335) - [使用流程](#section49299119344) - [获取MIPI-DSI操作句柄](#section5126155683811) @@ -20,10 +19,10 @@ - 图1显示了简化的DSI接口。从概念上看,符合DSI的接口与基于DBI-2和DPI-2标准的接口具有相同的功能。它向外围设备传输像素或命令数据,并且可以从外围设备读取状态或像素信息。主要区别在于,DSI对所有像素数据、命令和事件进行序列化,而在传统接口中,这些像素数据、命令和事件通常需要附加控制信号才能在并行数据总线上传输。 **图 1** DSI发送、接收接口 - ![](figure/DSI发送-接收接口.png "DSI发送-接收接口") + ![](figures/DSI发送-接收接口.png "DSI发送-接收接口") -### 接口说明 +## 接口说明 **表 1** MIPI-DSI API接口功能介绍 @@ -94,12 +93,10 @@ ### 使用流程 -使用MIPI-DSI的一般流程如[图2](#fig99821771782)所示。 - -**图 2** MIPI-DSI使用流程图 - +使用MIPI-DSI的一般流程如[图2](#fig129103491241)所示。 -![](figure/zh-cn_image_0000001123514210.png) +**图 2** MIPI-DSI使用流程图 +![](figures/MIPI-DSI使用流程图.png "MIPI-DSI使用流程图") ### 获取MIPI-DSI操作句柄 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 5dc633c45be6a6d6bbff017d0f17eccea67c3a1f..8bf3895f465ff6d2da893f246b11b140fc5d4f49 100755 --- a/zh-cn/device-dev/driver/driver-platform-mipidsi-develop.md +++ b/zh-cn/device-dev/driver/driver-platform-mipidsi-develop.md @@ -1,235 +1,339 @@ -# MIPI-DSI - -- [概述](#1) -- [开发步骤](#2) -- [开发实例](#3) - -## 概述 - -DSI(Display Serial Interface)是由移动行业处理器接口联盟(Mobile Industry Processor Interface \(MIPI\) Alliance)制定的规范。在HDF框架中, -MIPI-DSI的接口适配模式采用无服务模式,用于不需要在用户态提供API的设备类型,或者没有用户态和内核区分的OS系统,其关联方式是DevHandle直接指向设备对象内核态地址(DevHandle是一个void类型指针)。 - -图 1 无服务模式结构图 -![image1](figure/无服务模式.png) - -## 开发步骤 - -MIPI-DSI模块适配的三个环节是配置属性文件,实例化驱动入口,以及实例化核心层接口函数。 - -1. **实例化驱动入口:** - - - 实例化HdfDriverEntry结构体成员。 - - 调用HDF_INIT将HdfDriverEntry实例化对象注册到HDF框架中。 - -2. **配置属性文件:** - - - 在device_info.hcs文件中添加deviceNode描述。 - - 【可选】添加mipidsi_config.hcs器件属性文件。 - -3. **实例化MIPIDSI控制器对象:** - - - 初始化MipiDsiCntlr成员。 - - 实例化MipiDsiCntlr成员MipiDsiCntlrMethod,其定义和成员**说明**见下 - -4. **驱动调试:** - - 【可选】针对新增驱动程序,建议验证驱动基本功能,例如挂载后的信息反馈,数据传输的成功与否等。 - -> ![](../public_sys-resources/icon-note.gif) **说明:** -> -> 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 -> }; -> ``` -> -> 表1 MipiDsiCntlrMethod成员的回调函数功能说明 -> |成员函数|入参|出参|返回状态|功能| -> |-|-|-|-|-| -> |setCntlrCfg | **cntlr**: 结构体指针,MipiDsi控制器 ; | 无 |HDF_STATUS相关状态 | 设置控制器参数 | -> |setCmd | **cntlr**: 结构体指针,MipiDsi控制器 ;
**cmd**: 结构体指针,指令传入值|无|HDF_STATUS相关状态| 向显示设备发送指令 | -> |getCmd | **cntlr**: 结构体指针,MipiDsi控制器 ; |**cmd**: 结构体指针,
用于传出指令值;|HDF_STATUS相关状态|从显示设备读取信息指令 | -> |toHs | **cntlr**: 结构体指针,MipiDsi控制器 ; | 无 |HDF_STATUS相关状态 |设置为高速模式| -> |toLp | **cntlr**: 结构体指针,MipiDsi控制器 ; | 无 |HDF_STATUS相关状态 |设置为低电模式 | - -## 开发实例 - -下方将以mipi_tx_hi35xx.c为示例,展示需要厂商提供哪些内容来完整实现设备功能。 - - -1. 一般来说,驱动开发首先需要在 xx_config.hcs 中配置器件属性,并在device_info.hcs文件中添加deviceNode描述。器件属性值与核心层MipiDsiCntlr 成员的默认值或限制范围有密切关系,deviceNode信息与驱动入口注册相关。 - - **但本例中MIPI控制器无需配置额外属性,如有厂商需要,则需要在device_info文件的deviceNode增加deviceMatchAttr信息,以及增加mipidsi_config文件**。 - -- 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"; // 【必要且唯一】驱动对外发布服务的名称 - } - } - } - } - } - ``` - -2. 完成器件属性文件的配置之后,下一步请实例化驱动入口,驱动入口必须为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 中保持一致。 - }; - HDF_INIT(g_mipiTxDriverEntry); //调用HDF_INIT将驱动入口注册到HDF框架中 - ``` - -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 or YUV - SyncInfoTag syncInfo; // 时序相关的设置 - unsigned int phyDataRate; // mbps - unsigned int pixelClk; // KHz - } ComboDevCfgTag; - - // MipiDsiCntlr是核心层控制器结构体,其中的成员在Init函数中会被赋值 - struct MipiDsiCntlr { - struct IDeviceIoService service; - struct HdfDeviceObject *device; - unsigned int devNo; // 设备号 - struct MipiCfg cfg; - struct MipiDsiCntlrMethod *ops; - struct OsalMutex lock; - void *priv; - }; - ``` - -- **【重要】** MipiDsiCntlr成员回调函数结构体MipiDsiCntlrMethod的实例化,其他成员在Init函数中初始化 - - ```c - static struct MipiDsiCntlrMethod g_method = { - .setCntlrCfg = Hi35xxSetCntlrCfg, - .setCmd = Hi35xxSetCmd, - .getCmd = Hi35xxGetCmd, - .toHs = Hi35xxToHs, - .toLp = Hi35xxToLp, - }; - ``` - -- **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 |执行失败| - > - > **函数说明:** - > 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); //【必要】厂商对设备的初始化,形式不限 - } - - //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; - } - ``` - -- **Release函数参考** - - > **入参:** - > HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息 - > - > **返回值:** - > 无 - > - > **函数说明:** - > 该函数需要在驱动入口结构体中赋值给 Release 接口, 当 HDF 框架调用 Init 函数初始化驱动失败时,可以调用 Release 释放驱动资源, 该函数中需包含释放内存和删除控制器等操作。所有强制转换获取相应对象的操作**前提**是在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__); - } - ``` - +# MIPI-DSI + +- [概述](#section1266787503161538) +- [接口说明](#section752964871810) +- [开发步骤](#section545182932161538) +- [开发实例](#section1167576616161538) + +## 概述 + +DSI(Display Serial Interface)是由移动行业处理器接口联盟(Mobile Industry Processor Interface \(MIPI\) Alliance)制定的规范。在HDF框架中,MIPI-DSI的接口适配模式采用无服务模式,用于不需要在用户态提供API的设备类型,或者没有用户态和内核区分的OS系统,其关联方式是DevHandle直接指向设备对象内核态地址(DevHandle是一个void类型指针)。 + +**图 1** DSI无服务模式结构图 +![](figures/DSI无服务模式结构图.png "DSI无服务模式结构图") + +## 接口说明 + +MipiDsiCntlrMethod定义: + +``` +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 +}; +``` + +**表 1** MipiDsiCntlrMethod成员的回调函数功能说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

成员函数

+

入参

+

出参

+

返回状态

+

功能

+

setCntlrCfg

+

cntlr: 结构体指针,MipiDsi控制器 ;

+

+

HDF_STATUS相关状态

+

设置控制器参数

+

setCmd

+

cntlr: 结构体指针,MipiDsi控制器 ;cmd: 结构体指针,指令传入值

+

+

HDF_STATUS相关状态

+

向显示设备发送指令

+

getCmd

+

cntlr: 结构体指针,MipiDsi控制器 ;

+

cmd: 结构体指针,用于传出指令值;

+

HDF_STATUS相关状态

+

从显示设备读取信息指令

+

toHs

+

cntlr: 结构体指针,MipiDsi控制器 ;

+

+

HDF_STATUS相关状态

+

设置为高速模式

+

toLp

+

cntlr: 结构体指针,MipiDsi控制器 ;

+

+

HDF_STATUS相关状态

+

设置为低电模式

+
+ +## 开发步骤 + +MIPI-DSI模块适配的三个环节是配置属性文件,实例化驱动入口,以及实例化核心层接口函数。 + +1. **实例化驱动入口:** + - 实例化HdfDriverEntry结构体成员。 + - 调用HDF\_INIT将HdfDriverEntry实例化对象注册到HDF框架中。 + +2. **配置属性文件:** + - 在device\_info.hcs文件中添加deviceNode描述。 + - 【可选】添加mipidsi\_config.hcs器件属性文件。 + +3. **实例化MIPIDSI控制器对象:** + - 初始化MipiDsiCntlr成员。 + - 实例化MipiDsiCntlr成员MipiDsiCntlrMethod。 + + >![](../public_sys-resources/icon-note.gif) **说明:** + >实例化MipiDsiCntlr成员MipiDsiCntlrMethod,其定义和成员说明见[接口说明](#section752964871810)。 + + +4. **驱动调试:** + + 【可选】针对新增驱动程序,建议验证驱动基本功能,例如挂载后的信息反馈,数据传输的成功与否等。 + + +## 开发实例 + +下方将以mipi\_tx\_hi35xx.c为示例,展示需要厂商提供哪些内容来完整实现设备功能。 + +1. 一般来说,驱动开发首先需要在 xx\_config.hcs 中配置器件属性,并在device\_info.hcs文件中添加deviceNode描述。器件属性值与核心层MipiDsiCntlr 成员的默认值或限制范围有密切关系,deviceNode信息与驱动入口注册相关。 + + 但本例中MIPI控制器无需配置额外属性,如有厂商需要,则需要在device\_info文件的deviceNode增加deviceMatchAttr信息,以及增加mipidsi\_config文件。 + + device\_info.hcs 配置参考: + + ``` + 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"; // 【必要且唯一】驱动对外发布服务的名称 + } + } + } + } + } + ``` + +2. 完成器件属性文件的配置之后,下一步请实例化驱动入口,驱动入口必须为HdfDriverEntry(在 hdf\_device\_desc.h 中定义)类型的全局变量,且moduleName要和device\_info.hcs中保持一致。HdfDriverEntry结构体的函数指针成员会被厂商操作函数填充,HDF框架会将所有加载的驱动的HdfDriverEntry对象首地址汇总,形成一个类似数组,方便调用。 + + 一般在加载驱动时HDF框架会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。 + + - MIPI-DSI驱动入口参考。 + + ``` + struct HdfDriverEntry g_mipiTxDriverEntry = { + .moduleVersion = 1, + .Init = Hi35xxMipiTxInit, //见Init参考 + .Release = Hi35xxMipiTxRelease,//见Release参考 + .moduleName = "HDF_MIPI_TX", //【必要】需要与device_info.hcs 中保持一致。 + }; + HDF_INIT(g_mipiTxDriverEntry); //调用HDF_INIT将驱动入口注册到HDF框架中 + ``` + +3. 完成驱动入口注册之后,最后一步就是以核心层MipiDsiCntlr对象的初始化为核心,包括厂商自定义结构体(传递参数和数据),实例化MipiDsiCntlr成员MipiDsiCntlrMethod(让用户可以通过接口来调用驱动底层函数),实现HdfDriverEntry成员函数(Bind,Init,Release)。 + - 自定义结构体参考。 + + 从驱动的角度看,自定义结构体是参数和数据的载体,一般来说,config文件中的数值也会用来初始化结构体成员,但本例的mipidsi无器件属性文件,故基本成员结构与MipiDsiCntlr无太大差异。 + + ``` + typedef struct { + unsigned int devno; // 设备号 + short laneId[LANE_MAX_NUM]; // lane号 + OutPutModeTag outputMode; // 输出模式选择:刷新模式,命令行模式和视频流模式 + VideoModeTag videoMode; // 显示设备的同步模式 + OutputFormatTag outputFormat; // 输出DSI图像数据格式:RGB or YUV + SyncInfoTag syncInfo; // 时序相关的设置 + unsigned int phyDataRate; // mbps + unsigned int pixelClk; // KHz + } ComboDevCfgTag; + + // MipiDsiCntlr是核心层控制器结构体,其中的成员在Init函数中会被赋值 + struct MipiDsiCntlr { + struct IDeviceIoService service; + struct HdfDeviceObject *device; + unsigned int devNo; // 设备号 + struct MipiCfg cfg; + struct MipiDsiCntlrMethod *ops; + struct OsalMutex lock; + void *priv; + }; + ``` + + - MipiDsiCntlr成员回调函数结构体MipiDsiCntlrMethod的实例化,其他成员在Init函数中初始化。 + + ``` + static struct MipiDsiCntlrMethod g_method = { + .setCntlrCfg = Hi35xxSetCntlrCfg, + .setCmd = Hi35xxSetCmd, + .getCmd = Hi35xxGetCmd, + .toHs = Hi35xxToHs, + .toLp = Hi35xxToLp, + }; + ``` + + - 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

+

执行失败

+
+ + 函数说明: + + MipiDsiCntlrMethod的实例化对象的挂载,调用MipiDsiRegisterCntlr,以及其他厂商自定义初始化操作。 + + ``` + 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); //【必要】厂商对设备的初始化,形式不限 + } + + //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; + } + ``` + + - Release函数参考 + + 入参: + + HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息。 + + 返回值: + + 无。 + + 函数说明: + + 该函数需要在驱动入口结构体中赋值给 Release 接口, 当 HDF 框架调用 Init 函数初始化驱动失败时,可以调用 Release 释放驱动资源, 该函数中需包含释放内存和删除控制器等操作。所有强制转换获取相应对象的操作前提是在Init函数中具备对应赋值的操作。 + + ``` + 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__); + } + ``` + + + diff --git a/zh-cn/device-dev/driver/driver-platform-mmc-develop.md b/zh-cn/device-dev/driver/driver-platform-mmc-develop.md index a8c18fd7bc0a2f14c9ce52b971e28029981c343d..b8e0219717ffd428bad3623de5cafc7b17b5b95a 100755 --- a/zh-cn/device-dev/driver/driver-platform-mmc-develop.md +++ b/zh-cn/device-dev/driver/driver-platform-mmc-develop.md @@ -1,379 +1,552 @@ -# MMC - -- [概述](#1) -- [开发步骤](#2) -- [开发实例](#3) - -## 概述 - -MMC(MultiMedia Card),即多媒体卡,在HDF框架中,MMC的接口适配模式采用独立服务模式,在这种模式下,每一个设备对象会独立发布一个设备服务来处理外部访问,设备管理器收到API的访问请求之后,通过提取该请求的参数,达到调用实际设备对象的相应内部方法的目的。 - -独立服务模式可以直接借助HDFDeviceManager的服务管理能力,但需要为每个设备单独配置设备节点,增加内存占用。 - - -图 1 独立服务模式结构图 -![image1](figure/独立服务模式.png) - - -## 开发步骤 - -MMC模块适配的三个环节是配置属性文件,实例化驱动入口,以及实例化核心层接口函数。 - -1. **实例化驱动入口:** - - 实例化HdfDriverEntry结构体成员。 - - 调用HDF_INIT将HdfDriverEntry实例化对象注册到HDF框架中。 - -2. **配置属性文件:** - - - 在device_info.hcs文件中添加deviceNode描述。 - - 【可选】添加mmc_config.hcs器件属性文件。 - -3. **实例化MMC控制器对象:** - - 初始化MmcCntlr成员。 - - 实例化MmcCntlr成员MmcCntlrOps,其定义和成员说明见下 - -4. **驱动调试:** - - 【可选】针对新增驱动程序,建议验证驱动基本功能,例如挂载后的信息反馈,设备启动是否成功等。 - -> ![](../public_sys-resources/icon-note.gif) **说明:** -> -> MmcCntlrOps定义 -> ```c -> struct MmcCntlrOps { -> int32_t (*request)(struct MmcCntlr *cntlr, struct MmcCmd *cmd); -> int32_t (*setClock)(struct MmcCntlr *cntlr, uint32_t clock); -> int32_t (*setPowerMode)(struct MmcCntlr *cntlr, enum MmcPowerMode mode); -> int32_t (*setBusWidth)(struct MmcCntlr *cntlr, enum MmcBusWidth width); -> int32_t (*setBusTiming)(struct MmcCntlr *cntlr, enum MmcBusTiming timing); -> int32_t (*setSdioIrq)(struct MmcCntlr *cntlr, bool enable); -> int32_t (*hardwareReset)(struct MmcCntlr *cntlr); -> int32_t (*systemInit)(struct MmcCntlr *cntlr); -> int32_t (*setEnhanceSrobe)(struct MmcCntlr *cntlr, bool enable); -> int32_t (*switchVoltage)(struct MmcCntlr *cntlr, enum MmcVolt volt); -> bool (*devReadOnly)(struct MmcCntlr *cntlr); -> bool (*devPluged)(struct MmcCntlr *cntlr); -> bool (*devBusy)(struct MmcCntlr *cntlr); -> int32_t (*tune)(struct MmcCntlr *cntlr, uint32_t cmdCode); -> int32_t (*rescanSdioDev)(struct MmcCntlr *cntlr); -> }; -> ``` -> -> 表1 MmcCntlrOps结构体成员的回调函数功能说明 -> |成员函数|入参|返回值|功能| -> |-|-|-|-| -> |doRequest |**cntlr**: 核心层结构体指针,mmc控制器 ;
**cmd**: 结构体指针,传入命令值 |HDF_STATUS相关状态|request相应处理| -> |setClock |**cntlr**: 核心层结构体指针,mmc控制器 ;
**clock**: 时钟传入值 |HDF_STATUS相关状态|设置时钟频率| -> |setPowerMode |**cntlr**: 核心层结构体指针,mmc控制器 ;
**mode**: 枚举值(见MmcPowerMode定义),功耗模式 |HDF_STATUS相关状态|设置功耗模式| -> |setBusWidth |**cntlr**: 核心层结构体指针,mmc控制器 ;
**width**: 枚举值(见MmcBusWidth定义),总线带宽 |HDF_STATUS相关状态|设置总线带宽| -> |setBusTiming |**cntlr**: 核心层结构体指针,mmc控制器 ;
**timing**: 枚举值(见MmcBusTiming定义),总线时序 |HDF_STATUS相关状态|设置总线时序| -> |setSdioIrq |**cntlr**: 核心层结构体指针,mmc控制器 ;
**enable**: 布尔值,控制中断|HDF_STATUS相关状态|使能/去使能SDIO中断| -> |hardwareReset |**cntlr**: 核心层结构体指针,mmc控制器 ; |HDF_STATUS相关状态|复位硬件 | -> |systemInit |**cntlr**: 核心层结构体指针,mmc控制器 ; |HDF_STATUS相关状态|系统初始化 | -> |setEnhanceSrobe |**cntlr**: 核心层结构体指针,mmc控制器 ;
**enable**: 布尔值,设置功能 |HDF_STATUS相关状态|设置增强选通 | -> |switchVoltage |**cntlr**: 核心层结构体指针,mmc控制器 ;
**volt**: 枚举值,电压值(3.3,1.8,1.2V); |HDF_STATUS相关状态|设置电压值 | -> |devReadOnly |**cntlr**: 核心层结构体指针,mmc控制器 ; |布尔值 |检验设备是否只读 | -> |cardPluged |**cntlr**: 核心层结构体指针,mmc控制器 ; |布尔值 |检验设备是否拔出| -> |devBusy |**cntlr**: 核心层结构体指针,mmc控制器 ; |布尔值 |检验设备是否忙碌| -> |tune |**cntlr**: 核心层结构体指针,mmc控制器 ;
**cmdCode**: uint32_t,命令代码; |HDF_STATUS相关状态|调谐 | -> |rescanSdioDev |**cntlr**: 核心层结构体指针,mmc控制器 ; |HDF_STATUS相关状态|扫描并添加SDIO设备,| - - -## 开发实例 - -下方将以himci.c为示例,展示需要厂商提供哪些内容来完整实现设备功能。 - -1. 驱动开发首先需要实例化驱动入口,驱动入口必须为HdfDriverEntry(在 hdf_device_desc.h 中定义)类型的全局变量,且moduleName要和device_info.hcs中保持一致。HDF框架会将所有加载的驱动的HdfDriverEntry对象首地址汇总,形成一个类似数组的段地址空间,方便上层调用。 - - 一般在加载驱动时HDF会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。 - -- MMC驱动入口参考 - - ```c - struct HdfDriverEntry g_mmcDriverEntry = { - .moduleVersion = 1, - .Bind = HimciMmcBind, //见Bind参考 - .Init = HimciMmcInit, //见Init参考 - .Release = HimciMmcRelease, //见Release参考 - .moduleName = "hi3516_mmc_driver",//【必要且与HCS文件中里面的moduleName匹配】 - }; - HDF_INIT(g_mmcDriverEntry); //调用HDF_INIT将驱动入口注册到HDF框架中 - ``` - -2. 完成驱动入口注册之后,下一步请在device_info.hcs文件中添加deviceNode信息,并在mmc_config.hcs中配置器件属性。deviceNode信息与驱动入口注册相关,器件属性值与核心层MmcCntlr成员的默认值或限制范围有密切关系。 - - **如有多个器件信息,则需要在device_info文件增加deviceNode信息,以及在mmc_config文件中增加对应的器件属性。**。 - - -- device_info.hcs 配置参考 - - ```c - root { - device_info { - match_attr = "hdf_manager"; - platform :: host { - hostName = "platform_host"; - priority = 50; - device_mmc:: device { - device0 :: deviceNode { - policy = 2; - priority = 10; - permission = 0644; - moduleName = "hi3516_mmc_driver"; //【必要】用于指定驱动名称,需要与驱动Entry中的moduleName一致; - serviceName = "HDF_PLATFORM_MMC_0"; //【必要】驱动对外发布服务的名称,必须唯一 - deviceMatchAttr = "hi3516_mmc_emmc";//【必要】用于配置控制器私有数据,要与 mmc_config.hcs 中对应控制器保持一致 - } - device1 :: deviceNode { - policy = 1; - priority = 20; - permission = 0644; - moduleName = "hi3516_mmc_driver"; - serviceName = "HDF_PLATFORM_MMC_1"; - deviceMatchAttr = "hi3516_mmc_sd"; //SD类型 - } - device2 :: deviceNode { - policy = 1; - priority = 30; - permission = 0644; - moduleName = "hi3516_mmc_driver"; - serviceName = "HDF_PLATFORM_MMC_2"; - deviceMatchAttr = "hi3516_mmc_sdio";//SDIO类型 - } - } - } - } - } - ``` - -- mmc_config.hcs 配置参考 - - ```c - root { - platform { - mmc_config { - template mmc_controller {//模板公共参数,继承该模板的节点如果使用模板中的默认值,则节点字段可以缺省 - match_attr = ""; - voltDef = 0; // 3.3V - freqMin = 50000; //【必要】最小频率值 - freqMax = 100000000; //【必要】最大频率值 - freqDef = 400000; //【必要】默认频率值 - maxBlkNum = 2048; //【必要】最大的block号 - maxBlkSize = 512; //【必要】最大的block个数 - ocrDef = 0x300000; //【必要】工作电压设置相关 - caps2 = 0; //【必要】属性寄存器相关,见mmc_caps.h 中 MmcCaps2 定义 - regSize = 0x118; //【必要】寄存器位宽 - hostId = 0; //【必要】主机号 - regBasePhy = 0x10020000;//【必要】寄存器物理基地址 - irqNum = 63; //【必要】中断号 - devType = 2; //【必要】模式选择:emmc, SD, SDIO ,COMBO - caps = 0x0001e045; //【必要】属性寄存器相关,见mmc_caps.h 中 MmcCaps 定义 - } - controller_0x10100000 :: mmc_controller { - match_attr = "hi3516_mmc_emmc";//【必要】需要和device_info.hcs中的deviceMatchAttr值一致 - hostId = 0; - regBasePhy = 0x10100000; - irqNum = 96; - devType = 0; // emmc类型 - caps = 0xd001e045; - caps2 = 0x60; - } - controller_0x100f0000 :: mmc_controller { - match_attr = "hi3516_mmc_sd"; - hostId = 1; - regBasePhy = 0x100f0000; - irqNum = 62; - devType = 1; // sd类型 - caps = 0xd001e005; - } - controller_0x10020000 :: mmc_controller { - match_attr = "hi3516_mmc_sdio"; - hostId = 2; - regBasePhy = 0x10020000; - irqNum = 63; - devType = 2; // sdio类型 - caps = 0x0001e04d; - } - } - } - } - ``` - -3. 完成驱动入口注册之后,最后一步就是以核心层MmcCntlr对象的初始化为核心,包括厂商自定义结构体(传递参数和数据),实例化MmcCntlr成员MmcCntlrOps(让用户可以通过接口来调用驱动底层函数),实现HdfDriverEntry成员函数(Bind,Init,Release) - -- 自定义结构体参考 - - > 从驱动的角度看,自定义结构体是参数和数据的载体,而且mmc_config.hcs文件中的数值会被HDF读入通过DeviceResourceIface来初始化结构体成员 ,一些重要数值也会传递给核心层对象。 - - ```c - struct HimciHost { - struct MmcCntlr *mmc;//【必要】核心层结构体 - struct MmcCmd *cmd; //【必要】核心层结构体,传递命令的,相关命令见枚举量 MmcCmdCode - //【可选】根据厂商驱动需要添加 - void *base; - enum HimciPowerStatus powerStatus; - uint8_t *alignedBuff; - uint32_t buffLen; - struct scatterlist dmaSg; - struct scatterlist *sg; - uint32_t dmaSgNum; - DMA_ADDR_T dmaPaddr; - uint32_t *dmaVaddr; - uint32_t irqNum; - bool isTuning; - uint32_t id; - struct OsalMutex mutex; - bool waitForEvent; - HIMCI_EVENT himciEvent; - }; - //MmcCntlr是核心层控制器结构体,其中的成员在bind函数中会被赋值 - struct MmcCntlr { - struct IDeviceIoService service; - struct HdfDeviceObject *hdfDevObj; - struct PlatformDevice device; - struct OsalMutex mutex; - struct OsalSem released; - uint32_t devType; - struct MmcDevice *curDev; - struct MmcCntlrOps *ops; - struct PlatformQueue *msgQueue; - uint16_t index; - uint16_t voltDef; - uint32_t vddBit; - uint32_t freqMin; - uint32_t freqMax; - uint32_t freqDef; - union MmcOcr ocrDef; - union MmcCaps caps; - union MmcCaps2 caps2; - uint32_t maxBlkNum; - uint32_t maxBlkSize; - uint32_t maxReqSize; - bool devPluged; - bool detecting; - void *priv; - }; - ``` - - -- **【重要】** MmcCntlr成员回调函数结构体MmcCntlrOps的实例化,其他成员在Bind函数中初始化 - - ```c - static struct MmcCntlrOps g_himciHostOps = { - .request = HimciDoRequest, - .setClock = HimciSetClock, - .setPowerMode = HimciSetPowerMode, - .setBusWidth = HimciSetBusWidth, - .setBusTiming = HimciSetBusTiming, - .setSdioIrq = HimciSetSdioIrq, - .hardwareReset = HimciHardwareReset, - .systemInit = HimciSystemInit, - .setEnhanceSrobe= HimciSetEnhanceSrobe, - .switchVoltage = HimciSwitchVoltage, - .devReadOnly = HimciDevReadOnly, - .devPluged = HimciCardPluged, - .devBusy = HimciDevBusy, - .tune = HimciTune, - .rescanSdioDev = HimciRescanSdioDev, - }; - ``` - -- **Bind函数参考** - - > **入参:** - > 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 |初始化失败| - > - > **函数说明:** - > MmcCntlr,HimciHost,HdfDeviceObject之间互相赋值,方便其他函数可以相互转化,初始化自定义结构体HimciHost对象,初始化MmcCntlr成员,调用核心层MmcCntlrAdd函数。 - - ```c - static int32_t HimciMmcBind(struct HdfDeviceObject *obj) - { - struct MmcCntlr *cntlr = NULL; - struct HimciHost *host = NULL; - int32_t ret; - cntlr = (struct MmcCntlr *)OsalMemCalloc(sizeof(struct MmcCntlr)); - host = (struct HimciHost *)OsalMemCalloc(sizeof(struct HimciHost)); - - host->mmc = cntlr; //【必要】使HimciHost与MmcCntlr可以相互转化的前提 - cntlr->priv = (void *)host; //【必要】使HimciHost与MmcCntlr可以相互转化的前提 - cntlr->ops = &g_himciHostOps; //【必要】MmcCntlrOps的实例化对象的挂载 - cntlr->hdfDevObj = obj; //【必要】使HdfDeviceObject与MmcCntlr可以相互转化的前提 - obj->service = &cntlr->service; //【必要】使HdfDeviceObject与MmcCntlr可以相互转化的前提 - ret = MmcCntlrParse(cntlr, obj); //【必要】 初始化 cntlr. 失败就 goto _ERR; - ... - ret = HimciHostParse(host, obj); //【必要】 初始化 host对象的相关属性,失败就 goto _ERR; - ... - ret = HimciHostInit(host, cntlr);//厂商自定义的初始化,失败就 goto _ERR; - ... - ret = MmcCntlrAdd(cntlr); //调用核心层函数 失败就 goto _ERR; - ... - (void)MmcCntlrAddDetectMsgToQueue(cntlr);//将卡检测消息添加到队列中。 - HDF_LOGD("HimciMmcBind: success."); - return HDF_SUCCESS; - _ERR: - HimciDeleteHost(host); - HDF_LOGD("HimciMmcBind: fail, err = %d.", ret); - return ret; - } - ``` - - -- **Init函数参考** - - > **入参:** - > HdfDeviceObject是整个驱动对外暴露的接口参数,具备HCS配置文件的信息 - > - > **返回值:** - > HDF_STATUS相关状态 - > - > **函数说明:** - > 实现ProcMciInit - - ```c - static int32_t HimciMmcInit(struct HdfDeviceObject *obj) - { - static bool procInit = false; - (void)obj; - if (procInit == false) { - if (ProcMciInit() == HDF_SUCCESS) { - procInit = true; - HDF_LOGD("HimciMmcInit: proc init success."); - } - } - HDF_LOGD("HimciMmcInit: success."); - return HDF_SUCCESS; - } - ``` - -- **Release函数参考** - - > **入参:** - > HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息 - > - > **返回值:** - > 无 - > - > **函数说明:** - > 释放内存和删除控制器等操作,该函数需要在驱动入口结构体中赋值给Release接口,当HDF框架调用Init函数初始化驱动失败时,可以调用 Release释放驱动资源。所有强制转换获取相应对象的操作**前提**是在Init函数中具备对应赋值的操作。 - - ```c - static void HimciMmcRelease(struct HdfDeviceObject *obj) - { - struct MmcCntlr *cntlr = NULL; - ... - cntlr = (struct MmcCntlr *)obj->service;//这里有HdfDeviceObject到MmcCntlr的强制转化,通过service成员,赋值见Bind函数 - ... - HimciDeleteHost((struct HimciHost *)cntlr->priv);//厂商自定义的内存释放函数,这里有MmcCntlr到HimciHost的强制转化 - } - ``` +# MMC + +- [概述](#section1846388309162704) +- [接口说明](#section752964871810) +- [开发步骤](#section1617495117162704) +- [开发实例](#section1220893490162704) + +## 概述 + +MMC(MultiMedia Card),即多媒体卡,在HDF框架中,MMC的接口适配模式采用独立服务模式,在这种模式下,每一个设备对象会独立发布一个设备服务来处理外部访问,设备管理器收到API的访问请求之后,通过提取该请求的参数,达到调用实际设备对象的相应内部方法的目的。独立服务模式可以直接借助HDFDeviceManager的服务管理能力,但需要为每个设备单独配置设备节点,增加内存占用。 + +**图 1** MMC独立服务模式结构图 +![](figures/MMC独立服务模式结构图.png "MMC独立服务模式结构图") + +## 接口说明 + +MmcCntlrOps定义: + +``` +struct MmcCntlrOps { + int32_t (*request)(struct MmcCntlr *cntlr, struct MmcCmd *cmd); + int32_t (*setClock)(struct MmcCntlr *cntlr, uint32_t clock); + int32_t (*setPowerMode)(struct MmcCntlr *cntlr, enum MmcPowerMode mode); + int32_t (*setBusWidth)(struct MmcCntlr *cntlr, enum MmcBusWidth width); + int32_t (*setBusTiming)(struct MmcCntlr *cntlr, enum MmcBusTiming timing); + int32_t (*setSdioIrq)(struct MmcCntlr *cntlr, bool enable); + int32_t (*hardwareReset)(struct MmcCntlr *cntlr); + int32_t (*systemInit)(struct MmcCntlr *cntlr); + int32_t (*setEnhanceSrobe)(struct MmcCntlr *cntlr, bool enable); + int32_t (*switchVoltage)(struct MmcCntlr *cntlr, enum MmcVolt volt); + bool (*devReadOnly)(struct MmcCntlr *cntlr); + bool (*devPluged)(struct MmcCntlr *cntlr); + bool (*devBusy)(struct MmcCntlr *cntlr); + int32_t (*tune)(struct MmcCntlr *cntlr, uint32_t cmdCode); + int32_t (*rescanSdioDev)(struct MmcCntlr *cntlr); +}; +``` + +**表 1** MmcCntlrOps结构体成员的回调函数功能说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

成员函数

+

入参

+

返回值

+

功能

+

doRequest

+

cntlr: 核心层结构体指针;mmc控制器 ;cmd: 结构体指针,传入命令值

+

HDF_STATUS相关状态

+

request相应处理

+

setClock

+

cntlr: 核心层结构体指针;mmc控制器 ;clock: 时钟传入值

+

HDF_STATUS相关状态

+

设置时钟频率

+

setPowerMode

+

cntlr: 核心层结构体指针;mmc控制器 ;mode: 枚举值(见MmcPowerMode定义),功耗模式

+

HDF_STATUS相关状态

+

设置功耗模式

+

setBusWidth

+

cntlr: 核心层结构体指针;mmc控制器 ;width: 枚举值(见MmcBusWidth定义),总线带宽

+

HDF_STATUS相关状态

+

设置总线带宽

+

setBusTiming

+

cntlr: 核心层结构体指针;mmc控制器 ;timing: 枚举值(见MmcBusTiming定义),总线时序

+

HDF_STATUS相关状态

+

设置总线时序

+

setSdioIrq

+

cntlr: 核心层结构体指针;mmc控制器 ;enable: 布尔值,控制中断

+

HDF_STATUS相关状态

+

使能/去使能SDIO中断

+

hardwareReset

+

cntlr: 核心层结构体指针;mmc控制器 ;

+

HDF_STATUS相关状态

+

复位硬件

+

systemInit

+

cntlr: 核心层结构体指针;mmc控制器 ;

+

HDF_STATUS相关状态

+

系统初始化

+

setEnhanceSrobe

+

cntlr: 核心层结构体指针,mmc控制器 ;enable: 布尔值,设置功能

+

HDF_STATUS相关状态

+

设置增强选通

+

switchVoltage

+

cntlr: 核心层结构体指针;mmc控制器 ;volt: 枚举值,电压值(3.3,1.8,1.2V);

+

HDF_STATUS相关状态

+

设置电压值

+

devReadOnly

+

cntlr: 核心层结构体指针;mmc控制器 ;

+

布尔值

+

检验设备是否只读

+

cardPluged

+

cntlr: 核心层结构体指针;mmc控制器 ;

+

布尔值

+

检验设备是否拔出

+

devBusy

+

cntlr: 核心层结构体指针;mmc控制器 ;

+

布尔值

+

检验设备是否忙碌

+

tune

+

cntlr: 核心层结构体指针;mmc控制器 ;cmdCode: uint32_t,命令代码;

+

HDF_STATUS相关状态

+

调谐

+

rescanSdioDev

+

cntlr: 核心层结构体指针;mmc控制器 ;

+

HDF_STATUS相关状态

+

扫描并添加SDIO设备

+
+ +## 开发步骤 + +MMC模块适配的三个环节是配置属性文件,实例化驱动入口,以及实例化核心层接口函数。 + +1. **实例化驱动入口:** + - 实例化HdfDriverEntry结构体成员。 + - 调用HDF\_INIT将HdfDriverEntry实例化对象注册到HDF框架中。 + +2. **配置属性文件:** + - 在device\_info.hcs文件中添加deviceNode描述。 + - 【可选】添加mmc\_config.hcs器件属性文件。 + +3. **实例化MMC控制器对象:** + - 初始化MmcCntlr成员。 + - 实例化MmcCntlr成员MmcCntlrOps。 + + >![](../public_sys-resources/icon-note.gif) **说明:** + >实例化MmcCntlr成员MmcCntlrOps,其定义和成员说明见[接口说明](#section752964871810)。 + + +4. **驱动调试:** + + 【可选】针对新增驱动程序,建议验证驱动基本功能,例如挂载后的信息反馈,设备启动是否成功等。 + + +## 开发实例 + +下方将以himci.c为示例,展示需要厂商提供哪些内容来完整实现设备功能。 + +1. 驱动开发首先需要实例化驱动入口,驱动入口必须为HdfDriverEntry(在 hdf\_device\_desc.h 中定义)类型的全局变量,且moduleName要和device\_info.hcs中保持一致。HDF框架会将所有加载的驱动的HdfDriverEntry对象首地址汇总,形成一个类似数组的段地址空间,方便上层调用。 + + 一般在加载驱动时HDF会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。 + + MMC驱动入口参考: + + ``` + struct HdfDriverEntry g_mmcDriverEntry = { + .moduleVersion = 1, + .Bind = HimciMmcBind, //见Bind参考 + .Init = HimciMmcInit, //见Init参考 + .Release = HimciMmcRelease, //见Release参考 + .moduleName = "hi3516_mmc_driver",//【必要且与HCS文件中里面的moduleName匹配】 + }; + HDF_INIT(g_mmcDriverEntry); //调用HDF_INIT将驱动入口注册到HDF框架中 + ``` + +2. 完成驱动入口注册之后,下一步请在device\_info.hcs文件中添加deviceNode信息,并在mmc\_config.hcs中配置器件属性。deviceNode信息与驱动入口注册相关,器件属性值与核心层MmcCntlr成员的默认值或限制范围有密切关系。 + + 如有多个器件信息,则需要在device\_info文件增加deviceNode信息,以及在mmc\_config文件中增加对应的器件属性**。** + + - device\_info.hcs 配置参考。 + + ``` + root { + device_info { + match_attr = "hdf_manager"; + platform :: host { + hostName = "platform_host"; + priority = 50; + device_mmc:: device { + device0 :: deviceNode { + policy = 2; + priority = 10; + permission = 0644; + moduleName = "hi3516_mmc_driver"; //【必要】用于指定驱动名称,需要与驱动Entry中的moduleName一致; + serviceName = "HDF_PLATFORM_MMC_0"; //【必要】驱动对外发布服务的名称,必须唯一 + deviceMatchAttr = "hi3516_mmc_emmc";//【必要】用于配置控制器私有数据,要与 mmc_config.hcs 中对应控制器保持一致 + } + device1 :: deviceNode { + policy = 1; + priority = 20; + permission = 0644; + moduleName = "hi3516_mmc_driver"; + serviceName = "HDF_PLATFORM_MMC_1"; + deviceMatchAttr = "hi3516_mmc_sd"; //SD类型 + } + device2 :: deviceNode { + policy = 1; + priority = 30; + permission = 0644; + moduleName = "hi3516_mmc_driver"; + serviceName = "HDF_PLATFORM_MMC_2"; + deviceMatchAttr = "hi3516_mmc_sdio";//SDIO类型 + } + } + } + } + } + ``` + + - mmc\_config.hcs 配置参考。 + + ``` + root { + platform { + mmc_config { + template mmc_controller {//模板公共参数,继承该模板的节点如果使用模板中的默认值,则节点字段可以缺省 + match_attr = ""; + voltDef = 0; // 3.3V + freqMin = 50000; //【必要】最小频率值 + freqMax = 100000000; //【必要】最大频率值 + freqDef = 400000; //【必要】默认频率值 + maxBlkNum = 2048; //【必要】最大的block号 + maxBlkSize = 512; //【必要】最大的block个数 + ocrDef = 0x300000; //【必要】工作电压设置相关 + caps2 = 0; //【必要】属性寄存器相关,见mmc_caps.h 中 MmcCaps2 定义 + regSize = 0x118; //【必要】寄存器位宽 + hostId = 0; //【必要】主机号 + regBasePhy = 0x10020000;//【必要】寄存器物理基地址 + irqNum = 63; //【必要】中断号 + devType = 2; //【必要】模式选择:emmc, SD, SDIO ,COMBO + caps = 0x0001e045; //【必要】属性寄存器相关,见mmc_caps.h 中 MmcCaps 定义 + } + controller_0x10100000 :: mmc_controller { + match_attr = "hi3516_mmc_emmc";//【必要】需要和device_info.hcs中的deviceMatchAttr值一致 + hostId = 0; + regBasePhy = 0x10100000; + irqNum = 96; + devType = 0; // emmc类型 + caps = 0xd001e045; + caps2 = 0x60; + } + controller_0x100f0000 :: mmc_controller { + match_attr = "hi3516_mmc_sd"; + hostId = 1; + regBasePhy = 0x100f0000; + irqNum = 62; + devType = 1; // sd类型 + caps = 0xd001e005; + } + controller_0x10020000 :: mmc_controller { + match_attr = "hi3516_mmc_sdio"; + hostId = 2; + regBasePhy = 0x10020000; + irqNum = 63; + devType = 2; // sdio类型 + caps = 0x0001e04d; + } + } + } + } + ``` + +3. 完成驱动入口注册之后,最后一步就是以核心层MmcCntlr对象的初始化为核心,包括厂商自定义结构体(传递参数和数据),实例化MmcCntlr成员MmcCntlrOps(让用户可以通过接口来调用驱动底层函数),实现HdfDriverEntry成员函数(Bind,Init,Release)。 + - 自定义结构体参考。 + + 从驱动的角度看,自定义结构体是参数和数据的载体,而且mmc\_config.hcs文件中的数值会被HDF读入通过DeviceResourceIface来初始化结构体成员 ,一些重要数值也会传递给核心层对象。 + + ``` + struct HimciHost { + struct MmcCntlr *mmc;//【必要】核心层结构体 + struct MmcCmd *cmd; //【必要】核心层结构体,传递命令的,相关命令见枚举量 MmcCmdCode + //【可选】根据厂商驱动需要添加 + void *base; + enum HimciPowerStatus powerStatus; + uint8_t *alignedBuff; + uint32_t buffLen; + struct scatterlist dmaSg; + struct scatterlist *sg; + uint32_t dmaSgNum; + DMA_ADDR_T dmaPaddr; + uint32_t *dmaVaddr; + uint32_t irqNum; + bool isTuning; + uint32_t id; + struct OsalMutex mutex; + bool waitForEvent; + HIMCI_EVENT himciEvent; + }; + //MmcCntlr是核心层控制器结构体,其中的成员在bind函数中会被赋值 + struct MmcCntlr { + struct IDeviceIoService service; + struct HdfDeviceObject *hdfDevObj; + struct PlatformDevice device; + struct OsalMutex mutex; + struct OsalSem released; + uint32_t devType; + struct MmcDevice *curDev; + struct MmcCntlrOps *ops; + struct PlatformQueue *msgQueue; + uint16_t index; + uint16_t voltDef; + uint32_t vddBit; + uint32_t freqMin; + uint32_t freqMax; + uint32_t freqDef; + union MmcOcr ocrDef; + union MmcCaps caps; + union MmcCaps2 caps2; + uint32_t maxBlkNum; + uint32_t maxBlkSize; + uint32_t maxReqSize; + bool devPluged; + bool detecting; + void *priv; + }; + ``` + + - MmcCntlr成员回调函数结构体MmcCntlrOps的实例化,其他成员在Bind函数中初始化。 + + ``` + static struct MmcCntlrOps g_himciHostOps = { + .request = HimciDoRequest, + .setClock = HimciSetClock, + .setPowerMode = HimciSetPowerMode, + .setBusWidth = HimciSetBusWidth, + .setBusTiming = HimciSetBusTiming, + .setSdioIrq = HimciSetSdioIrq, + .hardwareReset = HimciHardwareReset, + .systemInit = HimciSystemInit, + .setEnhanceSrobe= HimciSetEnhanceSrobe, + .switchVoltage = HimciSwitchVoltage, + .devReadOnly = HimciDevReadOnly, + .devPluged = HimciCardPluged, + .devBusy = HimciDevBusy, + .tune = HimciTune, + .rescanSdioDev = HimciRescanSdioDev, + }; + ``` + + - Bind函数参考 + + 入参**:** + + 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

+

初始化失败

+
+ + 函数说明: + + MmcCntlr,HimciHost,HdfDeviceObject之间互相赋值,方便其他函数可以相互转化,初始化自定义结构体HimciHost对象,初始化MmcCntlr成员,调用核心层MmcCntlrAdd函数。 + + ``` + static int32_t HimciMmcBind(struct HdfDeviceObject *obj) + { + struct MmcCntlr *cntlr = NULL; + struct HimciHost *host = NULL; + int32_t ret; + cntlr = (struct MmcCntlr *)OsalMemCalloc(sizeof(struct MmcCntlr)); + host = (struct HimciHost *)OsalMemCalloc(sizeof(struct HimciHost)); + + host->mmc = cntlr; //【必要】使HimciHost与MmcCntlr可以相互转化的前提 + cntlr->priv = (void *)host; //【必要】使HimciHost与MmcCntlr可以相互转化的前提 + cntlr->ops = &g_himciHostOps; //【必要】MmcCntlrOps的实例化对象的挂载 + cntlr->hdfDevObj = obj; //【必要】使HdfDeviceObject与MmcCntlr可以相互转化的前提 + obj->service = &cntlr->service; //【必要】使HdfDeviceObject与MmcCntlr可以相互转化的前提 + ret = MmcCntlrParse(cntlr, obj); //【必要】 初始化 cntlr. 失败就 goto _ERR; + ... + ret = HimciHostParse(host, obj); //【必要】 初始化 host对象的相关属性,失败就 goto _ERR; + ... + ret = HimciHostInit(host, cntlr);//厂商自定义的初始化,失败就 goto _ERR; + ... + ret = MmcCntlrAdd(cntlr); //调用核心层函数 失败就 goto _ERR; + ... + (void)MmcCntlrAddDetectMsgToQueue(cntlr);//将卡检测消息添加到队列中。 + HDF_LOGD("HimciMmcBind: success."); + return HDF_SUCCESS; + _ERR: + HimciDeleteHost(host); + HDF_LOGD("HimciMmcBind: fail, err = %d.", ret); + return ret; + } + ``` + + - Init函数参考 + + 入参: + + HdfDeviceObject是整个驱动对外暴露的接口参数,具备HCS配置文件的信息。 + + 返回值: + + HDF\_STATUS相关状态。 + + 函数说明: + + 实现ProcMciInit。 + + ``` + static int32_t HimciMmcInit(struct HdfDeviceObject *obj) + { + static bool procInit = false; + (void)obj; + if (procInit == false) { + if (ProcMciInit() == HDF_SUCCESS) { + procInit = true; + HDF_LOGD("HimciMmcInit: proc init success."); + } + } + HDF_LOGD("HimciMmcInit: success."); + return HDF_SUCCESS; + } + ``` + + - Release函数参考 + + 入参: + + HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息。 + + 返回值: + + 无。 + + 函数说明: + + 释放内存和删除控制器等操作,该函数需要在驱动入口结构体中赋值给Release接口,当HDF框架调用Init函数初始化驱动失败时,可以调用 Release释放驱动资源。所有强制转换获取相应对象的操作**前提**是在Init函数中具备对应赋值的操作。 + + ``` + static void HimciMmcRelease(struct HdfDeviceObject *obj) + { + struct MmcCntlr *cntlr = NULL; + ... + cntlr = (struct MmcCntlr *)obj->service;//这里有HdfDeviceObject到MmcCntlr的强制转化,通过service成员,赋值见Bind函数 + ... + HimciDeleteHost((struct HimciHost *)cntlr->priv);//厂商自定义的内存释放函数,这里有MmcCntlr到HimciHost的强制转化 + } + ``` + + + diff --git a/zh-cn/device-dev/driver/driver-platform-pwm-des.md b/zh-cn/device-dev/driver/driver-platform-pwm-des.md new file mode 100644 index 0000000000000000000000000000000000000000..80d67a89dc0e6f067a30829dc8fd953d8cef2042 --- /dev/null +++ b/zh-cn/device-dev/driver/driver-platform-pwm-des.md @@ -0,0 +1,579 @@ +# PWM + +- [概述](#section1043395117296) +- [接口说明](#section3939192652418) +- [使用指导](#section435718267334) + - [使用流程](#section113655616347) + - [获取PWM设备句柄](#section17816586359) + - [设置PWM周期](#section920214812397) + - [设置PWM占空比](#section519712820405) + - [设置PWM极性](#section12383334115) + - [使能PWM](#section382684811414) + - [禁用PWM](#section16545114404218) + - [获取PWM设备配置信息](#section117101243144311) + - [设置PWM设备配置信息](#section13834163604414) + - [释放PWM设备句柄](#section12987111511450) + +- [使用实例](#section138636719469) + +## 概述 + +PWM是脉冲宽度调制(Pulse Width Modulation)的缩写,是一种对模拟信号电平进行数字编码并将其转换为脉冲的技术。常用于马达控制、背光亮度调节等。 + +PWM接口定义了操作PWM设备的通用方法集合,包括: + +- PWM设备句柄获取和释放。 +- PWM周期、占空比、极性的设置。 +- PWM使能和关闭。 +- PWM配置信息的获取和设置 + +## 接口说明 + +**表 1** PWM驱动API接口功能介绍 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

功能分类

+

接口名

+

描述

+

PWM设备句柄获取和释放

+

PwmOpen

+

获取PWM设备句柄

+

PwmClose

+

释放PWM设备句柄

+

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

+

PwmSetPeriod

+

设置PWM周期

+

PwmSetDuty

+

设置PWM占空比

+

PwmSetPolarity

+

设置PWM极性

+

PWM使能和关闭

+

PwmEnable

+

使能PWM

+

PwmDisable

+

禁用PWM

+

PWM配置信息的获取和设置

+

+

PwmSetConfig

+

设置PWM设备配置信息

+

PwmGetConfig

+

获取PWM设备配置信息

+
+ +>![](../public_sys-resources/icon-note.gif) **说明:** +>本文涉及的所有接口,仅限内核态使用,不支持在用户态使用。 + +## 使用指导 + +### 使用流程 + +使用PWM的一般流程如[图1](#fig23885455594)所示。 + +**图 1** PWM使用流程图 + + +![](figures/zh-cn_image_0000001206372673.png) + +### 获取PWM设备句柄 + +在操作PWM设备时,首先要调用PwmOpen获取PWM设备句柄,该函数会返回指定设备号的PWM设备句柄。 + +DevHandle PwmOpen\(uint32\_t num\); + +**表 2** PwmOpen参数和返回值描述 + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

num

+

PWM设备号

+

返回值

+

返回值描述

+

NULL

+

获取PWM设备句柄失败

+

设备句柄

+

对应的PWM设备句柄

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

参数

+

参数描述

+

handle

+

PWM设备句柄

+

period

+

周期,单位纳秒

+

返回值

+

返回值描述

+

0

+

设置周期成功

+

负数

+

设置周期失败

+
+ +``` +int32_t ret; +uint32_t period = 1000; /* 周期1000纳秒 */ +ret = PwmSetPeriod(pwm, period); /* 设置PWM周期 */ +if (ret != 0) { + HDF_LOGE("PwmSetPeriod: failed, ret %d", ret); +} +``` + +### 设置PWM占空比 + +int32\_t PwmSetDuty\(DevHandle handle, uint32\_t duty\); + +**表 4** PwmSetDuty参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

PWM设备句柄

+

duty

+

占空比,单位纳秒

+

返回值

+

返回值描述

+

0

+

设置占空比成功

+

负数

+

设置占空比失败

+
+ +``` +int32_t ret; +uint32_t duty = 500; /* 占空比500纳秒 */ +ret = PwmSetDuty(pwm, duty); /* 设置PWM占空比 */ +if (ret != 0) { + HDF_LOGE("PwmSetDuty: failed, ret %d", ret); +} +``` + +### 设置PWM极性 + +int32\_t PwmSetPolarity\(DevHandle handle, uint8\_t polarity\); + +**表 5** PwmSetPolarity参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

PWM设备句柄

+

polarity

+

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

+

返回值

+

返回值描述

+

0

+

设置极性成功

+

负数

+

设置极性失败

+
+ +``` +int32_t ret; +uint8_t polarity = PWM_INVERTED_POLARITY; /* 反转极性 */ +ret = PwmSetPolarity(pwm, polarity); /* 设置PWM反转极性 */ +if (ret != 0) { + HDF_LOGE("PwmSetPolarity: failed, ret %d", ret); +} +``` + +### 使能PWM + +int32\_t PwmEnable\(DevHandle handle\); + +**表 6** PwmEnable参数和返回值描述 + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

PWM设备句柄

+

返回值

+

返回值描述

+

0

+

使能PWM成功

+

负数

+

使能PWM失败

+
+ +``` +int32_t ret; +ret = PwmEnable(pwm); /* 使能PWM */ +if (ret != 0) { + HDF_LOGE("PwmEnable: failed, ret %d", ret); +} +``` + +### 禁用PWM + +int32\_t PwmDisable\(DevHandle handle\); + +**表 7** PwmDisable参数和返回值描述 + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

PWM设备句柄

+

返回值

+

返回值描述

+

0

+

关闭PWM成功

+

负数

+

关闭PWM失败

+
+ +``` +int32_t ret; +ret = PwmDisable(pwm); /* 禁用PWM */ +if (ret != 0) { + HDF_LOGE("PwmDisable: failed, ret %d", ret); +} +``` + +### 获取PWM设备配置信息 + +int32\_t PwmGetConfig\(DevHandle handle, struct PwmConfig \*config\); + +**表 8** PwmGetConfig参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

PWM设备句柄

+

config

+

PWM设备配置信息

+

返回值

+

返回值描述

+

0

+

获取配置成功

+

负数

+

获取配置失败

+
+ +``` +int32_t ret; +struct PwmConfig config= {0}; /* PWM配置信息 */ +ret = PwmGetConfig(pwm, &config); /* 获取PWM设备配置信息 */ +if (ret != 0) { + HDF_LOGE("PwmGetConfig: failed, ret %d", ret); +} +``` + +### 设置PWM设备配置信息 + +int32\_t PwmSetConfig\(DevHandle handle, struct PwmConfig \*config\); + +**表 9** PwmSetConfig参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

PWM设备句柄

+

config

+

PWM设备配置信息

+

返回值

+

返回值描述

+

0

+

设置配置成功

+

负数

+

设置配置失败

+
+ +``` +int32_t ret; +struct PwmConfig config= {0}; /* PWM配置信息 */ +config.duty = 500; /* 占空比500纳秒 */ +config.period = 1000; /* 周期1000纳秒 */ +config.number = 0; /* 一直输出方波 */ +config.polarity = PWM_NORMAL_POLARITY; /* 正常极性 */ +ret = PwmSetConfig(pwm, &config); /* 设置PWM设备配置信息 */ +if (ret != 0) { + HDF_LOGE("PwmSetConfig: failed, ret %d\n", ret); +} +``` + +### 释放PWM设备句柄 + +void PwmClose\(DevHandle handle\); + +该函数会释放掉由PwmClose申请的资源。 + +**表 10** PwmClose参数描述 + + + + + + + + + +

参数

+

参数描述

+

handle

+

PWM设备句柄

+
+ +``` +PwmClose(pwm); /* 释放PWM设备句柄 */ +``` + +## 使用实例 + +PWM设备完整的使用示例如下所示,首先获取PWM设备句柄,然后设置PWM设备配置信息,使能PWM,最后释放PWM设备句柄。 + +``` +#include "hdf_log.h" +#include "osal_time.h" +#include "pwm_if.h" + +void PwmTestSample(void) +{ + int32_t ret; + struct PwmConfig config; /* PWM配置信息 */ + DevHandle pwm = NULL; /* PWM设备句柄 */ + + pwm = PwmOpen(0); /* 获取PWM设备句柄 */ + if (pwm == NULL) { + HDF_LOGE("PwmOpen: pwm0 failed"); + return; + } + /* 获取PWM设备配置信息 */ + ret = PwmGetConfig(pwm, &config); + if (ret != 0) { + HDF_LOGE("PwmGetConfig: failed, ret %d\n", ret); + goto err; + } + config.duty = 500; /* 占空比500纳秒 */ + config.period = 1000; /* 周期1000纳秒 */ + /* 设置PWM设备配置信息 */ + ret = PwmSetConfig(pwm, &config); + if (ret != 0) { + HDF_LOGE("PwmSetConfig: failed, ret %d\n", ret); + goto err; + } + /* 使能PWM */ + ret = PwmEnable(pwm); + if (ret != 0) { + HDF_LOGE("PwmEnable: failed, ret %d\n", ret); + goto err; + } + /* 睡眠10秒 */ + OsalSleep(10); + /* 禁用PWM */ + ret = PwmDisable(pwm); + if (ret != 0) { + HDF_LOGE("PwmDisable: failed, ret %d\n", ret); + goto err; + } +err: + /* 释放PWM设备句柄 */ + PwmClose(pwm); +} +``` + diff --git a/zh-cn/device-dev/driver/driver-platform-pwm-develop.md b/zh-cn/device-dev/driver/driver-platform-pwm-develop.md index dd2e846b7809d31d3e8777b2026426c092c16f7a..123d12aee05a96359f76da4a2cd2f0691ae9b8df 100755 --- a/zh-cn/device-dev/driver/driver-platform-pwm-develop.md +++ b/zh-cn/device-dev/driver/driver-platform-pwm-develop.md @@ -1,275 +1,351 @@ -# PWM - -- [概述](#1) -- [开发步骤](#2) -- [开发实例](#3) - -## 概述 - -PWM(Pulse Width Modulator)即脉冲宽度调节器,在HDF框架中,PWM的接口适配模式采用独立服务模式,在这种模式下,每一个设备对象会独立发布一个设备服务来处理外部访问,设备管理器收到API的访问请求之后,通过提取该请求的参数,达到调用实际设备对象的相应内部方法的目的。 - -独立服务模式可以直接借助HDFDeviceManager的服务管理能力,但需要为每个设备单独配置设备节点,增加内存占用。 - -图 1 独立服务模式结构图 -![image1](figure/独立服务模式.png) - -## 开发步骤 - -PWM模块适配HDF框架的三个环节是配置属性文件,实例化驱动入口,以及填充核心层接口函数。 - -1. **实例化驱动入口:** - - 实例化HdfDriverEntry结构体成员。 - - 调用HDF_INIT将HdfDriverEntry实例化对象注册到HDF框架中。 - -2. **配置属性文件:** - - - 在device_info.hcs文件中添加deviceNode描述。 - - 【可选】添加pwm_config.hcs器件属性文件。 - -3. **实例化PWM控制器对象:** - - - 初始化PwmDev成员。 - - 实例化PwmDev成员PwmMethod,其定义和成员说明见下 - -4. **驱动调试:** - - 【可选】针对新增驱动程序,建议验证驱动基本功能,例如PWM控制状态,中断响应情况等。 - -> ![](../public_sys-resources/icon-note.gif) **说明:** -> -> PwmMethod定义 -> ```c -> struct PwmMethod { -> int32_t (*setConfig)(struct PwmDev *pwm, struct PwmConfig *config); -> int32_t (*open)(struct PwmDev *pwm); -> int32_t (*close)(struct PwmDev *pwm); -> }; -> ``` -> -> 表1 PwmMethod结构体成员的回调函数功能说明 -> |成员函数|入参|返回值|功能| -> |-|-|-|-| -> |setConfig|**pwm**: 结构体指针,核心层PWM控制器;
**config**: 结构体指针,属性传入值;|HDF_STATUS相关状态|配置属性| -> |open |**pwm**: 结构体指针,核心层PWM控制器;|HDF_STATUS相关状态|打开设备| -> |close|**pwm**: 结构体指针,核心层PWM控制器;|HDF_STATUS相关状态|关闭设备| - -## 开发实例 - -下方将以pwm_hi35xx.c为示例,展示需要厂商提供哪些内容来完整实现设备功能。 - -1. 驱动开发首先需要实例化驱动入口,驱动入口必须为HdfDriverEntry(在 hdf_device_desc.h 中定义)类型的全局变量,且moduleName要和device_info.hcs中保持一致。HDF框架会将所有加载的驱动的HdfDriverEntry对象首地址汇总,形成一个类似数组的段地址空间,方便上层调用。 - - 一般在加载驱动时HDF会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。 - -- PWM驱动入口参考 - - ```c - struct HdfDriverEntry g_hdfPwm = { - .moduleVersion = 1, - .moduleName = "HDF_PLATFORM_PWM",//【必要 且与 HCS文件中里面的moduleName匹配】 - .Bind = HdfPwmBind, - .Init = HdfPwmInit, - .Release = HdfPwmRelease, - }; - //调用HDF_INIT将驱动入口注册到HDF框架中 - HDF_INIT(g_hdfPwm); - ``` - -2. 完成驱动入口注册之后,下一步请在device_info.hcs文件中添加deviceNode信息,并在 pwm_config.hcs 中配置器件属性。deviceNode信息与驱动入口注册相关,器件属性值与核心层PwmDev成员的默认值或限制范围有密切关系。 - - **如有更多个器件信息,则需要在device_info文件增加deviceNode信息,以及在pwm_config文件中增加对应的器件属性**。 - -- device_info.hcs 配置参考 - - ```c - root { - device_info { - platform :: host { - hostName = "platform_host"; - priority = 50; - device_pwm :: device {//为每一个 pwm 控制器配置一个HDF设备节点,存在多个时【必须】添加,否则不用 - device0 :: deviceNode { - policy = 1; // 等于1,向内核态发布服务 - priority = 80; // 驱动启动优先级 - permission = 0644;// 驱动创建设备节点权限 - moduleName = "HDF_PLATFORM_PWM"; //【必要】用于指定驱动名称,需要与期望的驱动Entry中的moduleName一致; - serviceName = "HDF_PLATFORM_PWM_0";//【必要且唯一】驱动对外发布服务的名称 - deviceMatchAttr = "hisilicon_hi35xx_pwm_0";//【必要】用于配置控制器私有数据,要与 pwm_config.hcs 中对应 - // 控制器保持一致,具体的控制器信息在 pwm_config.hcs 中 - } - device1 :: deviceNode { - policy = 1; - priority = 80; - permission = 0644; - moduleName = "HDF_PLATFORM_PWM"; - serviceName = "HDF_PLATFORM_PWM_1"; - deviceMatchAttr = "hisilicon_hi35xx_pwm_1"; - } - } - } - } - } - ``` - -- pwm_config.hcs 配置参考 - - ```c - root { - platform { - pwm_config { - template pwm_device { //【必要】模板配置,继承该模板的节点如果使用模板中的默认值,则节点字段可以缺省 - serviceName = ""; - match_attr = ""; - num = 0; //【必要】设备号 - base = 0x12070000; //【必要】地址映射需要 - } - device_0x12070000 :: pwm_device { - match_attr = "hisilicon_hi35xx_pwm_0";//【必要】需要和device_info.hcs中的deviceMatchAttr值一致 - } - device_0x12070020 :: pwm_device { //存在多个设备时【必须】添加,否则不用 - match_attr = "hisilicon_hi35xx_pwm_1"; - num = 1; - base = 0x12070020; //【必要】地址映射需要 - } - } - } - } - ``` - -3. 完成驱动入口注册之后,最后一步就是以核心层PwmDev对象的初始化为核心,包括厂商自定义结构体(传递参数和数据),实例化PwmDev成员PwmMethod(让用户可以通过接口来调用驱动底层函数),实现HdfDriverEntry成员函数(Bind,Init,Release) - -- 自定义结构体参考 - - > 从驱动的角度看,自定义结构体是参数和数据的载体,而且pwm_config.hcs文件中的数值会被HDF读入通过DeviceResourceIface来初始化结构体成员,一些重要数值也会传递给核心层对象,例如设备号等。 - - ```c - struct HiPwm { - struct PwmDev dev; //【必要】 核心层结构体 - volatile unsigned char *base; - struct HiPwmRegs *reg; // 设备属性结构体,可自定义 - bool supportPolarity; - }; - - // PwmDev是核心层控制器结构体,其中的成员在Init函数中会被赋值 - struct PwmDev { - struct IDeviceIoService service; - struct HdfDeviceObject *device; - struct PwmConfig cfg; //属性结构体,相关定义见下 - struct PwmMethod *method; //钩子函数模板 - bool busy; - uint32_t num; //设备号 - OsalSpinlock lock; - void *priv; //私有数据,一般存储自定义结构体首地址,方便调用 - }; - struct PwmConfig { - uint32_t duty; // 占空时间 nanoseconds - uint32_t period; // pwm 周期 nanoseconds - uint32_t number; // pwm 连续个数 - uint8_t polarity; // Polarity - // ------------------- | -------------- - // PWM_NORMAL_POLARITY | Normal polarity - // PWM_INVERTED_POLARITY | Inverted polarity - // - uint8_t status; // 运行状态 - // ------------------ | ----------------- - // PWM_DISABLE_STATUS | Disabled - // PWM_ENABLE_STATUS | Enabled - }; - ``` - - -- **【重要】** PwmDev成员回调函数结构体PwmMethod的实例化,其他成员在Init函数中初始化 - - ```c - // pwm_hi35xx.c 中的示例:钩子函数的填充 - struct PwmMethod g_pwmOps = { - .setConfig = HiPwmSetConfig,//配置属性 - }; - ``` - -- **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 |初始化失败| - > - > **函数说明:** - > 初始化自定义结构体对象,初始化PwmDev成员,调用核心层PwmDeviceAdd函数。 - - ```c - //此处bind函数为空函数,可与init函数结合,也可根据厂商需要实现相关操作 - static int32_t HdfPwmBind(struct HdfDeviceObject *obj) - { - (void)obj; - return HDF_SUCCESS; - } - - static int32_t HdfPwmInit(struct HdfDeviceObject *obj) - { - int ret; - struct HiPwm *hp = NULL; - ... - hp = (struct HiPwm *)OsalMemCalloc(sizeof(*hp)); - ... - ret = HiPwmProbe(hp, obj); //【必要】实现见下 - ... - return ret; - } - - static int32_t HiPwmProbe(struct HiPwm *hp, struct HdfDeviceObject *obj) - { - uint32_t tmp; - struct DeviceResourceIface *iface = NULL; - - iface = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);//初始化自定义结构体HiPwm - ... - - hp->reg = (struct HiPwmRegs *)hp->base; //初始化自定义结构体HiPwm - hp->supportPolarity = false; //初始化自定义结构体HiPwm - hp->dev.method = &g_pwmOps; //PwmMethod的实例化对象的挂载 - hp->dev.cfg.duty = PWM_DEFAULT_DUTY_CYCLE; //初始化PwmDev - hp->dev.cfg.period = PWM_DEFAULT_PERIOD; //初始化PwmDev - hp->dev.cfg.polarity = PWM_DEFAULT_POLARITY; //初始化PwmDev - hp->dev.cfg.status = PWM_DISABLE_STATUS; //初始化PwmDev - hp->dev.cfg.number = 0; //初始化PwmDev - hp->dev.busy = false; //初始化PwmDev - if (PwmDeviceAdd(obj, &(hp->dev)) != HDF_SUCCESS) {//【重要】调用核心层函数,初始化hp->dev 的设备和服务 - OsalIoUnmap((void *)hp->base); - return HDF_FAILURE; - } - return HDF_SUCCESS; - } - ``` - -- **Release 函数参考** - - > **入参:** - > HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息 - > - > **返回值:** - > 无 - > - > **函数说明:** - > 释放内存和删除控制器,该函数需要在驱动入口结构体中赋值给 Release 接口, 当HDF框架调用Init函数初始化驱动失败时,可以调用 Release 释放驱动资源。 - - ```c - static void HdfPwmRelease(struct HdfDeviceObject *obj) - { - struct HiPwm *hp = NULL; - ... - hp = (struct HiPwm *)obj->service;//这里有HdfDeviceObject到HiPwm的强制转化 - ... - PwmDeviceRemove(obj, &(hp->dev));//【必要】调用核心层函数,释放PwmDev的设备和服务,这里有HiPwm到PwmDev的强制转化 - HiPwmRemove(hp); //释放HiPwm - } - ``` \ No newline at end of file +# PWM + +- [概述](#section1591602238164144) +- [接口说明](#section752964871810) +- [开发步骤](#section967396342164144) +- [开发实例](#section1883877829164144) + +## 概述 + +PWM(Pulse Width Modulator)即脉冲宽度调节器,在HDF框架中,PWM的接口适配模式采用独立服务模式,在这种模式下,每一个设备对象会独立发布一个设备服务来处理外部访问,设备管理器收到API的访问请求之后,通过提取该请求的参数,达到调用实际设备对象的相应内部方法的目的。独立服务模式可以直接借助HDFDeviceManager的服务管理能力,但需要为每个设备单独配置设备节点,增加内存占用。 + +**图 1** PWM独立服务模式结构图 +![](figures/PWM独立服务模式结构图.png "PWM独立服务模式结构图") + +## 接口说明 + +PwmMethod定义: + +``` +struct PwmMethod { + int32_t (*setConfig)(struct PwmDev *pwm, struct PwmConfig *config); + int32_t (*open)(struct PwmDev *pwm); + int32_t (*close)(struct PwmDev *pwm); +}; +``` + +**表 1** PwmMethod结构体成员的回调函数功能说明 + + + + + + + + + + + + + + + + + + + + + + + + +

成员函数

+

入参

+

返回值

+

功能

+

setConfig

+

pwm: 结构体指针,核心层PWM控制器;

+

config: 结构体指针,属性传入值;

+

HDF_STATUS相关状态

+

配置属性

+

open

+

pwm: 结构体指针,核心层PWM控制器;

+

HDF_STATUS相关状态

+

打开设备

+

close

+

pwm: 结构体指针,核心层PWM控制器;

+

HDF_STATUS相关状态

+

关闭设备

+
+ +## 开发步骤 + +PWM模块适配HDF框架的三个环节是配置属性文件,实例化驱动入口,以及填充核心层接口函数。 + +1. **实例化驱动入口:** + - 实例化HdfDriverEntry结构体成员。 + - 调用HDF\_INIT将HdfDriverEntry实例化对象注册到HDF框架中。 + +2. **配置属性文件:** + - 在device\_info.hcs文件中添加deviceNode描述。 + - 【可选】添加pwm\_config.hcs器件属性文件。 + +3. **实例化PWM控制器对象:** + - 初始化PwmDev成员。 + - 实例化PwmDev成员PwmMethod。 + + >![](../public_sys-resources/icon-note.gif) **说明:** + >实例化PwmDev成员PwmMethod,其定义和成员说明见[接口说明](#section752964871810)。 + + +4. **驱动调试:** + + 【可选】针对新增驱动程序,建议验证驱动基本功能,例如PWM控制状态,中断响应情况等。 + + +## 开发实例 + +下方将以pwm\_hi35xx.c为示例,展示需要厂商提供哪些内容来完整实现设备功能。 + +1. 驱动开发首先需要实例化驱动入口,驱动入口必须为HdfDriverEntry(在 hdf\_device\_desc.h 中定义)类型的全局变量,且moduleName要和device\_info.hcs中保持一致。HDF框架会将所有加载的驱动的HdfDriverEntry对象首地址汇总,形成一个类似数组的段地址空间,方便上层调用。 + + 一般在加载驱动时HDF会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。 + + PWM驱动入口参考 + + ``` + struct HdfDriverEntry g_hdfPwm = { + .moduleVersion = 1, + .moduleName = "HDF_PLATFORM_PWM",//【必要 且与 HCS文件中里面的moduleName匹配】 + .Bind = HdfPwmBind, + .Init = HdfPwmInit, + .Release = HdfPwmRelease, + }; + //调用HDF_INIT将驱动入口注册到HDF框架中 + HDF_INIT(g_hdfPwm); + ``` + +2. 完成驱动入口注册之后,下一步请在device\_info.hcs文件中添加deviceNode信息,并在 pwm\_config.hcs 中配置器件属性。deviceNode信息与驱动入口注册相关,器件属性值与核心层PwmDev成员的默认值或限制范围有密切关系。 如有更多个器件信息,则需要在device\_info文件增加deviceNode信息,以及在pwm\_config文件中增加对应的器件属性**。** + - device\_info.hcs 配置参考。 + + ``` + root { + device_info { + platform :: host { + hostName = "platform_host"; + priority = 50; + device_pwm :: device {//为每一个 pwm 控制器配置一个HDF设备节点,存在多个时【必须】添加,否则不用 + device0 :: deviceNode { + policy = 1; // 等于1,向内核态发布服务 + priority = 80; // 驱动启动优先级 + permission = 0644;// 驱动创建设备节点权限 + moduleName = "HDF_PLATFORM_PWM"; //【必要】用于指定驱动名称,需要与期望的驱动Entry中的moduleName一致; + serviceName = "HDF_PLATFORM_PWM_0";//【必要且唯一】驱动对外发布服务的名称 + deviceMatchAttr = "hisilicon_hi35xx_pwm_0";//【必要】用于配置控制器私有数据,要与 pwm_config.hcs 中对应 + // 控制器保持一致,具体的控制器信息在 pwm_config.hcs 中 + } + device1 :: deviceNode { + policy = 1; + priority = 80; + permission = 0644; + moduleName = "HDF_PLATFORM_PWM"; + serviceName = "HDF_PLATFORM_PWM_1"; + deviceMatchAttr = "hisilicon_hi35xx_pwm_1"; + } + } + } + } + } + ``` + + - pwm\_config.hcs 配置参考。 + + ``` + root { + platform { + pwm_config { + template pwm_device { //【必要】模板配置,继承该模板的节点如果使用模板中的默认值,则节点字段可以缺省 + serviceName = ""; + match_attr = ""; + num = 0; //【必要】设备号 + base = 0x12070000; //【必要】地址映射需要 + } + device_0x12070000 :: pwm_device { + match_attr = "hisilicon_hi35xx_pwm_0";//【必要】需要和device_info.hcs中的deviceMatchAttr值一致 + } + device_0x12070020 :: pwm_device { //存在多个设备时【必须】添加,否则不用 + match_attr = "hisilicon_hi35xx_pwm_1"; + num = 1; + base = 0x12070020; //【必要】地址映射需要 + } + } + } + } + ``` + +3. 完成驱动入口注册之后,最后一步就是以核心层PwmDev对象的初始化为核心,包括厂商自定义结构体(传递参数和数据),实例化PwmDev成员PwmMethod(让用户可以通过接口来调用驱动底层函数),实现HdfDriverEntry成员函数(Bind,Init,Release)。 + - 自定义结构体参考。 + + 从驱动的角度看,自定义结构体是参数和数据的载体,而且pwm\_config.hcs文件中的数值会被HDF读入通过DeviceResourceIface来初始化结构体成员,一些重要数值也会传递给核心层对象,例如设备号等。 + + ``` + struct HiPwm { + struct PwmDev dev; //【必要】 核心层结构体 + volatile unsigned char *base; + struct HiPwmRegs *reg; // 设备属性结构体,可自定义 + bool supportPolarity; + }; + + // PwmDev是核心层控制器结构体,其中的成员在Init函数中会被赋值 + struct PwmDev { + struct IDeviceIoService service; + struct HdfDeviceObject *device; + struct PwmConfig cfg; //属性结构体,相关定义见下 + struct PwmMethod *method; //钩子函数模板 + bool busy; + uint32_t num; //设备号 + OsalSpinlock lock; + void *priv; //私有数据,一般存储自定义结构体首地址,方便调用 + }; + struct PwmConfig { + uint32_t duty; // 占空时间 nanoseconds + uint32_t period; // pwm 周期 nanoseconds + uint32_t number; // pwm 连续个数 + uint8_t polarity; // Polarity + // ------------------- | -------------- + // PWM_NORMAL_POLARITY | Normal polarity + // PWM_INVERTED_POLARITY | Inverted polarity + // + uint8_t status; // 运行状态 + // ------------------ | ----------------- + // PWM_DISABLE_STATUS | Disabled + // PWM_ENABLE_STATUS | Enabled + }; + ``` + + - PwmDev成员回调函数结构体PwmMethod的实例化,其他成员在Init函数中初始化。 + + ``` + // pwm_hi35xx.c 中的示例:钩子函数的填充 + struct PwmMethod g_pwmOps = { + .setConfig = HiPwmSetConfig,//配置属性 + }; + ``` + + - 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

+

初始化失败

+
+ + 函数说明: + + 初始化自定义结构体对象,初始化PwmDev成员,调用核心层PwmDeviceAdd函数。 + + ``` + //此处bind函数为空函数,可与init函数结合,也可根据厂商需要实现相关操作 + static int32_t HdfPwmBind(struct HdfDeviceObject *obj) + { + (void)obj; + return HDF_SUCCESS; + } + + static int32_t HdfPwmInit(struct HdfDeviceObject *obj) + { + int ret; + struct HiPwm *hp = NULL; + ... + hp = (struct HiPwm *)OsalMemCalloc(sizeof(*hp)); + ... + ret = HiPwmProbe(hp, obj); //【必要】实现见下 + ... + return ret; + } + + static int32_t HiPwmProbe(struct HiPwm *hp, struct HdfDeviceObject *obj) + { + uint32_t tmp; + struct DeviceResourceIface *iface = NULL; + + iface = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);//初始化自定义结构体HiPwm + ... + + hp->reg = (struct HiPwmRegs *)hp->base; //初始化自定义结构体HiPwm + hp->supportPolarity = false; //初始化自定义结构体HiPwm + hp->dev.method = &g_pwmOps; //PwmMethod的实例化对象的挂载 + hp->dev.cfg.duty = PWM_DEFAULT_DUTY_CYCLE; //初始化PwmDev + hp->dev.cfg.period = PWM_DEFAULT_PERIOD; //初始化PwmDev + hp->dev.cfg.polarity = PWM_DEFAULT_POLARITY; //初始化PwmDev + hp->dev.cfg.status = PWM_DISABLE_STATUS; //初始化PwmDev + hp->dev.cfg.number = 0; //初始化PwmDev + hp->dev.busy = false; //初始化PwmDev + if (PwmDeviceAdd(obj, &(hp->dev)) != HDF_SUCCESS) {//【重要】调用核心层函数,初始化hp->dev 的设备和服务 + OsalIoUnmap((void *)hp->base); + return HDF_FAILURE; + } + return HDF_SUCCESS; + } + ``` + + - Release 函数参考 + + 入参: + + HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息。 + + 返回值: + + 无。 + + 函数说明: + + 释放内存和删除控制器,该函数需要在驱动入口结构体中赋值给 Release 接口, 当HDF框架调用Init函数初始化驱动失败时,可以调用 Release 释放驱动资源。 + + ``` + static void HdfPwmRelease(struct HdfDeviceObject *obj) + { + struct HiPwm *hp = NULL; + ... + hp = (struct HiPwm *)obj->service;//这里有HdfDeviceObject到HiPwm的强制转化 + ... + PwmDeviceRemove(obj, &(hp->dev));//【必要】调用核心层函数,释放PwmDev的设备和服务,这里有HiPwm到PwmDev的强制转化 + HiPwmRemove(hp); //释放HiPwm + } + ``` + + + 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 fb55001feb78e4e003f25a829f51539e4893d310..521a9ceefe94cfbb6dfb3870867b800b68fbdcb0 100644 --- a/zh-cn/device-dev/driver/driver-platform-rtc-des.md +++ b/zh-cn/device-dev/driver/driver-platform-rtc-des.md @@ -1,8 +1,7 @@ -# RTC +# RTC - [概述](#section104842041574) - - [接口说明](#section3373340142215) - +- [接口说明](#section20331159102519) - [使用指导](#section20636145604113) - [使用流程](#section16919828134215) - [创建RTC设备句柄](#section1131212144310) @@ -16,7 +15,7 @@ RTC\(real-time clock\)为操作系统中的实时时钟设备,为操作系统提供精准的实时时间和定时报警功能。当设备下电后,通过外置电池供电,RTC继续记录操作系统时间;设备上电后,RTC提供实时时钟给操作系统,确保断电后系统时间的连续性。 -### 接口说明 +## 接口说明 **表 1** RTC设备API接口功能介绍 @@ -116,12 +115,10 @@ RTC\(real-time clock\)为操作系统中的实时时钟设备,为操作系统 在操作系统启动过程中,驱动管理模块根据配置文件加载RTC驱动,RTC驱动会检测RTC器件并初始化驱动。 -使用RTC设备的一般流程如[图1](#fig166181128151112)所示。 - -**图 1** RTC设备使用流程图 - +使用RTC设备的一般流程如[图1](#fig1610020107333)所示。 -![](figure/zh-cn_image_0000001123675706.png) +**图 1** RTC设备使用流程图 +![](figures/RTC设备使用流程图.png "RTC设备使用流程图") ### 创建RTC设备句柄 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 ed31512235c1824e98cc594ede3027bdd0aca0c0..6a72063974617e607f0f69dd8fdf7888e434bf4c 100755 --- a/zh-cn/device-dev/driver/driver-platform-rtc-develop.md +++ b/zh-cn/device-dev/driver/driver-platform-rtc-develop.md @@ -1,295 +1,461 @@ -# RTC - -- [概述](#1) -- [开发步骤](#2) -- [开发实例](#3) - -## 概述 - -RTC(real-time clock)为操作系统中的实时时钟设备,在HDF框架中,RTC的接口适配模式采用独立服务模式,在这种模式下,每一个设备对象会独立发布一个设备服务来处理外部访问,设备管理器收到API的访问请求之后,通过提取该请求的参数,达到调用实际设备对象的相应内部方法的目的。 - -独立服务模式可以直接借助HDFDeviceManager的服务管理能力,但需要为每个设备单独配置设备节点,增加内存占用。 - -图 1 独立服务模式结构图 -![image1](figure/独立服务模式.png) - -## 开发步骤 - -RTC模块适配HDF框架的三个环节是配置属性文件,实例化驱动入口,以及填充核心层接口函数。 - - -1. **实例化驱动入口:** - - 实例化HdfDriverEntry结构体成员。 - - 调用HDF_INIT将HdfDriverEntry实例化对象注册到HDF框架中。 - -2. **配置属性文件:** - - - 在device_info.hcs文件中添加deviceNode描述。 - - 【可选】添加rtc_config.hcs器件属性文件。 - -3. **实例化RTC控制器对象:** - - - 初始化RtcHost成员。 - - 实例化RtcHost成员RtcMethod,其定义和成员说明见下 - -4. **驱动调试:** - - 【可选】针对新增驱动程序,建议验证驱动基本功能,例如RTC控制状态,中断响应情况等。 - -> ![](../public_sys-resources/icon-note.gif) **说明:** -> -> RtcMethod定义 -> -> ```c -> struct RtcMethod { -> int32_t (*ReadTime)(struct RtcHost *host, struct RtcTime *time); -> int32_t (*WriteTime)(struct RtcHost *host, const struct RtcTime *time); -> int32_t (*ReadAlarm)(struct RtcHost *host, enum RtcAlarmIndex alarmIndex, struct RtcTime *time); -> int32_t (*WriteAlarm)(struct RtcHost *host, enum RtcAlarmIndex alarmIndex, const struct RtcTime *time); -> int32_t (*RegisterAlarmCallback)(struct RtcHost *host, enum RtcAlarmIndex alarmIndex, RtcAlarmCallback cb); -> int32_t (*AlarmInterruptEnable)(struct RtcHost *host, enum RtcAlarmIndex alarmIndex, uint8_t enable); -> int32_t (*GetFreq)(struct RtcHost *host, uint32_t *freq); -> int32_t (*SetFreq)(struct RtcHost *host, uint32_t freq); -> int32_t (*Reset)(struct RtcHost *host); -> int32_t (*ReadReg)(struct RtcHost *host, uint8_t usrDefIndex, uint8_t *value); -> int32_t (*WriteReg)(struct RtcHost *host, uint8_t usrDefIndex, uint8_t value); -> }; -> ``` -> -> 表1 RtcMethod结构体成员的回调函数功能说明 -> -> |函数|入参|出参|返回值|功能| -> |-|-|-|-|-| -> |ReadTime |**host**: 结构体指针,核心层RTC控制器 ; |**time**: 结构体指针,
传出的时间值; |HDF_STATUS相关状态| 读RTC时间信息 | -> |WriteTime |**host**: 结构体指针,核心层RTC控制器 ;
**time**: 结构体指针,时间传入值; |无 |HDF_STATUS相关状态| 写RTC时间信息(包括毫秒~年) | -> |ReadAlarm |**host**: 结构体指针,核心层RTC控制器 ;
**alarmIndex**: 枚举值,闹钟报警索引 ;|**time**: 结构体指针,
传出的时间值;|HDF_STATUS相关状态| 读RTC报警时间信息 | -> |WriteAlarm |**host**: 结构体指针,核心层RTC控制器 ;
**alarmIndex**: 枚举值,闹钟报警索引 ;
**time**: 结构体指针,时间传入值;|无|HDF_STATUS相关状态| 写RTC报警时间信息 | -> |RegisterAlarmCallback|**host**: 结构体指针,核心层RTC控制器 ;
**alarmIndex**: 枚举值,闹钟报警索引 ;
**cb**:函数指针,回调函数; |无|HDF_STATUS相关状态| 注册报警超时回调函数| -> |AlarmInterruptEnable |**host**: 结构体指针,核心层RTC控制器 ;
**alarmIndex**: 枚举值,闹钟报警索引 ;
**enable**: 布尔值,控制报警; |无|HDF_STATUS相关状态| 使能/去使能RTC报警中断 | -> |GetFreq |**host**: 结构体指针,核心层RTC控制器 ; |**freq**: uint32_t指针,
传出的频率值;|HDF_STATUS相关状态| 读RTC外接晶振频率 | -> |SetFreq |**host**: 结构体指针,核心层RTC控制器 ;
**freq**: uint32_t,频率传入值; |无|HDF_STATUS相关状态| 配置RTC外接晶振频率 | -> |Reset |**host**: 结构体指针,核心层RTC控制器 ; |无|HDF_STATUS相关状态| RTC复位 | -> |ReadReg |**host**: 结构体指针,核心层RTC控制器 ;
**usrDefIndex**: 结构体,用户自定义寄存器索引; |**value**: uint8_t指针,
传出的寄存器值;|HDF_STATUS相关状态| 按照用户定义的寄存器索引,
读取对应的寄存器配置,
一个索引对应一字节的配置值 | -> |WriteReg |**host**: 结构体指针,核心层RTC控制器 ;
**usrDefIndex**: 结构体,用户自定义寄存器索引;
**value**: uint8_t,寄存器传入值; |无|HDF_STATUS相关状态| 按照用户定义的寄存器索引,
设置对应的寄存器配置,
一个索引对应一字节的配置值| - -## 开发实例 - -下方将以rtc_hi35xx.c为示例,展示需要厂商提供哪些内容来完整实现设备功能。 - -1. 驱动开发首先需要实例化驱动入口,驱动入口必须为HdfDriverEntry(在 hdf_device_desc.h 中定义)类型的全局变量,且moduleName要和device_info.hcs中保持一致。HDF框架会将所有加载的驱动的HdfDriverEntry对象首地址汇总,形成一个类似数组的段地址空间,方便上层调用。 - - 一般在加载驱动时HDF会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。 - -- RTC驱动入口参考 - - ```c - struct HdfDriverEntry g_rtcDriverEntry = { - .moduleVersion = 1, - .Bind = HiRtcBind, //见Bind参考 - .Init = HiRtcInit, //见Init参考 - .Release = HiRtcRelease, //见Release参考 - .moduleName = "HDF_PLATFORM_RTC",//【必要】且与 HCS 里面的名字匹配 - }; - //调用HDF_INIT将驱动入口注册到HDF框架中 - HDF_INIT(g_rtcDriverEntry); - ``` - -2. 完成驱动入口注册之后,下一步请在device_info.hcs文件中添加deviceNode信息,并在 rtc_config.hcs 中配置器件属性。deviceNode信息与驱动入口注册相关,器件属性值与核心层RtcHost成员的默认值或限制范围有密切关系。 - - **本例只有一个RTC控制器,如有多个器件信息,则需要在device_info文件增加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 匹配 - } - } - } - } - } - ``` - -- 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; - } - } - } - } - ``` - -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; //互斥锁 - }; - - // RtcHost是核心层控制器结构体,其中的成员在Init函数中会被赋值 - struct RtcHost { - struct IDeviceIoService service; - struct HdfDeviceObject *device; - struct RtcMethod *method; - void *data; - }; - ``` - -- **【重要】** RtcHost成员回调函数结构体RtcMethod的实例化,其他成员在Init函数中初始化 - - ```c - // rtc_hi35xx.c 中的示例:钩子函数的填充 - static struct RtcMethod g_method = { - .ReadTime = HiRtcReadTime, - .WriteTime = HiRtcWriteTime, - .ReadAlarm = HiReadAlarm, - .WriteAlarm = HiWriteAlarm, - .RegisterAlarmCallback = HiRegisterAlarmCallback, - .AlarmInterruptEnable = HiAlarmInterruptEnable, - .GetFreq = HiGetFreq, - .SetFreq = HiSetFreq, - .Reset = HiReset, - .ReadReg = HiReadReg, - .WriteReg = HiWriteReg, - }; - ``` - - -- **Bind 函数参考** - - > **入参:** - > 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 |初始化失败| - > - > **函数说明:** - > 关联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; - } - ``` - - -- **Init函数参考** - - > **入参:** - > HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息 - > - > **返回值:** - > HDF_STATUS相关状态 - > - > **函数说明:** - > 初始化自定义结构体对象,初始化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 提供参数,...函数内部处理失败后内存释放等操作 - 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; - } - ``` - -- **Release 函数参考** - - > **入参:** - > HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息 - > - > **返回值:** - > 无 - > - > **函数说明:** - > 释放内存和删除控制器,该函数需要在驱动入口结构体中赋值给 Release 接口, 当HDF框架调用Init函数初始化驱动失败时,可以调用 Release 释放驱动资源。所有强制转换获取相应对象的操作**前提**是在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的强制转化 - if (rtcInfo != NULL) { - HiRtcSwExit(rtcInfo); - OsalMemFree(rtcInfo); //释放RtcConfigInfo - host->data = NULL; - } - RtcHostDestroy(host); //释放RtcHost - } - ``` - +# RTC + +- [概述](#section509989381142407) +- [接口说明](#section752964871810) +- [开发步骤](#section1784450860142407) +- [开发实例](#section1594883301142407) + +## 概述 + +RTC\(real-time clock\)为操作系统中的实时时钟设备,在HDF框架中,RTC的接口适配模式采用独立服务模式,在这种模式下,每一个设备对象会独立发布一个设备服务来处理外部访问,设备管理器收到API的访问请求之后,通过提取该请求的参数,达到调用实际设备对象的相应内部方法的目的。独立服务模式可以直接借助HDFDeviceManager的服务管理能力,但需要为每个设备单独配置设备节点,增加内存占用。 + +**图 1** RTC独立服务模式结构图 +![](figures/RTC独立服务模式结构图.png "RTC独立服务模式结构图") + +## 接口说明 + +RtcMethod定义: + +``` +struct RtcMethod { + int32_t (*ReadTime)(struct RtcHost *host, struct RtcTime *time); + int32_t (*WriteTime)(struct RtcHost *host, const struct RtcTime *time); + int32_t (*ReadAlarm)(struct RtcHost *host, enum RtcAlarmIndex alarmIndex, struct RtcTime *time); + int32_t (*WriteAlarm)(struct RtcHost *host, enum RtcAlarmIndex alarmIndex, const struct RtcTime *time); + int32_t (*RegisterAlarmCallback)(struct RtcHost *host, enum RtcAlarmIndex alarmIndex, RtcAlarmCallback cb); + int32_t (*AlarmInterruptEnable)(struct RtcHost *host, enum RtcAlarmIndex alarmIndex, uint8_t enable); + int32_t (*GetFreq)(struct RtcHost *host, uint32_t *freq); + int32_t (*SetFreq)(struct RtcHost *host, uint32_t freq); + int32_t (*Reset)(struct RtcHost *host); + int32_t (*ReadReg)(struct RtcHost *host, uint8_t usrDefIndex, uint8_t *value); + int32_t (*WriteReg)(struct RtcHost *host, uint8_t usrDefIndex, uint8_t value); +}; +``` + +**表 1** RtcMethod结构体成员的回调函数功能说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

函数

+

入参

+

出参

+

返回值

+

功能

+

ReadTime

+

host: 结构体指针,核心层RTC控制器 ;

+

time: 结构体指针,传出的时间值;

+

HDF_STATUS相关状态

+

读RTC时间信息

+

WriteTime

+

host: 结构体指针,核心层RTC控制器 ;time: 结构体指针,时间传入值;

+

+

HDF_STATUS相关状态

+

写RTC时间信息(包括毫秒~年)

+

ReadAlarm

+

host: 结构体指针,核心层RTC控制器 ;alarmIndex: 枚举值,闹钟报警索引 ;

+

time: 结构体指针,传出的时间值;

+

HDF_STATUS相关状态

+

读RTC报警时间信息

+

WriteAlarm

+

host: 结构体指针,核心层RTC控制器 ;alarmIndex: 枚举值,闹钟报警索引 ;time: 结构体指针,时间传入值;

+

+

HDF_STATUS相关状态

+

写RTC报警时间信息

+

RegisterAlarmCallback

+

host: 结构体指针,核心层RTC控制器 ;alarmIndex: 枚举值,闹钟报警索引 ;cb:函数指针,回调函数;

+

+

HDF_STATUS相关状态

+

注册报警超时回调函数

+

AlarmInterruptEnable

+

host: 结构体指针,核心层RTC控制器 ;alarmIndex: 枚举值,闹钟报警索引 ;enable: 布尔值,控制报警;

+

+

HDF_STATUS相关状态

+

使能/去使能RTC报警中断

+

GetFreq

+

host: 结构体指针,核心层RTC控制器 ;

+

freq: uint32_t指针,传出的频率值;

+

HDF_STATUS相关状态

+

读RTC外接晶振频率

+

SetFreq

+

host: 结构体指针,核心层RTC控制器 ;freq: uint32_t,频率传入值;

+

+

HDF_STATUS相关状态

+

配置RTC外接晶振频率

+

Reset

+

host: 结构体指针,核心层RTC控制器 ;

+

+

HDF_STATUS相关状态

+

RTC复位

+

ReadReg

+

host: 结构体指针,核心层RTC控制器 ;usrDefIndex: 结构体,用户自定义寄存器索引;

+

value: uint8_t指针,传出的寄存器值;

+

HDF_STATUS相关状态

+

按照用户定义的寄存器索引,读取对应的寄存器配置,一个索引对应一字节的配置值

+

WriteReg

+

host: 结构体指针,核心层RTC控制器 ;usrDefIndex: 结构体,用户自定义寄存器索引;value: uint8_t,寄存器传入值;

+

+

HDF_STATUS相关状态

+

按照用户定义的寄存器索引,设置对应的寄存器配置,一个索引对应一字节的配置值

+
+ +## 开发步骤 + +RTC模块适配HDF框架的三个环节是配置属性文件,实例化驱动入口,以及填充核心层接口函数。 + +1. **实例化驱动入口:** + - 实例化HdfDriverEntry结构体成员。 + - 调用HDF\_INIT将HdfDriverEntry实例化对象注册到HDF框架中。 + +2. **配置属性文件:** + - 在device\_info.hcs文件中添加deviceNode描述。 + - 【可选】添加rtc\_config.hcs器件属性文件。 + +3. **实例化RTC控制器对象:** + - 初始化RtcHost成员。 + - 实例化RtcHost成员RtcMethod。 + + >![](../public_sys-resources/icon-note.gif) **说明:** + >实例化RtcHost成员RtcMethod,其定义和成员说明见[接口说明](#section752964871810)。 + + +4. **驱动调试:** + + 【可选】针对新增驱动程序,建议验证驱动基本功能,例如RTC控制状态,中断响应情况等。 + + +## 开发实例 + +下方将以rtc\_hi35xx.c为示例,展示需要厂商提供哪些内容来完整实现设备功能。 + +1. 驱动开发首先需要实例化驱动入口,驱动入口必须为HdfDriverEntry(在 hdf\_device\_desc.h 中定义)类型的全局变量,且moduleName要和device\_info.hcs中保持一致。HDF框架会将所有加载的驱动的HdfDriverEntry对象首地址汇总,形成一个类似数组的段地址空间,方便上层调用。 + + 一般在加载驱动时HDF会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。 + + RTC驱动入口参考: + + ``` + struct HdfDriverEntry g_rtcDriverEntry = { + .moduleVersion = 1, + .Bind = HiRtcBind, //见Bind参考 + .Init = HiRtcInit, //见Init参考 + .Release = HiRtcRelease, //见Release参考 + .moduleName = "HDF_PLATFORM_RTC",//【必要】且与 HCS 里面的名字匹配 + }; + //调用HDF_INIT将驱动入口注册到HDF框架中 + HDF_INIT(g_rtcDriverEntry); + ``` + +2. 完成驱动入口注册之后,下一步请在device\_info.hcs文件中添加deviceNode信息,并在 rtc\_config.hcs 中配置器件属性。deviceNode信息与驱动入口注册相关,器件属性值与核心层RtcHost成员的默认值或限制范围有密切关系。 + + 本例只有一个RTC控制器,如有多个器件信息,则需要在device\_info文件增加deviceNode信息,以及在rtc\_config文件中增加对应的器件属性。 + + - device\_info.hcs 配置参考。 + + ``` + 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 匹配 + } + } + } + } + } + ``` + + - rtc\_config.hcs 配置参考。 + + ``` + 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; + } + } + } + } + ``` + +3. 完成驱动入口注册之后,最后一步就是以核心层RtcHost对象的初始化为核心,包括厂商自定义结构体(传递参数和数据),实例化RtcHost成员RtcMethod(让用户可以通过接口来调用驱动底层函数),实现HdfDriverEntry成员函数(Bind,Init,Release)。 + - 自定义结构体参考。 + + 从驱动的角度看,自定义结构体是参数和数据的载体,而且rtc\_config.hcs文件中的数值会被HDF读入通过DeviceResourceIface来初始化结构体成员。 + + ``` + 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; //互斥锁 + }; + + // RtcHost是核心层控制器结构体,其中的成员在Init函数中会被赋值 + struct RtcHost { + struct IDeviceIoService service; + struct HdfDeviceObject *device; + struct RtcMethod *method; + void *data; + }; + ``` + + - RtcHost成员回调函数结构体RtcMethod的实例化,其他成员在Init函数中初始化。 + + ``` + // rtc_hi35xx.c 中的示例:钩子函数的填充 + static struct RtcMethod g_method = { + .ReadTime = HiRtcReadTime, + .WriteTime = HiRtcWriteTime, + .ReadAlarm = HiReadAlarm, + .WriteAlarm = HiWriteAlarm, + .RegisterAlarmCallback = HiRegisterAlarmCallback, + .AlarmInterruptEnable = HiAlarmInterruptEnable, + .GetFreq = HiGetFreq, + .SetFreq = HiSetFreq, + .Reset = HiReset, + .ReadReg = HiReadReg, + .WriteReg = HiWriteReg, + }; + ``` + + - Bind 函数参考 + + 入参: + + HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息。 + + 返回值: + + HDF\_STATUS相关状态 (下表为部分展示,如需使用其他状态,可见//drivers/framework/include/utils/hdf\_base.h中HDF\_STATUS 定义)。 + + **表 2** Bind 函数入参及返回值对照表 + + + + + + + + + + + + + + + + + + + + + + + + + +

状态(值)

+

问题描述

+

HDF_ERR_INVALID_OBJECT

+

控制器对象非法

+

HDF_ERR_MALLOC_FAIL

+

内存分配失败

+

HDF_ERR_INVALID_PARAM

+

参数非法

+

HDF_ERR_IO

+

I/O 错误

+

HDF_SUCCESS

+

初始化成功

+

HDF_FAILURE

+

初始化失败

+
+ + 函数说明: + + 关联HdfDeviceObject对象和RtcHost。 + + ``` + 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; + } + ``` + + - Init函数参考 + + 入参**:** + + HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息。 + + 返回值**:** + + HDF\_STATUS相关状态。 + + 函数说明: + + 初始化自定义结构体对象,初始化RtcHost成员。 + + ``` + 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 提供参数,...函数内部处理失败后内存释放等操作 + 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; + } + ``` + + - Release 函数参考 + + 入参**:** + + HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息。 + + 返回值**:** + + 无。 + + 函数说明: + + 释放内存和删除控制器,该函数需要在驱动入口结构体中赋值给 Release 接口, 当HDF框架调用Init函数初始化驱动失败时,可以调用 Release 释放驱动资源。所有强制转换获取相应对象的操作前提是在Init或Bind函数中具备对应赋值的操作。 + + ``` + 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的强制转化 + if (rtcInfo != NULL) { + HiRtcSwExit(rtcInfo); + OsalMemFree(rtcInfo); //释放RtcConfigInfo + host->data = NULL; + } + 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 1d85e6496ea6abc547afcdc1536b5068eb1acdbc..a3a0d13450beed13fea5e28b162d594ca2620fb9 100644 --- a/zh-cn/device-dev/driver/driver-platform-sdio-des.md +++ b/zh-cn/device-dev/driver/driver-platform-sdio-des.md @@ -1,8 +1,7 @@ -# SDIO +# SDIO - [概述](#section1155271783811) - - [接口说明](#section08064247248) - +- [接口说明](#section12601496259) - [使用指导](#section1878939192515) - [使用流程](#section1490685512255) - [打开SDIO控制器](#section10782428132616) @@ -29,14 +28,12 @@ - D0-3信号:4条数据线,其中,DAT1信号线复用为中断线,在1BIT模式下DAT0用来传输数据,在4BIT模式下DAT0-DAT3用来传输数据。 - CMD信号:用于HOST发送命令和DEVICE回复响应。 - **图 1** SDIO的HOST-DEVICE连接示意图 - - - ![](figure/zh-cn_image_0000001054280608.png) + **图 1** SDIO的HOST-DEVICE连接示意图 + ![](figures/SDIO的HOST-DEVICE连接示意图.png "SDIO的HOST-DEVICE连接示意图") - SDIO接口定义了操作SDIO的通用方法集合,包括打开/关闭SDIO控制器、独占/释放HOST、使能/去使能设备、申请/释放中断、读写、获取/设置公共信息等。 -### 接口说明 +## 接口说明 **表 1** SDIO驱动API接口功能介绍 @@ -165,12 +162,10 @@ ### 使用流程 -使用SDIO的一般流程如[图2](#fig1343742311264)所示。 - -**图 2** SDIO使用流程图 - +使用SDIO的一般流程如[图2](#fig1969028202613)所示。 -![](figure/zh-cn_image_0000001123540984.png) +**图 2** SDIO使用流程图 +![](figures/SDIO使用流程图.png "SDIO使用流程图") ### 打开SDIO控制器 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 cb8883babfaef39add44768b1ed927f336be3849..1c59197f4862db914d4f55c82cbee223f47783eb 100755 --- a/zh-cn/device-dev/driver/driver-platform-sdio-develop.md +++ b/zh-cn/device-dev/driver/driver-platform-sdio-develop.md @@ -1,306 +1,532 @@ -# SDIO - -- [概述](#1) -- [开发步骤](#2) -- [开发实例](#3) - -## 概述 - -SDIO由SD卡发展而来,被统称为mmc(MultiMediaCard),相关技术差别不大,在HDF框架中, -SDIO的接口适配模式采用独立服务模式,在这种模式下,每一个设备对象会独立发布一个设备服务来处理外部访问,设备管理器收到API的访问请求之后,通过提取该请求的参数,达到调用实际设备对象的相应内部方法的目的。 - -独立服务模式可以直接借助HDFDeviceManager的服务管理能力,但需要为每个设备单独配置设备节点,增加内存占用。 - -图 1 独立服务模式结构图 -![image1](figure/独立服务模式.png) - -## 开发步骤 - -SDIO模块适配HDF框架的三个环节是配置属性文件,实例化驱动入口,以及填充核心层接口函数。 - - -1. **实例化驱动入口:** - - 实例化HdfDriverEntry结构体成员。 - - 调用HDF_INIT将HdfDriverEntry实例化对象注册到HDF框架中。 - -2. **配置属性文件:** - - - 在device_info.hcs文件中添加deviceNode描述。 - - 【可选】添加sdio_config.hcs器件属性文件。 - -3. **实例化SDIO控制器对象:** - - - 初始化SdioDevice成员。 - - 实例化SdioDevice成员SdioDeviceOps,其定义和成员说明见下 - -4. **驱动调试:** - - 【可选】针对新增驱动程序,建议验证驱动基本功能,例如SDIO控制状态,中断响应情况等。 - -> ![](../public_sys-resources/icon-note.gif) **说明:** -> -> 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); -> }; -> ``` -> -> 表1 SdioDeviceOps结构体成员的回调函数功能说明 -> -> |函数|入参|出参|返回值|功能| -> |-|-|-|-|-| -> |incrAddrReadBytes, |**dev**: 结构体指针,SDIO设备控制器;
**addr**: uint32_t,地址值;
**size**: uint32_t,大小 |**data**: uint8_t指针,传出值;|HDF_STATUS相关状态| 从指定的SDIO地址增量读取给定长度的数据 | -> |incrAddrWriteBytes, |**dev**: 结构体指针,SDIO设备控制器;
**data**: uint8_t指针,传入值;
**addr**: uint32_t,地址值;
**size**: uint32_t,大小 |无|HDF_STATUS相关状态| 将给定长度的数据增量写入指定的SDIO地址 | -> |fixedAddrReadBytes, |**dev**: 结构体指针,SDIO设备控制器;
**addr**: uint32_t,地址值;
**size**: uint32_t,大小;
**scatterLen**: uint32_t,数据长度;|**data**: uint8_t指针,传出值;|HDF_STATUS相关状态| 从固定SDIO地址读取给定长度的数据。 | -> |fixedAddrWriteBytes,|**dev**: 结构体指针,SDIO设备控制器;
**data**: uint8_t指针,传入值;
**addr**: uint32_t,地址值;
**size**: uint32_t,大小;
**scatterLen**: uint32_t,数据长度;|无|HDF_STATUS相关状态| 将给定长度的数据写入固定SDIO地址 | -> |func0ReadBytes, |**dev**: 结构体指针,SDIO设备控制器;
**addr**: uint32_t,地址值;
**size**: uint32_t,大小; |**data**: uint8_t指针,传出值;|HDF_STATUS相关状态| 从SDIO函数0的地址空间读取给定长度的数据。 | -> |func0WriteBytes, |**dev**: 结构体指针,SDIO设备控制器;
**data**: uint8_t指针,传入值;
**addr**: uint32_t,地址值;
**size**: uint32_t,大小; |无|HDF_STATUS相关状态| 将给定长度的数据写入SDIO函数0的地址空间。 | -> |setBlockSize, |**dev**: 结构体指针,SDIO设备控制器;
**blockSize**: uint32_t,Block大小 |无|HDF_STATUS相关状态| 设置block大小| -> |getCommonInfo, |**dev**: 联合体指针,SDIO设备控制器;
**infoType**: uint32_t,info类型; |**info**: 结构体指针,传出SdioFuncInfo信息;|HDF_STATUS相关状态| 获取CommonInfo,说明见下 | -> |setCommonInfo, |**dev**: 结构体指针,SDIO设备控制器;
**info**: 联合体指针,SdioFuncInfo信息传入;
**infoType**: uint32_t,info类型; |无|HDF_STATUS相关状态| 设置CommonInfo,说明见下 | -> |flushData, |**dev**: 结构体指针,SDIO设备控制器; |无|HDF_STATUS相关状态|当SDIO需要重新初始化或发生意外错误时调用的函数| -> |enableFunc, |**dev**: 结构体指针,SDIO设备控制器; |无|HDF_STATUS相关状态|使能SDIO设备 | -> |disableFunc, |**dev**: 结构体指针,SDIO设备控制器; |无|HDF_STATUS相关状态|去使能SDIO设备 | -> |claimIrq, |**dev**: 结构体指针,SDIO设备控制器;
**irqHandler**: void函数指针; |无|HDF_STATUS相关状态|注册SDIO中断 | -> |releaseIrq, |**dev**: 结构体指针,SDIO设备控制器; |无|HDF_STATUS相关状态|释放SDIO中断| -> |findFunc, |**dev**: 结构体指针,SDIO设备控制器;
**configData**: 结构体指针, SDIO函数关键信息 |无|HDF_STATUS相关状态|寻找匹配的funcNum| -> |claimHost, |**dev**: 结构体指针,SDIO设备控制器; |无|HDF_STATUS相关状态|独占HOST | -> |releaseHost, |**dev**: 结构体指针,SDIO设备控制器; |无|HDF_STATUS相关状态|释放HOST | -> -> >![](../public_sys-resources/icon-note.gif) **CommonInfo说明:** -> > 包括maxBlockNum(单个request中最大block数), maxBlockSize(单个block最大字节数), maxRequestSize(单个Request最大字节数), enTimeout(最大超时时间,毫秒), funcNum(功能编号1~7), irqCap(IRQ capabilities), (void \*)data. - -## 开发实例 - -下方将以sdio_adapter.c为示例,展示需要厂商提供哪些内容来完整实现设备功能。 - -1. 驱动开发首先需要实例化驱动入口,驱动入口必须为HdfDriverEntry(在 hdf_device_desc.h 中定义)类型的全局变量,且moduleName要和device_info.hcs中保持一致。HDF框架会将所有加载的驱动的HdfDriverEntry对象首地址汇总,形成一个类似数组的段地址空间,方便上层调用。 - - 一般在加载驱动时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匹配】 - }; - //调用HDF_INIT将驱动入口注册到HDF框架中 - HDF_INIT(g_sdioDriverEntry); - ``` - -2. 完成驱动入口注册之后,下一步请在device_info.hcs文件中添加deviceNode信息,并在 sdio_config.hcs 中配置器件属性。deviceNode信息与驱动入口注册相关,器件属性值与核心层SdioDevice成员的默认值或限制范围有密切关系。 - - **本例只有一个SDIO控制器,如有多个器件信息,则需要在device_info文件增加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中对应控制器保持一致 - } - } - } - } - } - ``` - -- 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值一致 - } - } - } - ``` - -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 - uint32_t maxRequestSize; // 单个request最大的字节数 1~2048 - uint32_t enTimeout; // 最大超时时间,单位毫秒,且不能超过一秒 - uint32_t funcNum; // 函数编号1~7 - uint32_t irqCap; // 中断能力 - void *data; // 私有数据 - } SdioFuncInfo; - - //SdioDevice是核心层控制器结构体,其中的成员在Bind函数中会被赋值 - struct SdioDevice { - struct SdDevice sd; - struct SdioDeviceOps *sdioOps; - struct SdioRegister sdioReg; - uint32_t functions; - struct SdioFunction *sdioFunc[SDIO_MAX_FUNCTION_NUMBER]; - struct SdioFunction *curFunction; - struct OsalThread thread; /* irq thread */ - struct OsalSem sem; - bool irqPending; - bool threadRunning; - }; - ``` - -- **【重要】** SdioDevice成员回调函数结构体SdioDeviceOps的实例化,其他成员在Init函数中初始化 - - ```c - static struct SdioDeviceOps g_sdioDeviceOps = { - .incrAddrReadBytes = Hi35xxLinuxSdioIncrAddrReadBytes, - .incrAddrWriteBytes = Hi35xxLinuxSdioIncrAddrWriteBytes, - .fixedAddrReadBytes = Hi35xxLinuxSdioFixedAddrReadBytes, - .fixedAddrWriteBytes = Hi35xxLinuxSdioFixedAddrWriteBytes, - .func0ReadBytes = Hi35xxLinuxSdioFunc0ReadBytes, - .func0WriteBytes = Hi35xxLinuxSdioFunc0WriteBytes, - .setBlockSize = Hi35xxLinuxSdioSetBlockSize, - .getCommonInfo = Hi35xxLinuxSdioGetCommonInfo, - .setCommonInfo = Hi35xxLinuxSdioSetCommonInfo, - .flushData = Hi35xxLinuxSdioFlushData, - .enableFunc = Hi35xxLinuxSdioEnableFunc, - .disableFunc = Hi35xxLinuxSdioDisableFunc, - .claimIrq = Hi35xxLinuxSdioClaimIrq, - .releaseIrq = Hi35xxLinuxSdioReleaseIrq, - .findFunc = Hi35xxLinuxSdioFindFunc, - .claimHost = Hi35xxLinuxSdioClaimHost, - .releaseHost = Hi35xxLinuxSdioReleaseHost, - }; - ``` - -- **Bind函数参考** - - > **入参:** - > 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 |初始化失败| - > - > **函数说明:** - > 初始化自定义结构体对象,初始化SdioCntlr成员,调用核心层SdioCntlrAdd函数,以及其他厂商自定义初始化操作 - - ```c - static int32_t Hi35xxLinuxSdioBind(struct HdfDeviceObject *obj) - { - struct MmcCntlr *cntlr = NULL; - int32_t ret; - ... - cntlr = (struct MmcCntlr *)OsalMemCalloc(sizeof(struct MmcCntlr));// 分配内存 - ... - cntlr->ops = &g_sdioCntlrOps; //【必要】struct MmcCntlrOps g_sdioCntlrOps={ - // .rescanSdioDev = Hi35xxLinuxSdioRescan,}; - cntlr->hdfDevObj = obj; //【必要】使HdfDeviceObject与MmcCntlr可以相互转化的前提 - obj->service = &cntlr->service;//【必要】使HdfDeviceObject与MmcCntlr可以相互转化的前提 - ret = Hi35xxLinuxSdioCntlrParse(cntlr, obj);//【必要】初始化cntlr 的 index, devType, 失败则 goto _ERR; - ... - ret = MmcCntlrAdd(cntlr); //【必要】调用核心层mmc_core.c的函数, 失败则 goto _ERR; - ... - ret = MmcCntlrAllocDev(cntlr, (enum MmcDevType)cntlr->devType);//【必要】调用核心层mmc_core.c的函数, 失败则 goto _ERR; - ... - - MmcDeviceAddOps(cntlr->curDev, &g_sdioDeviceOps);//【必要】调用核心层mmc_core.c的函数, 钩子函数挂载 - HDF_LOGD("Hi35xxLinuxSdioBind: Success!"); - return HDF_SUCCESS; - - _ERR: - Hi35xxLinuxSdioDeleteCntlr(cntlr); - HDF_LOGE("Hi35xxLinuxSdioBind: Fail!"); - return HDF_FAILURE; - } - ``` - - -- **Init函数参考** - - > **入参:** - > HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息 - > - > **返回值:** - > HDF_STATUS相关状态 - > - > **函数说明:** - > 无操作,可根据厂商需要添加 - - ```c - static int32_t Hi35xxLinuxSdioInit(struct HdfDeviceObject *obj) - { - (void)obj;//无操作,可根据厂商需要添加 - HDF_LOGD("Hi35xxLinuxSdioInit: Success!"); - return HDF_SUCCESS; - } - ``` - -- **Release函数参考** - - > **入参:** - > HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息 - > - > **返回值:** - > 无 - > - > **函数说明:** - > 释放内存和删除控制器,该函数需要在驱动入口结构体中赋值给 Release 接口, 当HDF框架调用Init函数初始化驱动失败时,可以调用 Release 释放驱动资源。所有强制转换获取相应对象的操作**前提**是在Bind函数中具备对应赋值的操作。 - - ```c - static void Hi35xxLinuxSdioRelease(struct HdfDeviceObject *obj) - { - if (obj == NULL) { - return; - } - Hi35xxLinuxSdioDeleteCntlr((struct MmcCntlr *)obj->service);//【必要】自定义的内存释放函数,这里有HdfDeviceObject到MmcCntlr的强制转化 - } - ``` - +# SDIO + +- [概述](#section1347805272150053) +- [接口说明](#section752964871810) +- [开发步骤](#section581179475150053) +- [开发实例](#section2112250242150053) + +## 概述 + +SDIO由SD卡发展而来,被统称为mmc(MultiMediaCard),相关技术差别不大,在HDF框架中,SDIO的接口适配模式采用独立服务模式,在这种模式下,每一个设备对象会独立发布一个设备服务来处理外部访问,设备管理器收到API的访问请求之后,通过提取该请求的参数,达到调用实际设备对象的相应内部方法的目的。独立服务模式可以直接借助HDFDeviceManager的服务管理能力,但需要为每个设备单独配置设备节点,增加内存占用。 + +**图 1** SDIO独立服务模式结构图 +![](figures/SDIO独立服务模式结构图.png "SDIO独立服务模式结构图") + +## 接口说明 + +SdioDeviceOps定义: + +``` +// 函数模板 +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); +}; +``` + +**表 1** SdioDeviceOps结构体成员的回调函数功能说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

函数

+

入参

+

出参

+

返回值

+

功能

+

incrAddrReadBytes

+

dev: 结构体指针,SDIO设备控制器;addr: uint32_t,地址值;size: uint32_t,大小

+

data: uint8_t指针,传出值;

+

HDF_STATUS相关状态

+

从指定的SDIO地址增量读取给定长度的数据

+

incrAddrWriteBytes

+

dev: 结构体指针,SDIO设备控制器;data: uint8_t指针,传入值;addr: uint32_t,地址值;size: uint32_t,大小

+

+

HDF_STATUS相关状态

+

将给定长度的数据增量写入指定的SDIO地址

+

fixedAddrReadBytes

+

dev: 结构体指针,SDIO设备控制器;addr: uint32_t,地址值;size: uint32_t,大小;scatterLen: uint32_t,数据长度;

+

data: uint8_t指针,传出值;

+

HDF_STATUS相关状态

+

从固定SDIO地址读取给定长度的数据。

+

fixedAddrWriteBytes

+

dev: 结构体指针,SDIO设备控制器;data: uint8_t指针,传入值;addr: uint32_t,地址值;size: uint32_t,大小;scatterLen: uint32_t,数据长度;

+

+

HDF_STATUS相关状态

+

将给定长度的数据写入固定SDIO地址

+

func0ReadBytes

+

dev: 结构体指针,SDIO设备控制器;addr: uint32_t,地址值;size: uint32_t,大小;

+

data: uint8_t指针,传出值;

+

HDF_STATUS相关状态

+

从SDIO函数0的地址空间读取给定长度的数据。

+

func0WriteBytes

+

dev: 结构体指针,SDIO设备控制器;data: uint8_t指针,传入值;addr: uint32_t,地址值;size: uint32_t,大小;

+

+

HDF_STATUS相关状态

+

将给定长度的数据写入SDIO函数0的地址空间。

+

setBlockSize

+

dev: 结构体指针,SDIO设备控制器;blockSize: uint32_t,Block大小

+

+

HDF_STATUS相关状态

+

设置block大小

+

getCommonInfo

+

dev: 联合体指针,SDIO设备控制器;infoType: uint32_t,info类型;

+

info: 结构体指针,传出SdioFuncInfo信息;

+

HDF_STATUS相关状态

+

获取CommonInfo,说明见下

+

setCommonInfo

+

dev: 结构体指针,SDIO设备控制器;info: 联合体指针,SdioFuncInfo信息传入;infoType: uint32_t,info类型;

+

+

HDF_STATUS相关状态

+

设置CommonInfo,说明见下

+

flushData

+

dev: 结构体指针,SDIO设备控制器;

+

+

HDF_STATUS相关状态

+

当SDIO需要重新初始化或发生意外错误时调用的函数

+

enableFunc

+

dev: 结构体指针,SDIO设备控制器;

+

+

HDF_STATUS相关状态

+

使能SDIO设备

+

disableFunc

+

dev: 结构体指针,SDIO设备控制器;

+

+

HDF_STATUS相关状态

+

去使能SDIO设备

+

claimIrq

+

dev: 结构体指针,SDIO设备控制器;irqHandler: void函数指针;

+

+

HDF_STATUS相关状态

+

注册SDIO中断

+

releaseIrq

+

dev: 结构体指针,SDIO设备控制器;

+

+

HDF_STATUS相关状态

+

释放SDIO中断

+

findFunc

+

dev: 结构体指针,SDIO设备控制器;configData: 结构体指针, SDIO函数关键信息

+

+

HDF_STATUS相关状态

+

寻找匹配的funcNum

+

claimHost

+

dev: 结构体指针,SDIO设备控制器;

+

+

HDF_STATUS相关状态

+

独占HOST

+

releaseHost

+

dev: 结构体指针,SDIO设备控制器;

+

+

HDF_STATUS相关状态

+

释放HOST

+
+ +>![](../public_sys-resources/icon-note.gif) **说明:** +>CommonInfo包括maxBlockNum\(单个request中最大block数\), maxBlockSize\(单个block最大字节数\), maxRequestSize\(单个Request最大字节数\), enTimeout\(最大超时时间,毫秒\), funcNum\(功能编号1\~7\), irqCap\(IRQ capabilities\), \(void \*\)data. + +## 开发步骤 + +SDIO模块适配HDF框架的三个环节是配置属性文件,实例化驱动入口,以及填充核心层接口函数。 + +1. **实例化驱动入口:** + - 实例化HdfDriverEntry结构体成员。 + - 调用HDF\_INIT将HdfDriverEntry实例化对象注册到HDF框架中。 + +2. **配置属性文件:** + - 在device\_info.hcs文件中添加deviceNode描述。 + - 【可选】添加sdio\_config.hcs器件属性文件。 + +3. **实例化SDIO控制器对象:** + - 初始化SdioDevice成员。 + - 实例化SdioDevice成员SdioDeviceOps。 + + >![](../public_sys-resources/icon-note.gif) **说明:** + >实例化SdioDevice成员SdioDeviceOps,其定义和成员说明见[接口说明](#section752964871810)。 + + +4. **驱动调试:** + + 【可选】针对新增驱动程序,建议验证驱动基本功能,例如SDIO控制状态,中断响应情况等。 + + +## 开发实例 + +下方将以sdio\_adapter.c为示例,展示需要厂商提供哪些内容来完整实现设备功能。 + +1. 驱动开发首先需要实例化驱动入口,驱动入口必须为HdfDriverEntry(在 hdf\_device\_desc.h 中定义)类型的全局变量,且moduleName要和device\_info.hcs中保持一致。HDF框架会将所有加载的驱动的HdfDriverEntry对象首地址汇总,形成一个类似数组的段地址空间,方便上层调用。 + + 一般在加载驱动时HDF会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。 + + SDIO 驱动入口参考: + + ``` + struct HdfDriverEntry g_sdioDriverEntry = { + .moduleVersion = 1, + .Bind = Hi35xxLinuxSdioBind, //见Bind参考 + .Init = Hi35xxLinuxSdioInit, //见Init参考 + .Release = Hi35xxLinuxSdioRelease,//见Release参考 + .moduleName = "HDF_PLATFORM_SDIO",//【必要 且与 HCS文件中里面的moduleName匹配】 + }; + //调用HDF_INIT将驱动入口注册到HDF框架中 + HDF_INIT(g_sdioDriverEntry); + ``` + +2. 完成驱动入口注册之后,下一步请在device\_info.hcs文件中添加deviceNode信息,并在 sdio\_config.hcs 中配置器件属性。deviceNode信息与驱动入口注册相关,器件属性值与核心层SdioDevice成员的默认值或限制范围有密切关系。 + + 本例只有一个SDIO控制器,如有多个器件信息,则需要在device\_info文件增加deviceNode信息,以及在sdio\_config文件中增加对应的器件属性。 + + - device\_info.hcs 配置参考: + + ``` + 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中对应控制器保持一致 + } + } + } + } + } + ``` + + - sdio\_config.hcs 配置参考: + + ``` + 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值一致 + } + } + } + ``` + +3. 完成驱动入口注册之后,最后一步就是以核心层SdioDevice对象的初始化为核心,包括厂商自定义结构体(传递参数和数据),实例化SdioDevice成员SdioDeviceOps(让用户可以通过接口来调用驱动底层函数),实现HdfDriverEntry成员函数(Bind,Init,Release)。 + - 自定义结构体参考: + + 从驱动的角度看,自定义结构体是参数和数据的载体,而且sdio\_config.hcs文件中的数值会被HDF读入通过DeviceResourceIface来初始化结构体成员,一些重要数值也会传递给核心层对象。 + + ``` + typedef struct { + uint32_t maxBlockNum; // 单个request最大的block个数 + uint32_t maxBlockSize; // 单个block最大的字节数1~2048 + uint32_t maxRequestSize; // 单个request最大的字节数 1~2048 + uint32_t enTimeout; // 最大超时时间,单位毫秒,且不能超过一秒 + uint32_t funcNum; // 函数编号1~7 + uint32_t irqCap; // 中断能力 + void *data; // 私有数据 + } SdioFuncInfo; + + //SdioDevice是核心层控制器结构体,其中的成员在Bind函数中会被赋值 + struct SdioDevice { + struct SdDevice sd; + struct SdioDeviceOps *sdioOps; + struct SdioRegister sdioReg; + uint32_t functions; + struct SdioFunction *sdioFunc[SDIO_MAX_FUNCTION_NUMBER]; + struct SdioFunction *curFunction; + struct OsalThread thread; /* irq thread */ + struct OsalSem sem; + bool irqPending; + bool threadRunning; + }; + ``` + + - SdioDevice成员回调函数结构体SdioDeviceOps的实例化,其他成员在Init函数中初始化。 + + ``` + static struct SdioDeviceOps g_sdioDeviceOps = { + .incrAddrReadBytes = Hi35xxLinuxSdioIncrAddrReadBytes, + .incrAddrWriteBytes = Hi35xxLinuxSdioIncrAddrWriteBytes, + .fixedAddrReadBytes = Hi35xxLinuxSdioFixedAddrReadBytes, + .fixedAddrWriteBytes = Hi35xxLinuxSdioFixedAddrWriteBytes, + .func0ReadBytes = Hi35xxLinuxSdioFunc0ReadBytes, + .func0WriteBytes = Hi35xxLinuxSdioFunc0WriteBytes, + .setBlockSize = Hi35xxLinuxSdioSetBlockSize, + .getCommonInfo = Hi35xxLinuxSdioGetCommonInfo, + .setCommonInfo = Hi35xxLinuxSdioSetCommonInfo, + .flushData = Hi35xxLinuxSdioFlushData, + .enableFunc = Hi35xxLinuxSdioEnableFunc, + .disableFunc = Hi35xxLinuxSdioDisableFunc, + .claimIrq = Hi35xxLinuxSdioClaimIrq, + .releaseIrq = Hi35xxLinuxSdioReleaseIrq, + .findFunc = Hi35xxLinuxSdioFindFunc, + .claimHost = Hi35xxLinuxSdioClaimHost, + .releaseHost = Hi35xxLinuxSdioReleaseHost, + }; + ``` + + - Bind函数参考 + + 入参: + + HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息。 + + 返回值: + + HDF\_STATUS相关状态 (下表为部分展示,如需使用其他状态,可见//drivers/framework/include/utils/hdf\_base.h中HDF\_STATUS 定义)。 + + **表 2** Bind函数入参及返回值 + + + + + + + + + + + + + + + + + + + + + + + + + +

状态(值)

+

问题描述

+

HDF_ERR_INVALID_OBJECT

+

控制器对象非法

+

HDF_ERR_MALLOC_FAIL

+

内存分配失败

+

HDF_ERR_INVALID_PARAM

+

参数非法

+

HDF_ERR_IO

+

I/O 错误

+

HDF_SUCCESS

+

初始化成功

+

HDF_FAILURE

+

初始化失败

+
+ + 函数说明: + + 初始化自定义结构体对象,初始化SdioCntlr成员,调用核心层SdioCntlrAdd函数,以及其他厂商自定义初始化操作。 + + ``` + static int32_t Hi35xxLinuxSdioBind(struct HdfDeviceObject *obj) + { + struct MmcCntlr *cntlr = NULL; + int32_t ret; + ... + cntlr = (struct MmcCntlr *)OsalMemCalloc(sizeof(struct MmcCntlr));// 分配内存 + ... + cntlr->ops = &g_sdioCntlrOps; //【必要】struct MmcCntlrOps g_sdioCntlrOps={ + // .rescanSdioDev = Hi35xxLinuxSdioRescan,}; + cntlr->hdfDevObj = obj; //【必要】使HdfDeviceObject与MmcCntlr可以相互转化的前提 + obj->service = &cntlr->service;//【必要】使HdfDeviceObject与MmcCntlr可以相互转化的前提 + ret = Hi35xxLinuxSdioCntlrParse(cntlr, obj);//【必要】初始化cntlr 的 index, devType, 失败则 goto _ERR; + ... + ret = MmcCntlrAdd(cntlr); //【必要】调用核心层mmc_core.c的函数, 失败则 goto _ERR; + ... + ret = MmcCntlrAllocDev(cntlr, (enum MmcDevType)cntlr->devType);//【必要】调用核心层mmc_core.c的函数, 失败则 goto _ERR; + ... + + MmcDeviceAddOps(cntlr->curDev, &g_sdioDeviceOps);//【必要】调用核心层mmc_core.c的函数, 钩子函数挂载 + HDF_LOGD("Hi35xxLinuxSdioBind: Success!"); + return HDF_SUCCESS; + + _ERR: + Hi35xxLinuxSdioDeleteCntlr(cntlr); + HDF_LOGE("Hi35xxLinuxSdioBind: Fail!"); + return HDF_FAILURE; + } + ``` + + - Init函数参考 + + 入参: + + HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息。 + + 返回值: + + HDF\_STATUS相关状态。 + + 函数说明: + + 无操作,可根据厂商需要添加。 + + ``` + static int32_t Hi35xxLinuxSdioInit(struct HdfDeviceObject *obj) + { + (void)obj;//无操作,可根据厂商需要添加 + HDF_LOGD("Hi35xxLinuxSdioInit: Success!"); + return HDF_SUCCESS; + } + ``` + + - Release函数参考 + + 入参: + + HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息。 + + 返回值: + + 无。 + + 函数说明: + + 释放内存和删除控制器,该函数需要在驱动入口结构体中赋值给 Release 接口, 当HDF框架调用Init函数初始化驱动失败时,可以调用 Release 释放驱动资源。所有强制转换获取相应对象的操作前提是在Bind函数中具备对应赋值的操作。 + + ``` + static void Hi35xxLinuxSdioRelease(struct HdfDeviceObject *obj) + { + if (obj == NULL) { + return; + } + Hi35xxLinuxSdioDeleteCntlr((struct MmcCntlr *)obj->service);//【必要】自定义的内存释放函数,这里有HdfDeviceObject到MmcCntlr的强制转化 + } + ``` + + + 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 b903ae469fc1ff91ea3a0bf0ad2713ea20e0de09..033a3b0e06d8469ad5cce3955b0b971c0a5af27a 100644 --- a/zh-cn/device-dev/driver/driver-platform-spi-des.md +++ b/zh-cn/device-dev/driver/driver-platform-spi-des.md @@ -1,8 +1,7 @@ -# SPI +# SPI - [概述](#section193356154511) - - [接口说明](#section232141411476) - +- [接口说明](#section1325964832615) - [使用指导](#section71363452477) - [使用流程](#section32846814820) - [获取SPI设备句柄](#section1927265711481) @@ -24,12 +23,10 @@ - CS – 片选,从设备使能信号,由主设备控制。 -- 一个主设备和两个从设备的连接示意图如[图1](#fig15227181812587)所示,Device A和Device B共享主设备的SCLK、MISO和MOSI三根引脚,Device A的片选CS0连接主设备的CS0,Device B的片选CS1连接主设备的CS1。 - -**图 1** SPI主从设备连接示意图。 - +- 一个主设备和两个从设备的连接示意图如[图1](#fig89085710359)所示,Device A和Device B共享主设备的SCLK、MISO和MOSI三根引脚,Device A的片选CS0连接主设备的CS0,Device B的片选CS1连接主设备的CS1。 -![](figure/zh-cn_image_0000001123742254.png) +**图 1** SPI主从设备连接示意图。 +![](figures/SPI主从设备连接示意图.png "SPI主从设备连接示意图") - SPI通信通常由主设备发起,通过以下步骤完成一次通信: @@ -54,7 +51,7 @@ >![](../public_sys-resources/icon-note.gif) **说明:** >当前只支持主机模式,不支持从机模式。 -### 接口说明 +## 接口说明 **表 1** SPI驱动API接口功能介绍 @@ -119,12 +116,10 @@ ### 使用流程 -使用SPI的一般流程如[图2](#fig23885455594)所示。 - -**图 2** SPI使用流程图 - +使用SPI的一般流程如[图2](#fig1586912310348)所示。 -![](figure/zh-cn_image_0000001123703482.png) +**图 2** SPI使用流程图 +![](figures/SPI使用流程图.png "SPI使用流程图") ### 获取SPI设备句柄 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 705791a44c4cbc25286e710cb264007dd831fc2a..30865e6ae085c5825530053318f69bde8ab8cab4 100755 --- a/zh-cn/device-dev/driver/driver-platform-spi-develop.md +++ b/zh-cn/device-dev/driver/driver-platform-spi-develop.md @@ -1,354 +1,449 @@ -# SPI - -- [概述](#1) -- [开发步骤](#2) -- [开发实例](#3) - -## 概述 - -SPI是串行外设接口(Serial Peripheral Interface)的缩写,在HDF框架中,SPI的接口适配模式采用独立服务模式,在这种模式下,每一个设备对象会独立发布一个设备服务来处理外部访问,设备管理器收到API的访问请求之后,通过提取该请求的参数,达到调用实际设备对象的相应内部方法的目的。 - -独立服务模式可以直接借助HDFDeviceManager的服务管理能力,但需要为每个设备单独配置设备节点,增加内存占用。 - -图 1 独立服务模式结构图 -![image1](figure/独立服务模式.png) - -## 开发步骤 - -SPI模块适配HDF框架的三个环节是配置属性文件,实例化驱动入口,以及实例化核心层接口函数。 - -1. **实例化驱动入口:** - - 实例化HdfDriverEntry结构体成员。 - - 调用HDF_INIT将HdfDriverEntry实例化对象注册到HDF框架中。 - -2. **配置属性文件:** - - - 在device_info.hcs文件中添加deviceNode描述。 - - 【可选】添加spi_config.hcs器件属性文件。 - -3. **实例化SPI控制器对象:** - - - 初始化SpiCntlr成员。 - - 实例化SpiCntlr成员SpiCntlrMethod,其定义和成员说明见下 - -4. **驱动调试:** - - 【可选】针对新增驱动程序,建议验证驱动基本功能,例如spi控制状态,中断响应情况等。 - -> ![](../public_sys-resources/icon-note.gif) **说明:** -> -> 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); -> }; -> ``` -> 表1 SpiCntlrMethod结构体成员的回调函数功能说明 -> -> |成员函数|入参|返回值|功能| -> |-|-|-|-| -> |Transfer |**cntlr**: 结构体指针,核心层spi控制器 ;
**msg**: 结构体指针,Spi消息;
**count**: uint32_t,消息个数 |HDF_STATUS相关状态|传输消息| -> |SetCfg |**cntlr**: 结构体指针,核心层spi控制器 ;
**cfg**: 结构体指针,Spi属性 |HDF_STATUS相关状态|设置控制器属性 | -> |GetCfg |**cntlr**: 结构体指针,核心层spi控制器 ;
**cfg**: 结构体指针,Spi属性 |HDF_STATUS相关状态|获取控制器属性 | -> |Open |**cntlr**: 结构体指针,核心层spi控制器 ; |HDF_STATUS相关状态|打开SPI | -> |Close |**cntlr**: 结构体指针,核心层spi控制器 ; |HDF_STATUS相关状态|关闭SPI | - -## 开发实例 - -下方将以spi_hi35xx.c为示例,展示需要厂商提供哪些内容来完整实现设备功能。 - -1. 驱动开发首先需要实例化驱动入口,驱动入口必须为HdfDriverEntry(在 hdf_device_desc.h 中定义)类型的全局变量,且moduleName要和device_info.hcs中保持一致。HDF框架会将所有加载的驱动的HdfDriverEntry对象首地址汇总,形成一个类似数组的段地址空间,方便上层调用。 - - 一般在加载驱动时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参考 - }; - //调用HDF_INIT将驱动入口注册到HDF框架中 - HDF_INIT(g_hdfSpiDevice); - ``` - -2. 完成驱动入口注册之后,下一步请在device_info.hcs文件中添加deviceNode信息,并在 spi_config.hcs 中配置器件属性。deviceNode信息与驱动入口注册相关,器件属性值与核心层SpiCntlr 成员的默认值或限制范围有密切关系。 -**本例只有一个SPI控制器,如有多个器件信息,则需要在device_info文件增加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"; - } - 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 添加对应的节点 - } - } - } - ``` - -3. 完成驱动入口注册之后,最后一步就是以核心层SpiCntlr对象的初始化为核心,包括厂商自定义结构体(传递参数和数据),实例化SpiCntlr成员SpiCntlrMethod(让用户可以通过接口来调用驱动底层函数),实现HdfDriverEntry成员函数(Bind,Init,Release) - -- 自定义结构体参考 - - > 从驱动的角度看,自定义结构体是参数和数据的载体,而且spi_config.hcs文件中的数值会被HDF读入通过DeviceResourceIface来初始化结构体成员,一些重要数值也会传递给核心层对象,例如设备号、总线号等。 - - ```c - 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; - }; - ``` - - -- **【重要】** SpiCntlr成员回调函数结构体SpiCntlrMethod的实例化,其他成员在Init函数中初始化 - - ```c - // spi_hi35xx.c 中的示例:钩子函数的实例化 - struct SpiCntlrMethod g_method = { - .Transfer = Pl022Transfer, - .SetCfg = Pl022SetCfg, - .GetCfg = Pl022GetCfg, - .Open = Pl022Open, - .Close = Pl022Close, - }; - ``` - - -- **Bind 函数参考** - - > **入参:** - > HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息 - > - > **返回值:** - > HDF_STATUS相关状态 - > - > **函数说明:** - > 将 SpiCntlr 对象同 HdfDeviceObject 进行了关联 - - ```c - static int32_t HdfSpiDeviceBind(struct HdfDeviceObject *device) - { - ... - return (SpiCntlrCreate(device) == NULL) ? HDF_FAILURE : HDF_SUCCESS; - } - - struct SpiCntlr *SpiCntlrCreate(struct HdfDeviceObject *device) - { - struct SpiCntlr *cntlr = NULL; //创建核心层 SpiCntlr 对象 - ... - 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->priv = NULL; - return cntlr; - } - ``` - - -- **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 |初始化失败| - > - > **函数说明:** - > 初始化自定义结构体对象,初始化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; - } - - 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; //挂载总线号 - cntlr->method = &g_method; //SpiCntlrMethod的实例化对象的挂载 - ... - ret = Pl022CreatAndInitDevice(pl022); - if (ret != 0) { - Pl022Release(pl022); //初始化失败就释放Pl022对象 - return ret; - } - return 0; - } - ``` - -- **Release函数参考** - - > **入参:** - > HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息 - > - > **返回值:** - > 无 - > - > **函数说明:** - > 释放内存和删除控制器,该函数需要在驱动入口结构体中赋值给 Release 接口, 当HDF框架调用Init函数初始化驱动失败时,可以调用 Release 释放驱动资源。所有强制转换获取相应对象的操作**前提**是在Init函数中具备对应赋值的操作。 - - ```c - static void HdfSpiDeviceRelease(struct HdfDeviceObject *device) - { - struct SpiCntlr *cntlr = NULL; - ... - 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的强制转化 - } - SpiCntlrDestroy(cntlr); //释放Pl022对象 - } - ``` +# SPI + +- [概述](#section84922229152909) +- [接口说明](#section752964871810) +- [开发步骤](#section799667984152909) +- [开发实例](#section956157227152909) + +## 概述 + +SPI是串行外设接口(Serial Peripheral Interface)的缩写,在HDF框架中,SPI的接口适配模式采用独立服务模式,在这种模式下,每一个设备对象会独立发布一个设备服务来处理外部访问,设备管理器收到API的访问请求之后,通过提取该请求的参数,达到调用实际设备对象的相应内部方法的目的。独立服务模式可以直接借助HDFDeviceManager的服务管理能力,但需要为每个设备单独配置设备节点,增加内存占用。 + +**图 1** SPI独立服务模式结构图 +![](figures/SPI独立服务模式结构图.png "SPI独立服务模式结构图") + +## 接口说明 + +SpiCntlrMethod定义: + +``` +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); +}; +``` + +**表 1** SpiCntlrMethod结构体成员的回调函数功能说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

成员函数

+

入参

+

返回值

+

功能

+

Transfer

+

cntlr: 结构体指针,核心层spi控制器;msg: 结构体指针,Spi消息;count: uint32_t,消息个数

+

HDF_STATUS相关状态

+

传输消息

+

SetCfg

+

cntlr: 结构体指针,核心层spi控制器;cfg: 结构体指针,Spi属性

+

HDF_STATUS相关状态

+

设置控制器属性

+

GetCfg

+

cntlr: 结构体指针,核心层spi控制器;cfg: 结构体指针,Spi属性

+

HDF_STATUS相关状态

+

获取控制器属性

+

Open

+

cntlr: 结构体指针,核心层spi控制器;

+

HDF_STATUS相关状态

+

打开SPI

+

Close

+

cntlr: 结构体指针,核心层spi控制器;

+

HDF_STATUS相关状态

+

关闭SPI

+
+ +## 开发步骤 + +SPI模块适配HDF框架的三个环节是配置属性文件,实例化驱动入口,以及实例化核心层接口函数。 + +1. **实例化驱动入口:** + - 实例化HdfDriverEntry结构体成员。 + - 调用HDF\_INIT将HdfDriverEntry实例化对象注册到HDF框架中。 + +2. **配置属性文件:** + - 在device\_info.hcs文件中添加deviceNode描述。 + - 【可选】添加spi\_config.hcs器件属性文件。 + +3. **实例化SPI控制器对象:** + - 初始化SpiCntlr成员。 + - 实例化SpiCntlr成员SpiCntlrMethod。 + + >![](../public_sys-resources/icon-note.gif) **说明:** + >实例化SpiCntlr成员SpiCntlrMethod,其定义和成员说明见[接口说明](#section752964871810)。 + + +4. **驱动调试:** + + 【可选】针对新增驱动程序,建议验证驱动基本功能,例如spi控制状态,中断响应情况等。 + + +## 开发实例 + +下方将以spi\_hi35xx.c为示例,展示需要厂商提供哪些内容来完整实现设备功能。 + +1. 驱动开发首先需要实例化驱动入口,驱动入口必须为HdfDriverEntry(在 hdf\_device\_desc.h 中定义)类型的全局变量,且moduleName要和device\_info.hcs中保持一致。HDF框架会将所有加载的驱动的HdfDriverEntry对象首地址汇总,形成一个类似数组的段地址空间,方便上层调用。 + + 一般在加载驱动时HDF会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。 + + SPI驱动入口参考: + + ``` + struct HdfDriverEntry g_hdfSpiDevice = { + .moduleVersion = 1, + .moduleName = "HDF_PLATFORM_SPI",//【必要 且与 HCS文件中里面的moduleName匹配】 + .Bind = HdfSpiDeviceBind, //见Bind参考 + .Init = HdfSpiDeviceInit, //见Init参考 + .Release = HdfSpiDeviceRelease, //见Release参考 + }; + //调用HDF_INIT将驱动入口注册到HDF框架中 + HDF_INIT(g_hdfSpiDevice); + ``` + +2. 完成驱动入口注册之后,下一步请在device\_info.hcs文件中添加deviceNode信息,并在 spi\_config.hcs 中配置器件属性。deviceNode信息与驱动入口注册相关,器件属性值与核心层SpiCntlr 成员的默认值或限制范围有密切关系。 + + 本例只有一个SPI控制器,如有多个器件信息,则需要在device\_info文件增加deviceNode信息,以及在spi\_config文件中增加对应的器件属性。 + + - device\_info.hcs 配置参考。 + + ``` + 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"; + } + 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 配置参考。 + + ``` + 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 添加对应的节点 + } + } + } + ``` + +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; + }; + ``` + + - SpiCntlr成员回调函数结构体SpiCntlrMethod的实例化,其他成员在Init函数中初始化。 + + ``` + // spi_hi35xx.c 中的示例:钩子函数的实例化 + struct SpiCntlrMethod g_method = { + .Transfer = Pl022Transfer, + .SetCfg = Pl022SetCfg, + .GetCfg = Pl022GetCfg, + .Open = Pl022Open, + .Close = Pl022Close, + }; + ``` + + - Bind 函数参考 + + 入参: + + HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息。 + + 返回值**:** + + HDF\_STATUS相关状态。 + + 函数说明**:** + + 将 SpiCntlr 对象同 HdfDeviceObject 进行了关联。 + + ``` + static int32_t HdfSpiDeviceBind(struct HdfDeviceObject *device) + { + ... + return (SpiCntlrCreate(device) == NULL) ? HDF_FAILURE : HDF_SUCCESS; + } + + struct SpiCntlr *SpiCntlrCreate(struct HdfDeviceObject *device) + { + struct SpiCntlr *cntlr = NULL; //创建核心层 SpiCntlr 对象 + ... + 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->priv = NULL; + return cntlr; + } + ``` + + - Init函数参考 + + 入参: + + HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息。 + + 返回值**:** + + HDF\_STATUS相关状态 (下表为部分展示,如需使用其他状态,可见//drivers/framework/include/utils/hdf\_base.h中HDF\_STATUS 定义)。 + + **表 2** init函数入参和返回值 + + + + + + + + + + + + + + + + + + + + + + + + + +

状态(值)

+

问题描述

+

HDF_ERR_INVALID_OBJECT

+

控制器对象非法

+

HDF_ERR_MALLOC_FAIL

+

内存分配失败

+

HDF_ERR_INVALID_PARAM

+

参数非法

+

HDF_ERR_IO

+

I/O 错误

+

HDF_SUCCESS

+

初始化成功

+

HDF_FAILURE

+

初始化失败

+
+ + 函数说明**:** + + 初始化自定义结构体对象,初始化SpiCntlr成员。 + + ``` + 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; + } + + 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; + } + ``` + + - Release函数参考 + + 入参**:** + + HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息。 + + 返回值: + + 无。 + + 函数说明: + + 释放内存和删除控制器,该函数需要在驱动入口结构体中赋值给 Release 接口, 当HDF框架调用Init函数初始化驱动失败时,可以调用 Release 释放驱动资源。所有强制转换获取相应对象的操作**前提**是在Init函数中具备对应赋值的操作。 + + ``` + static void HdfSpiDeviceRelease(struct HdfDeviceObject *device) + { + struct SpiCntlr *cntlr = NULL; + ... + 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的强制转化 + } + SpiCntlrDestroy(cntlr); //释放Pl022对象 + } + ``` + + + diff --git a/zh-cn/device-dev/driver/driver-platform-uart-des.md b/zh-cn/device-dev/driver/driver-platform-uart-des.md index 182cad984a49051847129210d7cce9e9db7bbcdd..d094332869782c3d4bf9ec999fe44327939d19a8 100644 --- a/zh-cn/device-dev/driver/driver-platform-uart-des.md +++ b/zh-cn/device-dev/driver/driver-platform-uart-des.md @@ -1,8 +1,7 @@ -# UART +# UART - [概述](#section833012453535) - - [接口说明](#section1680292311549) - +- [接口说明](#section1928742202715) - [使用指导](#section12779050105412) - [使用流程](#section1858116395510) - [获取UART设备句柄](#section124512065617) @@ -27,21 +26,17 @@ - RTS:发送请求信号,用于指示本设备是否准备好,可接受数据,和对端CTS相连; - CTS:允许发送信号,用于判断是否可以向对端发送数据,和对端RTS相连; - **图 1** 2线UART设备连接示意图 - - - ![](figure/zh-cn_image_0000001170262141.png) - - **图 2** 4线UART设备连接示意图 - + **图 1** 2线UART设备连接示意图 + ![](figures/2线UART设备连接示意图.png "2线UART设备连接示意图") - ![](figure/zh-cn_image_0000001123582482.png) + **图 2** 4线UART设备连接示意图 + ![](figures/4线UART设备连接示意图.png "4线UART设备连接示意图") - UART通信之前,收发双方需要约定好一些参数:波特率、数据格式(起始位、数据位、校验位、停止位)等。通信过程中,UART通过TX发送给对端数据,通过RX接收对端发送的数据。当UART接收缓存达到预定的门限值时,RTS变为不可发送数据,对端的CTS检测到不可发送数据,则停止发送数据。 - UART接口定义了操作UART端口的通用方法集合,包括获取、释放设备句柄、读写数据、获取和设置波特率、获取和设置设备属性。 -### 接口说明 +## 接口说明 **表 1** UART驱动API接口功能介绍 @@ -122,12 +117,10 @@ ### 使用流程 -使用UART的一般流程如[图3](#fig1852173020185)所示。 - -**图 3** UART使用流程图 - +使用UART的一般流程如[图3](#fig99673244388)所示。 -![](figure/zh-cn_image_0000001170227689.png) +**图 3** UART使用流程图 +![](figures/UART使用流程图.png "UART使用流程图") ### 获取UART设备句柄 diff --git a/zh-cn/device-dev/driver/driver-platform-uart-develop.md b/zh-cn/device-dev/driver/driver-platform-uart-develop.md index f087e7df7b4dc89607be5080d4d65822c5ecdf1a..03aca8344b3dfa0be34f75bfc1242c713687d23c 100755 --- a/zh-cn/device-dev/driver/driver-platform-uart-develop.md +++ b/zh-cn/device-dev/driver/driver-platform-uart-develop.md @@ -1,390 +1,547 @@ -# UART - -- [概述](#1) -- [开发步骤](#2) -- [开发实例](#3) - -## 概述 - -UART是通用异步收发传输器(Universal Asynchronous Receiver/Transmitter)的缩写,在HDF框架中,uart的接口适配模式采用独立服务模式。在这种模式下,每一个设备对象会独立发布一个设备服务来处理外部访问,设备管理器收到API的访问请求之后,通过提取该请求的参数,达到调用实际设备对象的相应内部方法的目的。 - -独立服务模式可以直接借助HDFDeviceManager的服务管理能力,但需要为每个设备单独配置设备节点,增加内存占用。 - -图 1 独立服务模式结构图 -![image1](figure/独立服务模式.png) - -## 开发步骤 - -uart模块适配HDF框架的三个环节是配置属性文件,实例化驱动入口,以及实例化核心层接口函数。 - -1. **实例化驱动入口:** - - 实例化HdfDriverEntry结构体成员。 - - 调用HDF_INIT将HdfDriverEntry实例化对象注册到HDF框架中。 - -2. **配置属性文件:** - - - 在device_info.hcs文件中添加deviceNode描述。 - - 【可选】添加uart_config.hcs器件属性文件。 - -3. **实例化UART控制器对象:** - - - 初始化UartHost成员。 - - 实例化UartHost成员UartHostMethod,其定义和成员说明见下 - -4. **驱动调试:** - - 【可选】针对新增驱动程序,建议验证驱动基本功能,例如UART控制状态,中断响应情况等。 - -> ![](../public_sys-resources/icon-note.gif) **说明:** -> UartHostMethod定义 -> -> ```c -> struct UartHostMethod { -> int32_t (*Init)(struct UartHost *host); -> int32_t (*Deinit)(struct UartHost *host); -> int32_t (*Read)(struct UartHost *host, uint8_t *data, uint32_t size); -> int32_t (*Write)(struct UartHost *host, uint8_t *data, uint32_t size); -> int32_t (*GetBaud)(struct UartHost *host, uint32_t *baudRate); -> int32_t (*SetBaud)(struct UartHost *host, uint32_t baudRate); -> int32_t (*GetAttribute)(struct UartHost *host, struct UartAttribute *attribute); -> int32_t (*SetAttribute)(struct UartHost *host, struct UartAttribute *attribute); -> int32_t (*SetTransMode)(struct UartHost *host, enum UartTransMode mode); -> int32_t (*pollEvent)(struct UartHost *host, void *filep, void *table); -> }; -> ``` -> -> 表1 UartHostMethod结构体成员的回调函数功能说明 -> -> |函数|入参|出参|返回值|功能| -> |-|-|-|-|-| -> |Init |**host**: 结构体指针,核心层uart控制器; |无|HDF_STATUS相关状态|初始化Uart设备| -> |Deinit |**host**: 结构体指针,核心层uart控制器; |无|HDF_STATUS相关状态| 去初始化Uart设备 | -> |Read |**host**: 结构体指针,核心层uart控制器;
**size**:uint32_t,数据大小; |**data**: uint8_t指针,传出的数据 |HDF_STATUS相关状态|接收数据 RX | -> |Write |**host**: 结构体指针,核心层uart控制器;
**data**:uint8_t指针,传入数据;
**size**:uint32_t,数据大小; |无|HDF_STATUS相关状态|发送数据 TX | -> |SetBaud |**host**: 结构体指针,核心层uart控制器;
**baudRate**: uint32_t指针,波特率传入值; |无|HDF_STATUS相关状态| 设置波特率 | -> |GetBaud |**host**: 结构体指针,核心层uart控制器; |**baudRate**: uint32_t指针,传出的波特率; |HDF_STATUS相关状态|获取当前设置的波特率| -> |GetAttribute |**host**: 结构体指针,核心层uart控制器; |**attribute**: 结构体指针,传出的属性值
(见uart_if.h中UartAttribute定义)|HDF_STATUS相关状态| 获取设备uart相关属性| -> |SetAttribute |**host**: 结构体指针,核心层uart控制器;
**attribute**: 结构体指针,属性传入值; |无|HDF_STATUS相关状态| 设置设备uart相关属性 | -> |SetTransMode |**host**: 结构体指针,核心层uart控制器;
**mode**: 枚举值(见uart_if.h中
UartTransMode定义),传输模式 |无|HDF_STATUS相关状态| 设置传输模式 | -> |PollEvent |**host**: 结构体指针,核心层uart控制器;
**filep**: void 指针,file ;
**table**: void 指针,poll_table ;|无|HDF_STATUS相关状态|poll机制| - - -## 开发实例 - -下方将以uart_hi35xx.c为示例,展示需要厂商提供哪些内容来完整实现设备功能。 - -1. 驱动开发首先需要实例化驱动入口,驱动入口必须为HdfDriverEntry(在 hdf_device_desc.h 中定义)类型的全局变量,且moduleName要和device_info.hcs中保持一致。HDF框架会将所有加载的驱动的HdfDriverEntry对象首地址汇总,形成一个类似数组的段地址空间,方便上层调用。 - - 一般在加载驱动时HDF会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。 - -- UART驱动入口参考 - - ```c - struct HdfDriverEntry g_hdfUartDevice = { - .moduleVersion = 1, - .moduleName = "HDF_PLATFORM_UART",//【必要且与 HCS 里面的名字匹配】 - .Bind = HdfUartDeviceBind, //见Bind参考 - .Init = HdfUartDeviceInit, //见Init参考 - .Release = HdfUartDeviceRelease, //见Release参考 - }; - //调用HDF_INIT将驱动入口注册到HDF框架中 - HDF_INIT(g_hdfUartDevice); - ``` - -2. 完成驱动入口注册之后,下一步请在device_info.hcs文件中添加deviceNode信息,并在 uart_config.hcs 中配置器件属性。deviceNode信息与驱动入口注册相关,器件属性值与核心层UartHost成员的默认值或限制范围有密切关系。 - - **本例只有一个UART控制器,如有多个器件信息,则需要在device_info文件增加deviceNode信息,以及在uart_config文件中增加对应的器件属性**。 - -- device_info.hcs 配置参考 - - ```c - root { - device_info { - match_attr = "hdf_manager"; - platform :: host { - hostName = "platform_host"; - priority = 50; - device_uart :: device { - device0 :: deviceNode { - policy = 1; //驱动服务发布的策略,policy大于等于1(用户态可见为2,仅内核态可见为1); - priority = 40; //驱动启动优先级 - permission = 0644; //驱动创建设备节点权限 - moduleName = "HDF_PLATFORM_UART"; //驱动名称,该字段的值必须和驱动入口结构的moduleName值一致 - serviceName = "HDF_PLATFORM_UART_0";//驱动对外发布服务的名称,必须唯一,必须要按照HDF_PLATFORM_UART_X的格式,X为UART控制器编号 - deviceMatchAttr = "hisilicon_hi35xx_uart_0";//驱动私有数据匹配的关键字,必须和驱动私有数据配置表中的match_attr值一致 - } - device1 :: deviceNode { - policy = 2; - permission = 0644; - priority = 40; - moduleName = "HDF_PLATFORM_UART"; - serviceName = "HDF_PLATFORM_UART_1"; - deviceMatchAttr = "hisilicon_hi35xx_uart_1"; - } - ... - } - } - } - } - ``` - -- uart_config.hcs 配置参考 - - ```c - root { - platform { - template uart_controller {//模板公共参数, 继承该模板的节点如果使用模板中的默认值, 则节点字段可以缺省 - match_attr = ""; - num = 0; //【必要】设备号 - baudrate = 115200; //【必要】波特率,数值可按需填写 - fifoRxEn = 1; //【必要】使能接收FIFO - fifoTxEn = 1; //【必要】使能发送FIFO - flags = 4; //【必要】标志信号 - regPbase = 0x120a0000; //【必要】地址映射需要 - interrupt = 38; //【必要】中断号 - iomemCount = 0x48; //【必要】地址映射需要 - } - controller_0x120a0000 :: uart_controller { - match_attr = "hisilicon_hi35xx_uart_0";//【必要】必须和device_info.hcs中对应的设备的deviceMatchAttr值一致 - } - controller_0x120a1000 :: uart_controller { - num = 1; - baudrate = 9600; - regPbase = 0x120a1000; - interrupt = 39; - match_attr = "hisilicon_hi35xx_uart_1"; - } - ... - // 【可选】可新增,但需要在 device_info.hcs 添加对应的节点 - } - } - ``` - -3. 完成驱动入口注册之后,最后一步就是以核心层UartHost对象的初始化为核心,包括厂商自定义结构体(传递参数和数据),实例化UartHost成员UartHostMethod(让用户可以通过接口来调用驱动底层函数),实现HdfDriverEntry成员函数(Bind,Init,Release) - -- 自定义结构体参考 - - > 从驱动的角度看,自定义结构体是参数和数据的载体,而且uart_config.hcs文件中的数值会被HDF读入通过DeviceResourceIface来初始化结构体成员,一些重要数值也会传递给核心层对象,例如设备号等。 - - ```c - struct UartPl011Port { //接口相关的结构体 - int32_t enable; - unsigned long physBase; //物理地址 - uint32_t irqNum; //中断号 - uint32_t defaultBaudrate;//默认波特率 - uint32_t flags; //标志信号,下面三个宏与之相关 - #define PL011_FLG_IRQ_REQUESTED (1 << 0) - #define PL011_FLG_DMA_RX_REQUESTED (1 << 1) - #define PL011_FLG_DMA_TX_REQUESTED (1 << 2) - struct UartDmaTransfer *rxUdt; //DMA传输相关 - struct UartDriverData *udd; //见下 - }; - struct UartDriverData { //数据传输相关的结构体 - uint32_t num; - uint32_t baudrate; //波特率(可设置) - struct UartAttribute attr; //数据位、停止位等传输属性相关 - struct UartTransfer *rxTransfer; //缓冲区相关,可理解为FIFO结构 - wait_queue_head_t wait; //条件变量相关的排队等待信号 - int32_t count; //数据数量 - int32_t state; //uart控制器状态 - #define UART_STATE_NOT_OPENED 0 - #define UART_STATE_OPENING 1 - #define UART_STATE_USEABLE 2 - #define UART_STATE_SUSPENED 3 - uint32_t flags; //状态标志 - #define UART_FLG_DMA_RX (1 << 0) - #define UART_FLG_DMA_TX (1 << 1) - #define UART_FLG_RD_BLOCK (1 << 2) - RecvNotify recv; //函数指针类型,指向串口数据接收函数 - struct UartOps *ops; //自定义函数指针结构体,详情见device/hisilicon/drivers/uart/uart_pl011.c - void *private; //一般用来存储UartPl011Port首地址,方便调用 - }; - - // UartHost是核心层控制器结构体,其中的成员在Init函数中会被赋值 - struct UartHost { - struct IDeviceIoService service; - struct HdfDeviceObject *device; - uint32_t num; - OsalAtomic atom; - void *priv; //一般存储厂商自定义结构体首地址,方便后者被调用 - struct UartHostMethod *method; //核心层钩子函数,厂商需要实现其成员函数功能并实例化 - }; - ``` - -- **【重要】** UartHost成员回调函数结构体UartHostMethod的实例化,其他成员在Bind函数中初始化 - - ```c - // uart_hi35xx.c 中的示例:钩子函数的实例化 - struct UartHostMethod g_uartHostMethod = { - .Init = Hi35xxInit, - .Deinit = Hi35xxDeinit, - .Read = Hi35xxRead, - .Write = Hi35xxWrite, - .SetBaud = Hi35xxSetBaud, - .GetBaud = Hi35xxGetBaud, - .SetAttribute = Hi35xxSetAttribute, - .GetAttribute = Hi35xxGetAttribute, - .SetTransMode = Hi35xxSetTransMode, - .pollEvent = Hi35xxPollEvent, - }; - ``` - - -- **Bind函数参考** - - > **入参:** - > 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 |初始化失败| - > - > **函数说明:** - > 初始化自定义结构体对象,初始化UartHost成员 - - ```c - //uart_hi35xx.c - static int32_t HdfUartDeviceBind(struct HdfDeviceObject *device) - { - ... - return (UartHostCreate(device) == NULL) ? HDF_FAILURE : HDF_SUCCESS;//【必须做】调用核心层函数 UartHostCreate - } - //uart_core.c 核心层 UartHostCreate 函数说明 - struct UartHost *UartHostCreate(struct HdfDeviceObject *device) - { - struct UartHost *host = NULL; //新建 UartHost - ... - host = (struct UartHost *)OsalMemCalloc(sizeof(*host));//分配内存 - ... - host->device = device; //【必要】使HdfDeviceObject与UartHost可以相互转化的前提 - device->service = &(host->service);//【必要】使HdfDeviceObject与UartHost可以相互转化的前提 - host->device->service->Dispatch = UartIoDispatch;//为 service 成员的 Dispatch 方法赋值 - OsalAtomicSet(&host->atom, 0); //原子量初始化或者原子量设置 - host->priv = NULL; - host->method = NULL; - return host; - } - ``` - - -- **Init函数参考** - - > **入参:** - > HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息 - > - > **返回值:** - > HDF_STATUS相关状态 - > - > **函数说明:** - > 初始化自定义结构体对象,初始化UartHost成员,调用核心层UartAddDev函数,接入VFS - - ```c - int32_t HdfUartDeviceInit(struct HdfDeviceObject *device) - { - int32_t ret; - struct UartHost *host = NULL; - HDF_LOGI("%s: entry", __func__); - ... - host = UartHostFromDevice(device);//通过service成员后强制转为UartHost,赋值是在Bind函数中 - ... - ret = Hi35xxAttach(host, device); //完成UartHost对象的初始化,见下 - ... - host->method = &g_uartHostMethod; //UartHostMethod的实例化对象的挂载 - return ret; - } - //完成 UartHost 对象的初始化 - static int32_t Hi35xxAttach(struct UartHost *host, struct HdfDeviceObject *device) - { - int32_t ret; - //udd 和 port 对象是厂商自定义的结构体对象,可根据需要实现相关功能 - struct UartDriverData *udd = NULL; - struct UartPl011Port *port = NULL; - ... - // 【必要相关功能】步骤【1】~【7】主要实现对 udd 对象的实例化赋值,然后赋值给核心层UartHost对象上 - udd = (struct UartDriverData *)OsalMemCalloc(sizeof(*udd));//【1】 - ... - port = (struct UartPl011Port *)OsalMemCalloc(sizeof(struct UartPl011Port));//【2】 - ... - udd->ops = Pl011GetOps();//【3】设备开启、关闭、属性设置、发送操作等函数挂载 - udd->recv = PL011UartRecvNotify;//【4】数据接收通知函数(条件锁机制)挂载 - udd->count = 0; //【5】 - port->udd = udd; //【6】使UartPl011Port与UartDriverData可以相互转化的前提 - ret = UartGetConfigFromHcs(port, device->property);//【必要】 此步骤是将 HdfDeviceObject 的属性传递给厂商自定义结构体 - // 用于相关操作,示例代码见下 - ... - udd->private = port; //【7】 - - host->priv = udd; //【必要】使UartHost与UartDriverData可以相互转化的前提 - host->num = udd->num;//【必要】uart 设备号 - UartAddDev(host); //【必要】核心层uart_dev.c 中的函数,作用:注册了一个字符设备节点到vfs, 这样从用户态可以通过这个虚拟文件节点访问uart - return HDF_SUCCESS; - } - - static int32_t UartGetConfigFromHcs(struct UartPl011Port *port, const struct DeviceResourceNode *node) - { - uint32_t tmp, regPbase, iomemCount; - struct UartDriverData *udd = port->udd; - struct DeviceResourceIface *iface = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE); - ... - //通过请求参数提取相应的值,并赋值给厂商自定义的结构体 - if (iface->GetUint32(node, "num", &udd->num, 0) != HDF_SUCCESS) { - HDF_LOGE("%s: read busNum fail", __func__); - return HDF_FAILURE; - } - ... - return 0; - } - ``` - -- **Release函数参考** - - > **入参:** - > HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息 - > - > **返回值:** - > 无 - > - > **函数说明:** - > 该函数需要在驱动入口结构体中赋值给 Release 接口, 当HDF框架调用Init函数初始化驱动失败时,可以调用 Release 释放驱动资源, 该函数中需包含释放内存和删除控制器等操作。所有强制转换获取相应对象的操作**前提**是在Init函数中具备对应赋值的操作。 - - ```c - void HdfUartDeviceRelease(struct HdfDeviceObject *device) - { - struct UartHost *host = NULL; - ... - host = UartHostFromDevice(device);//这里有HdfDeviceObject到UartHost的强制转化,通过service成员,赋值见Bind函数 - ... - if (host->priv != NULL) { - Hi35xxDetach(host); //厂商自定义的内存释放函数,见下 - } - UartHostDestroy(host); //调用核心层函数释放host - } - - static void Hi35xxDetach(struct UartHost *host) - { - struct UartDriverData *udd = NULL; - struct UartPl011Port *port = NULL; - ... - udd = host->priv; //这里有UartHost到UartDriverData的转化 - ... - UartRemoveDev(host);//VFS注销 - port = udd->private;//这里有UartDriverData到UartPl011Port的转化 - if (port != NULL) { - if (port->physBase != 0) { - OsalIoUnmap((void *)port->physBase);//地址反映射 - } - (void)OsalMemFree(port); - udd->private = NULL; - } - (void)OsalMemFree(udd);//释放UartDriverData - host->priv = NULL; - } - ``` - +# UART + +- [概述](#section1761881586154520) +- [接口说明](#section752964871810) +- [开发步骤](#section944397404154520) +- [开发实例](#section774610224154520) + +## 概述 + +UART是通用异步收发传输器(Universal Asynchronous Receiver/Transmitter)的缩写,在HDF框架中,UART的接口适配模式采用独立服务模式。在这种模式下,每一个设备对象会独立发布一个设备服务来处理外部访问,设备管理器收到API的访问请求之后,通过提取该请求的参数,达到调用实际设备对象的相应内部方法的目的。独立服务模式可以直接借助HDFDeviceManager的服务管理能力,但需要为每个设备单独配置设备节点,增加内存占用。 + +**图 1** UART独立服务模式结构图 +![](figures/UART独立服务模式结构图.png "UART独立服务模式结构图") + +## 接口说明 + +UartHostMethod定义: + +``` +struct UartHostMethod { + int32_t (*Init)(struct UartHost *host); + int32_t (*Deinit)(struct UartHost *host); + int32_t (*Read)(struct UartHost *host, uint8_t *data, uint32_t size); + int32_t (*Write)(struct UartHost *host, uint8_t *data, uint32_t size); + int32_t (*GetBaud)(struct UartHost *host, uint32_t *baudRate); + int32_t (*SetBaud)(struct UartHost *host, uint32_t baudRate); + int32_t (*GetAttribute)(struct UartHost *host, struct UartAttribute *attribute); + int32_t (*SetAttribute)(struct UartHost *host, struct UartAttribute *attribute); + int32_t (*SetTransMode)(struct UartHost *host, enum UartTransMode mode); + int32_t (*pollEvent)(struct UartHost *host, void *filep, void *table); +}; +``` + +**表 1** UartHostMethod结构体成员的回调函数功能说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

函数

+

入参

+

出参

+

返回值

+

功能

+

Init

+

host: 结构体指针,核心层uart控制器;

+

+

HDF_STATUS相关状态

+

初始化Uart设备

+

Deinit

+

host: 结构体指针,核心层uart控制器;

+

+

HDF_STATUS相关状态

+

去初始化Uart设备

+

Read

+

host: 结构体指针,核心层uart控制器;size:uint32_t,数据大小;

+

data: uint8_t指针,传出的数据

+

HDF_STATUS相关状态

+

接收数据 RX

+

Write

+

host: 结构体指针,核心层uart控制器;data:uint8_t指针,传入数据;size:uint32_t,数据大小;

+

+

HDF_STATUS相关状态

+

发送数据 TX

+

SetBaud

+

host: 结构体指针,核心层uart控制器;baudRate: uint32_t指针,波特率传入值;

+

+

HDF_STATUS相关状态

+

设置波特率

+

GetBaud

+

host: 结构体指针,核心层uart控制器;

+

baudRate: uint32_t指针,传出的波特率;

+

HDF_STATUS相关状态

+

获取当前设置的波特率

+

GetAttribute

+

host: 结构体指针,核心层uart控制器;

+

attribute: 结构体指针,传出的属性值(见uart_if.h中UartAttribute定义)

+

HDF_STATUS相关状态

+

获取设备uart相关属性

+

SetAttribute

+

host: 结构体指针,核心层uart控制器;attribute: 结构体指针,属性传入值;

+

+

HDF_STATUS相关状态

+

设置设备uart相关属性

+

SetTransMode

+

host: 结构体指针,核心层uart控制器;mode: 枚举值(见uart_if.h中UartTransMode定义),传输模式

+

+

HDF_STATUS相关状态

+

设置传输模式

+

PollEvent

+

host: 结构体指针,核心层uart控制器;filep: void 指针,file ;table: void 指针,poll_table ;

+

+

HDF_STATUS相关状态

+

poll机制

+
+ +## 开发步骤 + +UART模块适配HDF框架的三个环节是配置属性文件,实例化驱动入口,以及实例化核心层接口函数。 + +1. **实例化驱动入口:** + - 实例化HdfDriverEntry结构体成员。 + - 调用HDF\_INIT将HdfDriverEntry实例化对象注册到HDF框架中。 + +2. **配置属性文件:** + - 在device\_info.hcs文件中添加deviceNode描述。 + - 【可选】添加uart\_config.hcs器件属性文件。 + +3. **实例化UART控制器对象:** + - 初始化UartHost成员。 + - 实例化UartHost成员UartHostMethod。 + + >![](../public_sys-resources/icon-note.gif) **说明:** + >实例化UartHost成员UartHostMethod,其定义和成员说明见[接口说明](#section752964871810)。 + + +4. **驱动调试:** + + 【可选】针对新增驱动程序,建议验证驱动基本功能,例如UART控制状态,中断响应情况等。 + + +## 开发实例 + +下方将以uart\_hi35xx.c为示例,展示需要厂商提供哪些内容来完整实现设备功能。 + +1. 驱动开发首先需要实例化驱动入口,驱动入口必须为HdfDriverEntry(在 hdf\_device\_desc.h 中定义)类型的全局变量,且moduleName要和device\_info.hcs中保持一致。HDF框架会将所有加载的驱动的HdfDriverEntry对象首地址汇总,形成一个类似数组的段地址空间,方便上层调用。 + + 一般在加载驱动时HDF会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。 + + UART驱动入口参考: + + ``` + struct HdfDriverEntry g_hdfUartDevice = { + .moduleVersion = 1, + .moduleName = "HDF_PLATFORM_UART",//【必要且与 HCS 里面的名字匹配】 + .Bind = HdfUartDeviceBind, //见Bind参考 + .Init = HdfUartDeviceInit, //见Init参考 + .Release = HdfUartDeviceRelease, //见Release参考 + }; + //调用HDF_INIT将驱动入口注册到HDF框架中 + HDF_INIT(g_hdfUartDevice); + ``` + +2. 完成驱动入口注册之后,下一步请在device\_info.hcs文件中添加deviceNode信息,并在 uart\_config.hcs 中配置器件属性。deviceNode信息与驱动入口注册相关,器件属性值与核心层UartHost成员的默认值或限制范围有密切关系。 + + 本例只有一个UART控制器,如有多个器件信息,则需要在device\_info文件增加deviceNode信息,以及在uart\_config文件中增加对应的器件属性。 + + - device\_info.hcs 配置参考。 + + ``` + root { + device_info { + match_attr = "hdf_manager"; + platform :: host { + hostName = "platform_host"; + priority = 50; + device_uart :: device { + device0 :: deviceNode { + policy = 1; //驱动服务发布的策略,policy大于等于1(用户态可见为2,仅内核态可见为1); + priority = 40; //驱动启动优先级 + permission = 0644; //驱动创建设备节点权限 + moduleName = "HDF_PLATFORM_UART"; //驱动名称,该字段的值必须和驱动入口结构的moduleName值一致 + serviceName = "HDF_PLATFORM_UART_0";//驱动对外发布服务的名称,必须唯一,必须要按照HDF_PLATFORM_UART_X的格式,X为UART控制器编号 + deviceMatchAttr = "hisilicon_hi35xx_uart_0";//驱动私有数据匹配的关键字,必须和驱动私有数据配置表中的match_attr值一致 + } + device1 :: deviceNode { + policy = 2; + permission = 0644; + priority = 40; + moduleName = "HDF_PLATFORM_UART"; + serviceName = "HDF_PLATFORM_UART_1"; + deviceMatchAttr = "hisilicon_hi35xx_uart_1"; + } + ... + } + } + } + } + ``` + + - uart\_config.hcs 配置参考。 + + ``` + root { + platform { + template uart_controller {//模板公共参数, 继承该模板的节点如果使用模板中的默认值, 则节点字段可以缺省 + match_attr = ""; + num = 0; //【必要】设备号 + baudrate = 115200; //【必要】波特率,数值可按需填写 + fifoRxEn = 1; //【必要】使能接收FIFO + fifoTxEn = 1; //【必要】使能发送FIFO + flags = 4; //【必要】标志信号 + regPbase = 0x120a0000; //【必要】地址映射需要 + interrupt = 38; //【必要】中断号 + iomemCount = 0x48; //【必要】地址映射需要 + } + controller_0x120a0000 :: uart_controller { + match_attr = "hisilicon_hi35xx_uart_0";//【必要】必须和device_info.hcs中对应的设备的deviceMatchAttr值一致 + } + controller_0x120a1000 :: uart_controller { + num = 1; + baudrate = 9600; + regPbase = 0x120a1000; + interrupt = 39; + match_attr = "hisilicon_hi35xx_uart_1"; + } + ... + // 【可选】可新增,但需要在 device_info.hcs 添加对应的节点 + } + } + ``` + +3. 完成驱动入口注册之后,最后一步就是以核心层UartHost对象的初始化为核心,包括厂商自定义结构体(传递参数和数据),实例化UartHost成员UartHostMethod(让用户可以通过接口来调用驱动底层函数),实现HdfDriverEntry成员函数(Bind,Init,Release)。 + - 自定义结构体参考。 + + 从驱动的角度看,自定义结构体是参数和数据的载体,而且uart\_config.hcs文件中的数值会被HDF读入通过DeviceResourceIface来初始化结构体成员,一些重要数值也会传递给核心层对象,例如设备号等。 + + ``` + struct UartPl011Port { //接口相关的结构体 + int32_t enable; + unsigned long physBase; //物理地址 + uint32_t irqNum; //中断号 + uint32_t defaultBaudrate;//默认波特率 + uint32_t flags; //标志信号,下面三个宏与之相关 + #define PL011_FLG_IRQ_REQUESTED (1 << 0) + #define PL011_FLG_DMA_RX_REQUESTED (1 << 1) + #define PL011_FLG_DMA_TX_REQUESTED (1 << 2) + struct UartDmaTransfer *rxUdt; //DMA传输相关 + struct UartDriverData *udd; //见下 + }; + struct UartDriverData { //数据传输相关的结构体 + uint32_t num; + uint32_t baudrate; //波特率(可设置) + struct UartAttribute attr; //数据位、停止位等传输属性相关 + struct UartTransfer *rxTransfer; //缓冲区相关,可理解为FIFO结构 + wait_queue_head_t wait; //条件变量相关的排队等待信号 + int32_t count; //数据数量 + int32_t state; //uart控制器状态 + #define UART_STATE_NOT_OPENED 0 + #define UART_STATE_OPENING 1 + #define UART_STATE_USEABLE 2 + #define UART_STATE_SUSPENED 3 + uint32_t flags; //状态标志 + #define UART_FLG_DMA_RX (1 << 0) + #define UART_FLG_DMA_TX (1 << 1) + #define UART_FLG_RD_BLOCK (1 << 2) + RecvNotify recv; //函数指针类型,指向串口数据接收函数 + struct UartOps *ops; //自定义函数指针结构体,详情见device/hisilicon/drivers/uart/uart_pl011.c + void *private; //一般用来存储UartPl011Port首地址,方便调用 + }; + + // UartHost是核心层控制器结构体,其中的成员在Init函数中会被赋值 + struct UartHost { + struct IDeviceIoService service; + struct HdfDeviceObject *device; + uint32_t num; + OsalAtomic atom; + void *priv; //一般存储厂商自定义结构体首地址,方便后者被调用 + struct UartHostMethod *method; //核心层钩子函数,厂商需要实现其成员函数功能并实例化 + }; + ``` + + - UartHost成员回调函数结构体UartHostMethod的实例化,其他成员在Bind函数中初始化。 + + ``` + // uart_hi35xx.c 中的示例:钩子函数的实例化 + struct UartHostMethod g_uartHostMethod = { + .Init = Hi35xxInit, + .Deinit = Hi35xxDeinit, + .Read = Hi35xxRead, + .Write = Hi35xxWrite, + .SetBaud = Hi35xxSetBaud, + .GetBaud = Hi35xxGetBaud, + .SetAttribute = Hi35xxSetAttribute, + .GetAttribute = Hi35xxGetAttribute, + .SetTransMode = Hi35xxSetTransMode, + .pollEvent = Hi35xxPollEvent, + }; + ``` + + - Bind函数参考 + + 入参: + + HdfDeviceObject 这个是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息。 + + **返回值:** + + HDF\_STATUS相关状态 (下表为部分展示,如需使用其他状态,可见//drivers/framework/include/utils/hdf\_base.h中HDF\_STATUS 定义)。 + + **表 2** Bind函数入参和返回值 + + + + + + + + + + + + + + + + + + + + + + + + + +

状态(值)

+

问题描述

+

HDF_ERR_INVALID_OBJECT

+

控制器对象非法

+

HDF_ERR_MALLOC_FAIL

+

内存分配失败

+

HDF_ERR_INVALID_PARAM

+

参数非法

+

HDF_ERR_IO

+

I/O 错误

+

HDF_SUCCESS

+

初始化成功

+

HDF_FAILURE

+

初始化失败

+
+ + 函数说明: + + 初始化自定义结构体对象,初始化UartHost成员。 + + ``` + //uart_hi35xx.c + static int32_t HdfUartDeviceBind(struct HdfDeviceObject *device) + { + ... + return (UartHostCreate(device) == NULL) ? HDF_FAILURE : HDF_SUCCESS;//【必须做】调用核心层函数 UartHostCreate + } + //uart_core.c 核心层 UartHostCreate 函数说明 + struct UartHost *UartHostCreate(struct HdfDeviceObject *device) + { + struct UartHost *host = NULL; //新建 UartHost + ... + host = (struct UartHost *)OsalMemCalloc(sizeof(*host));//分配内存 + ... + host->device = device; //【必要】使HdfDeviceObject与UartHost可以相互转化的前提 + device->service = &(host->service);//【必要】使HdfDeviceObject与UartHost可以相互转化的前提 + host->device->service->Dispatch = UartIoDispatch;//为 service 成员的 Dispatch 方法赋值 + OsalAtomicSet(&host->atom, 0); //原子量初始化或者原子量设置 + host->priv = NULL; + host->method = NULL; + return host; + } + ``` + + - Init函数参考 + + 入参**:** + + HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息。 + + 返回值: + + HDF\_STATUS相关状态。 + + 函数说明: + + 初始化自定义结构体对象,初始化UartHost成员,调用核心层UartAddDev函数,接入VFS。 + + ``` + int32_t HdfUartDeviceInit(struct HdfDeviceObject *device) + { + int32_t ret; + struct UartHost *host = NULL; + HDF_LOGI("%s: entry", __func__); + ... + host = UartHostFromDevice(device);//通过service成员后强制转为UartHost,赋值是在Bind函数中 + ... + ret = Hi35xxAttach(host, device); //完成UartHost对象的初始化,见下 + ... + host->method = &g_uartHostMethod; //UartHostMethod的实例化对象的挂载 + return ret; + } + //完成 UartHost 对象的初始化 + static int32_t Hi35xxAttach(struct UartHost *host, struct HdfDeviceObject *device) + { + int32_t ret; + //udd 和 port 对象是厂商自定义的结构体对象,可根据需要实现相关功能 + struct UartDriverData *udd = NULL; + struct UartPl011Port *port = NULL; + ... + // 【必要相关功能】步骤【1】~【7】主要实现对 udd 对象的实例化赋值,然后赋值给核心层UartHost对象上 + udd = (struct UartDriverData *)OsalMemCalloc(sizeof(*udd));//【1】 + ... + port = (struct UartPl011Port *)OsalMemCalloc(sizeof(struct UartPl011Port));//【2】 + ... + udd->ops = Pl011GetOps();//【3】设备开启、关闭、属性设置、发送操作等函数挂载 + udd->recv = PL011UartRecvNotify;//【4】数据接收通知函数(条件锁机制)挂载 + udd->count = 0; //【5】 + port->udd = udd; //【6】使UartPl011Port与UartDriverData可以相互转化的前提 + ret = UartGetConfigFromHcs(port, device->property);//【必要】 此步骤是将 HdfDeviceObject 的属性传递给厂商自定义结构体 + // 用于相关操作,示例代码见下 + ... + udd->private = port; //【7】 + + host->priv = udd; //【必要】使UartHost与UartDriverData可以相互转化的前提 + host->num = udd->num;//【必要】uart 设备号 + UartAddDev(host); //【必要】核心层uart_dev.c 中的函数,作用:注册了一个字符设备节点到vfs, 这样从用户态可以通过这个虚拟文件节点访问uart + return HDF_SUCCESS; + } + + static int32_t UartGetConfigFromHcs(struct UartPl011Port *port, const struct DeviceResourceNode *node) + { + uint32_t tmp, regPbase, iomemCount; + struct UartDriverData *udd = port->udd; + struct DeviceResourceIface *iface = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE); + ... + //通过请求参数提取相应的值,并赋值给厂商自定义的结构体 + if (iface->GetUint32(node, "num", &udd->num, 0) != HDF_SUCCESS) { + HDF_LOGE("%s: read busNum fail", __func__); + return HDF_FAILURE; + } + ... + return 0; + } + ``` + + - Release函数参考 + + 入参: + + HdfDeviceObject 是整个驱动对外暴露的接口参数,具备 HCS 配置文件的信息。 + + 返回值: + + 无。 + + 函数说明: + + 该函数需要在驱动入口结构体中赋值给 Release 接口, 当HDF框架调用Init函数初始化驱动失败时,可以调用 Release 释放驱动资源, 该函数中需包含释放内存和删除控制器等操作。所有强制转换获取相应对象的操作**前提**是在Init函数中具备对应赋值的操作。 + + ``` + void HdfUartDeviceRelease(struct HdfDeviceObject *device) + { + struct UartHost *host = NULL; + ... + host = UartHostFromDevice(device);//这里有HdfDeviceObject到UartHost的强制转化,通过service成员,赋值见Bind函数 + ... + if (host->priv != NULL) { + Hi35xxDetach(host); //厂商自定义的内存释放函数,见下 + } + UartHostDestroy(host); //调用核心层函数释放host + } + + static void Hi35xxDetach(struct UartHost *host) + { + struct UartDriverData *udd = NULL; + struct UartPl011Port *port = NULL; + ... + udd = host->priv; //这里有UartHost到UartDriverData的转化 + ... + UartRemoveDev(host);//VFS注销 + port = udd->private;//这里有UartDriverData到UartPl011Port的转化 + if (port != NULL) { + if (port->physBase != 0) { + OsalIoUnmap((void *)port->physBase);//地址反映射 + } + (void)OsalMemFree(port); + udd->private = NULL; + } + (void)OsalMemFree(udd);//释放UartDriverData + host->priv = NULL; + } + ``` + + + diff --git a/zh-cn/device-dev/driver/driver-platform-watchdog-des.md b/zh-cn/device-dev/driver/driver-platform-watchdog-des.md index 57f2d55bc5fb03474aad9ff7042334c214ec7632..fcc46c34fcc16906c9f15e55016aea94513f3f58 100644 --- a/zh-cn/device-dev/driver/driver-platform-watchdog-des.md +++ b/zh-cn/device-dev/driver/driver-platform-watchdog-des.md @@ -1,8 +1,7 @@ -# WATCHDOG +# WATCHDOG - [概述](#section14918241977) - - [接口说明](#section20177131219818) - +- [接口说明](#section1180575010271) - [使用指导](#section10103184312813) - [使用流程](#section10181195910815) - [打开看门狗设备](#section66089201107) @@ -20,7 +19,7 @@ 看门狗(watchdog),又叫看门狗计时器(watchdog timer),是一种硬件的计时设备,当系统的主程序发生某些错误时,导致未及时清除看门狗计时器的计时值,这时看门狗计时器就会对系统发出复位信号,使系统从悬停状态恢复到正常运作状态。 -### 接口说明 +## 接口说明 **表 1** 看门狗 API接口功能介绍 @@ -93,12 +92,10 @@ ### 使用流程 -使用看门狗的一般流程如[图1](#fig19134125410189)所示。 - -**图 1** 看门狗使用流程图 - +使用看门狗的一般流程如[图1](#fig430533913392)所示。 -![](figure/zh-cn_image_0000001170229891.png) +**图 1** 看门狗使用流程图 +![](figures/看门狗使用流程图.png "看门狗使用流程图") ### 打开看门狗设备 diff --git a/zh-cn/device-dev/driver/driver-platform-watchdog-develop.md b/zh-cn/device-dev/driver/driver-platform-watchdog-develop.md index 85f75ad85201fdea2ea2ef35c9d69b300e87ee80..dbfcba6136a653dfa85e047b05555d4f75601793 100755 --- a/zh-cn/device-dev/driver/driver-platform-watchdog-develop.md +++ b/zh-cn/device-dev/driver/driver-platform-watchdog-develop.md @@ -1,253 +1,365 @@ -# WatchDog - -- [概述](#1) -- [开发步骤](#2) -- [开发实例](#3) - -## 概述 - -看门狗(Watchdog),又叫看门狗计时器(Watchdog timer),是一种硬件的计时设备,在HDF框架中,Watchdog接口适配模式采用独立服务模式,在这种模式下,每一个设备对象会独立发布一个设备服务来处理外部访问,设备管理器收到API的访问请求之后,通过提取该请求的参数,达到调用实际设备对象的相应内部方法的目的。 - -独立服务模式可以直接借助HDFDeviceManager的服务管理能力,但需要为每个设备单独配置设备节点,增加内存占用。 - -图 1 独立服务模式结构图 -![image1](figure/独立服务模式.png) - -## 开发步骤 - -Watchdog模块适配HDF框架的三个环节是配置属性文件,实例化驱动入口,以及实例化核心层接口函数。 - -1. **实例化驱动入口:** - - 实例化HdfDriverEntry结构体成员。 - - 调用HDF_INIT将HdfDriverEntry实例化对象注册到HDF框架中。 - -2. **配置属性文件:** - - - 在device_info.hcs文件中添加deviceNode描述。 - - 【可选】添加watchdog_config.hcs器件属性文件。 - -3. **实例化Watchdog控制器对象:** - - - 初始化WatchdogCntlr成员。 - - 实例化WatchdogCntlr成员WatchdogMethod,其定义和成员**说明**见下 - -4. **驱动调试:** - - 【可选】针对新增驱动程序,建议验证驱动基本功能,例如挂载后的信息反馈,超时时间设置的成功与否等。 - -> ![](../public_sys-resources/icon-note.gif) **说明:** -> WatchdogMethod定义 -> -> ```c -> struct WatchdogMethod { -> int32_t (*getStatus)(struct WatchdogCntlr *wdt, int32_t *status); -> int32_t (*setTimeout)(struct WatchdogCntlr *wdt, uint32_t seconds); -> int32_t (*getTimeout)(struct WatchdogCntlr *wdt, uint32_t *seconds); -> int32_t (*start)(struct WatchdogCntlr *wdt); -> int32_t (*stop)(struct WatchdogCntlr *wdt); -> int32_t (*feed)(struct WatchdogCntlr *wdt); -> int32_t (*getPriv)(struct WatchdogCntlr *wdt); //【可选】如果WatchdogCntlr 中的priv成员存在,则按需进行实例化 -> void (*releasePriv)(struct WatchdogCntlr *wdt);//【可选】 -> }; -> ``` -> -> 表1 WatchdogMethod成员的回调函数功能说明 -> |成员函数|入参|出参|返回值|功能| -> |-|-|-|-|-| -> |getStatus |**wdt**: 结构体指针,核心层WDG控制器; |**status**: int32_t指针,
表示狗的状态(打开或关闭); |HDF_STATUS相关状态|获取看门狗所处的状态| -> |start |**wdt**: 结构体指针,核心层WDG控制器; |无 |HDF_STATUS相关状态|打开开门狗 | -> |stop |**wdt**: 结构体指针,核心层WDG控制器; |无 |HDF_STATUS相关状态|关闭开门狗 | -> |setTimeout|**wdt**: 结构体指针,核心层WDG控制器;
**seconds**: uint32_t,时间传入值;|无|HDF_STATUS相关状态|设置超时时间值,单位秒,
需要保证看门狗实际运行的时间符合该值 | -> |getTimeout|**wdt**: 结构体指针,核心层WDG控制器; |**seconds**: uint32_t,
传出的时间值|HDF_STATUS相关状态|回读设置的超时时间值 | -> |feed |**wdt**: 结构体指针,核心层WDG控制器; |无 |HDF_STATUS相关状态|喂狗 | - - -## 开发实例 - -下方将以watchdog_hi35xx.c为示例,展示需要厂商提供哪些内容来完整实现设备功能。 - -1. 驱动开发首先需要实例化驱动入口,驱动入口必须为HdfDriverEntry(在 hdf_device_desc.h 中定义)类型的全局变量,且moduleName要和device_info.hcs中保持一致。HDF框架会将所有加载的驱动的HdfDriverEntry对象首地址汇总,形成一个类似数组的段地址空间,方便上层调用。 - - 一般在加载驱动时HDF会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。 - -- Watchdog驱动入口参考 - - ```c - struct HdfDriverEntry g_watchdogDriverEntry = { - .moduleVersion = 1, - .Bind = Hi35xxWatchdogBind, //见Bind参考 - .Init = Hi35xxWatchdogInit, //见Init参考 - .Release = Hi35xxWatchdogRelease, //见Release参考 - .moduleName = "HDF_PLATFORM_WATCHDOG",//【必要且与HCS文件中里面的moduleName匹配】 - }; - HDF_INIT(g_watchdogDriverEntry);//调用HDF_INIT将驱动入口注册到HDF框架中 - ``` - -2. 完成驱动入口注册之后,下一步请在device_info.hcs文件中添加deviceNode信息,并在 watchdog_config.hcs 中配置器件属性。deviceNode信息与驱动入口注册相关,器件属性值与核心层WatchdogCntlr 成员的默认值或限制范围有密切关系。 - - **本例只有一个Watchdog控制器,如有多个器件信息,则需要在device_info文件增加deviceNode信息,以及在watchdog_config文件中增加对应的器件属性**。 - -- device_info.hcs 配置参考 - - ```c - root { - device_info { - match_attr = "hdf_manager"; - device_watchdog :: device { // 设备节点 - device0 :: deviceNode { // 驱动的DeviceNode节点 - policy = 1; // policy字段是驱动服务发布的策略,如果需要面向用户态,则为2 - priority = 20; // 驱动启动优先级 - permission = 0644; // 驱动创建设备节点权限 - moduleName = "HDF_PLATFORM_WATCHDOG"; - // 【必要】驱动名称,该字段的值必须和驱动入口结构的moduleName值一致 - serviceName = "HDF_PLATFORM_WATCHDOG_0"; - // 【必要且唯一】驱动对外发布服务的名称 - deviceMatchAttr = "hisilicon_hi35xx_watchdog_0"; - // 【必要】驱动私有数据匹配的关键字,必须和驱动私有数据配置表中的match_attr值相等 - } - } - } - } - ``` - -- watchdog_config.hcs 配置参考 - - ```c - root { - platform { - template watchdog_controller {//【必要】模板配置,继承该模板的节点如果使用模板中的默认值,则节点字段可以缺省 - id = 0; - match_attr = ""; - regBase = 0x12050000; //【必要】地址映射需要 - regStep = 0x1000; //【必要】地址映射需要 - } - controller_0x12050000 :: watchdog_controller {//【必要】是作为设备驱动私有数据匹配的关键字 - match_attr = "hisilicon_hi35xx_watchdog_0"; //【必要】必须和device_info.hcs中的deviceMatchAttr值一致 - } - //存在多个 watchdog 时【必须】添加,否则不用 - ... - } - } - ``` - -3. 完成驱动入口注册之后,最后一步就是以核心层WatchdogCntlr对象的初始化为核心,包括厂商自定义结构体(传递参数和数据),实例化WatchdogCntlr成员WatchdogMethod(让用户可以通过接口来调用驱动底层函数),实现HdfDriverEntry成员函数(Bind,Init,Release) - -- 自定义结构体参考 - - > 从驱动的角度看,自定义结构体是参数和数据的载体,而且watchdog_config.hcs文件中的数值会被HDF读入通过DeviceResourceIface来初始化结构体成员,其中一些重要数值也会传递给核心层WatchdogCntlr对象,例如索引、管脚数等。 - - ```c - struct Hi35xxWatchdog { - struct WatchdogCntlr wdt; //【必要】是链接上下层的载体,具体描述见下面 - OsalSpinlock lock; - volatile unsigned char *regBase;//【必要】地址映射需要 - uint32_t phyBase; //【必要】地址映射需要 - uint32_t regStep; //【必要】地址映射需要 - }; - //WatchdogCntlr是核心层控制器结构体,其中的成员在Init函数中会被赋值 - struct WatchdogCntlr { - struct IDeviceIoService service;//驱动服务 - struct HdfDeviceObject *device; //驱动设备 - OsalSpinlock lock; //在HDF核心层调用时从系统代码实现了一个自旋锁的机制,挂载的变量需要是相同的变量,不建议挂载 - struct WatchdogMethod *ops; //接口回调函数 - int16_t wdtId; //WDG设备的识别id - void *priv; //存储指针 - }; - ``` - -- **【重要】** WatchdogCntlr成员回调函数结构体WatchdogMethod的实例化,其他成员在Init和Bind函数中初始化 - - ```c - static struct WatchdogMethod g_method = { - .getStatus = Hi35xxWatchdogGetStatus, - .start = Hi35xxWatchdogStart, - .stop = Hi35xxWatchdogStop, - .setTimeout = Hi35xxWatchdogSetTimeout, - .getTimeout = Hi35xxWatchdogGetTimeout, - .feed = Hi35xxWatchdogFeed, - }; - ``` - - -- **Init函数和Bind函数参考** - - > **入参:** - > HdfDeviceObject :HDF框架给每一个驱动创建的设备对象,用来保存设备相关的私有数据和服务接口 - > - > **返回值:** - > HDF_STATUS相关状态 (下表为部分展示,如需使用其他状态,可见//drivers/framework/include/utils/hdf_base.h中HDF_STATUS 定义) - > - > |状态(值)|问题描述| - > |:-|:-:| - > |HDF_ERR_INVALID_OBJECT|找不到 WDG 设备| - > |HDF_ERR_MALLOC_FAIL |内存分配失败| - > |HDF_ERR_IO |I/O 错误| - > |HDF_SUCCESS |初始化成功| - > |HDF_FAILURE |初始化失败| - > - > **函数说明:** - > 初始化自定义结构体对象,初始化WatchdogCntlr成员,调用核心层WatchdogCntlrAdd函数。 - - ```c - //一般而言,Init函数需要根据入参(HdfDeviceObject对象)的属性值初始化Hi35xxWatchdog结构体的成员, - //但本例中是在bind函数中实现的 - static int32_t Hi35xxWatchdogInit(struct HdfDeviceObject *device) - { - (void)device; - return HDF_SUCCESS; - } - - static int32_t Hi35xxWatchdogBind(struct HdfDeviceObject *device) - { - int32_t ret; - struct Hi35xxWatchdog *hwdt = NULL; - ... - hwdt = (struct Hi35xxWatchdog *)OsalMemCalloc(sizeof(*hwdt));//Hi35xxWatchdog 结构体的内存申请 - ... - hwdt->regBase = OsalIoRemap(hwdt->phyBase, hwdt->regStep); //地址映射 - ... - - hwdt->wdt.priv = (void *)device->property;//【可选】此处是将设备属性的内容赋值给priv成员,但后续没有调用priv成员, - // 如果需要用到priv成员,需要额外实例化WatchdogMethod的getPriv和releasePriv成员函数 - hwdt->wdt.ops = &g_method; //【必要】将实例化后的对象赋值给ops成员,就可以实现顶层调用WatchdogMethod成员函数 - hwdt->wdt.device = device; //【必要】这是为了方便HdfDeviceObject与WatchdogcCntlr相互转化 - ret = WatchdogCntlrAdd(&hwdt->wdt); //【必要】调用此函数初始化核心层结构体,返回成功信号后驱动才完全接入平台核心层 - if (ret != HDF_SUCCESS) { // 不成功的话,需要释放初始化函数申请的资源 - OsalIoUnmap((void *)hwdt->regBase); - OsalMemFree(hwdt); - return ret; - } - return HDF_SUCCESS; - } - ``` - -- **Release函数参考** - - > **入参:** - > HdfDeviceObject :HDF框架给每一个驱动创建的设备对象,用来保存设备相关的私有数据和服务接口 - > - > **返回值:** - > 无 - > - > **函数说明:** - > 该函数需要在驱动入口结构体中赋值给Release,当HDF框架调用Init函数初始化驱动失败时,可以调用Release释放驱动资源。该函数中需包含释放内存和删除控制器等操作。所有强制转换获取相应对象的操作**前提**是在Init函数中具备对应赋值的操作。 - - ```c - static void Hi35xxWatchdogRelease(struct HdfDeviceObject *device) - { - struct WatchdogCntlr *wdt = NULL; - struct Hi35xxWatchdog *hwdt = NULL; - ... - wdt = WatchdogCntlrFromDevice(device); //这里通过service成员将HdfDeviceObject强制转化为WatchdogCntlr - //return (device == NULL) ? NULL : (struct WatchdogCntlr *)device->service; - if (wdt == NULL) { - return; - } - WatchdogCntlrRemove(wdt); //核心层函数,实际执行wdt->device->service = NULL以及cntlr->lock的释放 - hwdt = (struct Hi35xxWatchdog *)wdt; //这里将WatchdogCntlr强制转化为HimciHost - if (hwdt->regBase != NULL) { //解除地址映射 - OsalIoUnmap((void *)hwdt->regBase); - hwdt->regBase = NULL; - } - OsalMemFree(hwdt); //释放厂商自定义对象占用的内存 - } - ``` +# WatchDog + +- [概述](#section1315827527160117) +- [接口说明](#section752964871810) +- [开发步骤](#section477974542160117) +- [开发实例](#section1832270347160117) + +## 概述 + +看门狗(Watchdog),又叫看门狗计时器(Watchdog timer),是一种硬件的计时设备,在HDF框架中,Watchdog接口适配模式采用独立服务模式,在这种模式下,每一个设备对象会独立发布一个设备服务来处理外部访问,设备管理器收到API的访问请求之后,通过提取该请求的参数,达到调用实际设备对象的相应内部方法的目的。独立服务模式可以直接借助HDFDeviceManager的服务管理能力,但需要为每个设备单独配置设备节点,增加内存占用。 + +**图 1** Watchdog独立服务模式结构图 +![](figures/Watchdog独立服务模式结构图.png "Watchdog独立服务模式结构图") + +## 接口说明 + +WatchdogMethod定义: + +``` +struct WatchdogMethod { + int32_t (*getStatus)(struct WatchdogCntlr *wdt, int32_t *status); + int32_t (*setTimeout)(struct WatchdogCntlr *wdt, uint32_t seconds); + int32_t (*getTimeout)(struct WatchdogCntlr *wdt, uint32_t *seconds); + int32_t (*start)(struct WatchdogCntlr *wdt); + int32_t (*stop)(struct WatchdogCntlr *wdt); + int32_t (*feed)(struct WatchdogCntlr *wdt); + int32_t (*getPriv)(struct WatchdogCntlr *wdt); //【可选】如果WatchdogCntlr 中的priv成员存在,则按需实例化 + void (*releasePriv)(struct WatchdogCntlr *wdt);//【可选】 +}; +``` + +**表 1** WatchdogMethod成员的回调函数功能说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

成员函数

+

入参

+

出参

+

返回值

+

功能

+

getStatus

+

wdt: 结构体指针,核心层WDG控制器;

+

status: int32_t指针,表示狗的状态(打开或关闭);

+

HDF_STATUS相关状态

+

获取看门狗所处的状态

+

start

+

wdt: 结构体指针,核心层WDG控制器;

+

+

HDF_STATUS相关状态

+

打开开门狗

+

stop

+

wdt: 结构体指针,核心层WDG控制器;

+

+

HDF_STATUS相关状态

+

关闭开门狗

+

setTimeout

+

wdt: 结构体指针,核心层WDG控制器;seconds: uint32_t,时间传入值;

+

+

HDF_STATUS相关状态

+

设置超时时间值,单位秒,需要保证看门狗实际运行的时间符合该值

+

getTimeout

+

wdt: 结构体指针,核心层WDG控制器;

+

seconds: uint32_t,传出的时间值

+

HDF_STATUS相关状态

+

回读设置的超时时间值

+

feed

+

wdt: 结构体指针,核心层WDG控制器;

+

+

HDF_STATUS相关状态

+

喂狗

+
+ +## 开发步骤 + +Watchdog模块适配HDF框架的三个环节是配置属性文件,实例化驱动入口,以及实例化核心层接口函数。 + +1. **实例化驱动入口:** + - 实例化HdfDriverEntry结构体成员。 + - 调用HDF\_INIT将HdfDriverEntry实例化对象注册到HDF框架中。 + +2. **配置属性文件:** + - 在device\_info.hcs文件中添加deviceNode描述。 + - 【可选】添加watchdog\_config.hcs器件属性文件。 + +3. **实例化Watchdog控制器对象:** + - 初始化WatchdogCntlr成员。 + - 实例化WatchdogCntlr成员WatchdogMethod。 + + >![](../public_sys-resources/icon-note.gif) **说明:** + >实例化WatchdogCntlr成员WatchdogMethod,其定义和成员说明见[接口说明](#section752964871810)。 + + +4. **驱动调试:** + + 【可选】针对新增驱动程序,建议验证驱动基本功能,例如挂载后的信息反馈,超时时间设置的成功与否等。 + + +## 开发实例 + +下方将以watchdog\_hi35xx.c为示例,展示需要厂商提供哪些内容来完整实现设备功能。 + +1. 驱动开发首先需要实例化驱动入口,驱动入口必须为HdfDriverEntry(在 hdf\_device\_desc.h 中定义)类型的全局变量,且moduleName要和device\_info.hcs中保持一致。HDF框架会将所有加载的驱动的HdfDriverEntry对象首地址汇总,形成一个类似数组的段地址空间,方便上层调用。 + + 一般在加载驱动时HDF会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。 + + Watchdog驱动入口参考: + + ``` + struct HdfDriverEntry g_watchdogDriverEntry = { + .moduleVersion = 1, + .Bind = Hi35xxWatchdogBind, //见Bind参考 + .Init = Hi35xxWatchdogInit, //见Init参考 + .Release = Hi35xxWatchdogRelease, //见Release参考 + .moduleName = "HDF_PLATFORM_WATCHDOG",//【必要且与HCS文件中里面的moduleName匹配】 + }; + HDF_INIT(g_watchdogDriverEntry);//调用HDF_INIT将驱动入口注册到HDF框架中 + ``` + +2. 完成驱动入口注册之后,下一步请在device\_info.hcs文件中添加deviceNode信息,并在 watchdog\_config.hcs 中配置器件属性。deviceNode信息与驱动入口注册相关,器件属性值与核心层WatchdogCntlr 成员的默认值或限制范围有密切关系。 + + 本例只有一个Watchdog控制器,如有多个器件信息,则需要在device\_info文件增加deviceNode信息,以及在watchdog\_config文件中增加对应的器件属性。 + + - device\_info.hcs 配置参考。 + + ``` + root { + device_info { + match_attr = "hdf_manager"; + device_watchdog :: device { // 设备节点 + device0 :: deviceNode { // 驱动的DeviceNode节点 + policy = 1; // policy字段是驱动服务发布的策略,如果需要面向用户态,则为2 + priority = 20; // 驱动启动优先级 + permission = 0644; // 驱动创建设备节点权限 + moduleName = "HDF_PLATFORM_WATCHDOG"; + // 【必要】驱动名称,该字段的值必须和驱动入口结构的moduleName值一致 + serviceName = "HDF_PLATFORM_WATCHDOG_0"; + // 【必要且唯一】驱动对外发布服务的名称 + deviceMatchAttr = "hisilicon_hi35xx_watchdog_0"; + // 【必要】驱动私有数据匹配的关键字,必须和驱动私有数据配置表中的match_attr值相等 + } + } + } + } + ``` + + - watchdog\_config.hcs 配置参考。 + + ``` + root { + platform { + template watchdog_controller {//【必要】模板配置,继承该模板的节点如果使用模板中的默认值,则节点字段可以缺省 + id = 0; + match_attr = ""; + regBase = 0x12050000; //【必要】地址映射需要 + regStep = 0x1000; //【必要】地址映射需要 + } + controller_0x12050000 :: watchdog_controller {//【必要】是作为设备驱动私有数据匹配的关键字 + match_attr = "hisilicon_hi35xx_watchdog_0"; //【必要】必须和device_info.hcs中的deviceMatchAttr值一致 + } + //存在多个 watchdog 时【必须】添加,否则不用 + ... + } + } + ``` + +3. 完成驱动入口注册之后,最后一步就是以核心层WatchdogCntlr对象的初始化为核心,包括厂商自定义结构体(传递参数和数据),实例化WatchdogCntlr成员WatchdogMethod(让用户可以通过接口来调用驱动底层函数),实现HdfDriverEntry成员函数(Bind,Init,Release)。 + - 自定义结构体参考。 + + 从驱动的角度看,自定义结构体是参数和数据的载体,而且watchdog\_config.hcs文件中的数值会被HDF读入通过DeviceResourceIface来初始化结构体成员,其中一些重要数值也会传递给核心层WatchdogCntlr对象,例如索引、管脚数等。 + + ``` + struct Hi35xxWatchdog { + struct WatchdogCntlr wdt; //【必要】是链接上下层的载体,具体描述见下面 + OsalSpinlock lock; + volatile unsigned char *regBase;//【必要】地址映射需要 + uint32_t phyBase; //【必要】地址映射需要 + uint32_t regStep; //【必要】地址映射需要 + }; + //WatchdogCntlr是核心层控制器结构体,其中的成员在Init函数中会被赋值 + struct WatchdogCntlr { + struct IDeviceIoService service;//驱动服务 + struct HdfDeviceObject *device; //驱动设备 + OsalSpinlock lock; //此变量在HDF核心层被调用来实现自旋锁功能 + struct WatchdogMethod *ops; //接口回调函数 + int16_t wdtId; //WDG设备的识别id + void *priv; //存储指针 + }; + ``` + + - WatchdogCntlr成员回调函数结构体WatchdogMethod的实例化,其他成员在Init和Bind函数中初始化。 + + ``` + static struct WatchdogMethod g_method = { + .getStatus = Hi35xxWatchdogGetStatus, + .start = Hi35xxWatchdogStart, + .stop = Hi35xxWatchdogStop, + .setTimeout = Hi35xxWatchdogSetTimeout, + .getTimeout = Hi35xxWatchdogGetTimeout, + .feed = Hi35xxWatchdogFeed, + }; + ``` + + - Init函数和Bind函数参考 + + 入参**:** + + HdfDeviceObject :HDF框架给每一个驱动创建的设备对象,用来保存设备相关的私有数据和服务接口。 + + 返回值**:** + + HDF\_STATUS相关状态 (下表为部分展示,如需使用其他状态,可见//drivers/framework/include/utils/hdf\_base.h中HDF\_STATUS 定义)。 + + **表 2** Init函数和Bind函数入参和返回值 + + + + + + + + + + + + + + + + + + + + + + +

状态(值)

+

问题描述

+

HDF_ERR_INVALID_OBJECT

+

找不到 WDG 设备

+

HDF_ERR_MALLOC_FAIL

+

内存分配失败

+

HDF_ERR_IO

+

I/O 错误

+

HDF_SUCCESS

+

初始化成功

+

HDF_FAILURE

+

初始化失败

+
+ + 函数说明**:** + + 初始化自定义结构体对象,初始化WatchdogCntlr成员,调用核心层WatchdogCntlrAdd函数。 + + ``` + //一般而言,Init函数需要根据入参(HdfDeviceObject对象)的属性值初始化Hi35xxWatchdog结构体的成员, + //但本例中是在bind函数中实现的 + static int32_t Hi35xxWatchdogInit(struct HdfDeviceObject *device) + { + (void)device; + return HDF_SUCCESS; + } + + static int32_t Hi35xxWatchdogBind(struct HdfDeviceObject *device) + { + int32_t ret; + struct Hi35xxWatchdog *hwdt = NULL; + ... + hwdt = (struct Hi35xxWatchdog *)OsalMemCalloc(sizeof(*hwdt));//Hi35xxWatchdog 结构体的内存申请 + ... + hwdt->regBase = OsalIoRemap(hwdt->phyBase, hwdt->regStep); //地址映射 + ... + hwdt->wdt.priv = (void *)device->property;//【可选】此处是将设备属性的内容赋值给priv成员,但后续没有调用 priv 成员, + // 如果需要用到priv成员,需要额外实例化WatchdogMethod的getPriv和releasePriv成员函数 + hwdt->wdt.ops = &g_method; //【必要】将实例化后的对象赋值给ops成员,就可以实现顶层调用WatchdogMethod成员函数 + hwdt->wdt.device = device; //【必要】这是为了方便HdfDeviceObject与WatchdogcCntlr相互转化 + ret = WatchdogCntlrAdd(&hwdt->wdt); //【必要】调用此函数初始化核心层结构体,返回成功信号后驱动才完全接入平台核心层 + if (ret != HDF_SUCCESS) { //不成功的话,需要释放Init函数申请的资源 + OsalIoUnmap((void *)hwdt->regBase); + OsalMemFree(hwdt); + return ret; + } + return HDF_SUCCESS; + } + ``` + + - Release函数参考 + + 入参: + + HdfDeviceObject :HDF框架给每一个驱动创建的设备对象,用来保存设备相关的私有数据和服务接口。 + + 返回值**:** + + 无。 + + 函数说明**:** + + 该函数需要在驱动入口结构体中赋值给Release,当HDF框架调用Init函数初始化驱动失败时,可以调用Release释放驱动资源。该函数中需包含释放内存和删除控制器等操作。所有强制转换获取相应对象的操作**前提**是在Init函数中具备对应赋值的操作。 + + ``` + static void Hi35xxWatchdogRelease(struct HdfDeviceObject *device) + { + struct WatchdogCntlr *wdt = NULL; + struct Hi35xxWatchdog *hwdt = NULL; + ... + wdt = WatchdogCntlrFromDevice(device);//这里会通过service成员将HdfDeviceObject转化为WatchdogCntlr + //return (device == NULL) ? NULL : (struct WatchdogCntlr *)device->service; + if (wdt == NULL) { + return; + } + WatchdogCntlrRemove(wdt); //核心层函数,实际执行wdt->device->service = NULL以及cntlr->lock的释放 + hwdt = (struct Hi35xxWatchdog *)wdt; //这里将WatchdogCntlr转化为HimciHost + if (hwdt->regBase != NULL) { //解除地址映射 + OsalIoUnmap((void *)hwdt->regBase); + hwdt->regBase = NULL; + } + OsalMemFree(hwdt); //释放厂商自定义对象占用的内存 + } + ``` + + + diff --git a/zh-cn/device-dev/driver/driver-platform.md b/zh-cn/device-dev/driver/driver-platform.md index 8c34624b9f491bcc9858feb1c988bce30c133541..017b58ac18c54d64ed5cf536984ce2dd5ae10dc5 100644 --- a/zh-cn/device-dev/driver/driver-platform.md +++ b/zh-cn/device-dev/driver/driver-platform.md @@ -16,4 +16,6 @@ - **[MIPI DSI](driver-platform-mipidsi-des.md)** +- **[PWM](driver-platform-pwm-des.md)** + diff --git a/zh-cn/device-dev/driver/driver.md b/zh-cn/device-dev/driver/driver.md index 58ee5fe7bc877da89acf3d2c7a5f08d2fd2f0a69..da3839d4de7c68822c784f3f6b1fe32c1457baae 100644 --- a/zh-cn/device-dev/driver/driver.md +++ b/zh-cn/device-dev/driver/driver.md @@ -1,9 +1,11 @@ -# 驱动使用指南 +# 驱动 - **[HDF驱动框架](driver-hdf.md)** -- **[平台驱动](driver-platform.md)** +- **[平台驱动开发](driver-develop.md)** -- **[外设](driver-peripherals.md)** +- **[平台驱动使用](driver-platform.md)** + +- **[外设驱动使用](driver-peripherals.md)** diff --git "a/zh-cn/device-dev/driver/figure/Touchscreen\345\231\250\344\273\266\345\270\270\347\224\250\347\256\241\350\204\232.png" "b/zh-cn/device-dev/driver/figure/Touchscreen\345\231\250\344\273\266\345\270\270\347\224\250\347\256\241\350\204\232.png" deleted file mode 100755 index 2d78b7c7f6994107238e21a1a21b55a5ec7b84a1..0000000000000000000000000000000000000000 Binary files "a/zh-cn/device-dev/driver/figure/Touchscreen\345\231\250\344\273\266\345\270\270\347\224\250\347\256\241\350\204\232.png" and /dev/null differ diff --git "a/zh-cn/device-dev/driver/figure/USB-Device\351\251\261\345\212\250\346\250\241\345\236\213\345\233\276.png" "b/zh-cn/device-dev/driver/figure/USB-Device\351\251\261\345\212\250\346\250\241\345\236\213\345\233\276.png" deleted file mode 100755 index 3766cf8117505a0d47720dcbccc1030536921bdb..0000000000000000000000000000000000000000 Binary files "a/zh-cn/device-dev/driver/figure/USB-Device\351\251\261\345\212\250\346\250\241\345\236\213\345\233\276.png" and /dev/null differ diff --git "a/zh-cn/device-dev/driver/figure/USB-Host\351\251\261\345\212\250\346\250\241\345\236\213\345\233\276.png" "b/zh-cn/device-dev/driver/figure/USB-Host\351\251\261\345\212\250\346\250\241\345\236\213\345\233\276.png" deleted file mode 100755 index 6bea2992afd00b031176998278c0bcfce0f8e843..0000000000000000000000000000000000000000 Binary files "a/zh-cn/device-dev/driver/figure/USB-Host\351\251\261\345\212\250\346\250\241\345\236\213\345\233\276.png" and /dev/null differ diff --git a/zh-cn/device-dev/driver/figure/zh-cn_image_0000001170262141.png "b/zh-cn/device-dev/driver/figures/2\347\272\277UART\350\256\276\345\244\207\350\277\236\346\216\245\347\244\272\346\204\217\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/driver/figure/zh-cn_image_0000001170262141.png rename to "zh-cn/device-dev/driver/figures/2\347\272\277UART\350\256\276\345\244\207\350\277\236\346\216\245\347\244\272\346\204\217\345\233\276.png" diff --git a/zh-cn/device-dev/driver/figure/zh-cn_image_0000001123582482.png "b/zh-cn/device-dev/driver/figures/4\347\272\277UART\350\256\276\345\244\207\350\277\236\346\216\245\347\244\272\346\204\217\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/driver/figure/zh-cn_image_0000001123582482.png rename to "zh-cn/device-dev/driver/figures/4\347\272\277UART\350\256\276\345\244\207\350\277\236\346\216\245\347\244\272\346\204\217\345\233\276.png" diff --git "a/zh-cn/device-dev/driver/figure/\347\273\237\344\270\200\346\234\215\345\212\241\346\250\241\345\274\217.png" "b/zh-cn/device-dev/driver/figures/ADC\347\273\237\344\270\200\346\234\215\345\212\241.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/driver/figure/\347\273\237\344\270\200\346\234\215\345\212\241\346\250\241\345\274\217.png" rename to "zh-cn/device-dev/driver/figures/ADC\347\273\237\344\270\200\346\234\215\345\212\241.png" diff --git "a/zh-cn/device-dev/driver/figure/DSI\345\217\221\351\200\201-\346\216\245\346\224\266\346\216\245\345\217\243.png" "b/zh-cn/device-dev/driver/figures/DSI\345\217\221\351\200\201-\346\216\245\346\224\266\346\216\245\345\217\243.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/driver/figure/DSI\345\217\221\351\200\201-\346\216\245\346\224\266\346\216\245\345\217\243.png" rename to "zh-cn/device-dev/driver/figures/DSI\345\217\221\351\200\201-\346\216\245\346\224\266\346\216\245\345\217\243.png" diff --git "a/zh-cn/device-dev/driver/figure/\346\227\240\346\234\215\345\212\241\346\250\241\345\274\217.png" "b/zh-cn/device-dev/driver/figures/DSI\346\227\240\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/driver/figure/\346\227\240\346\234\215\345\212\241\346\250\241\345\274\217.png" rename to "zh-cn/device-dev/driver/figures/DSI\346\227\240\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" diff --git a/zh-cn/device-dev/driver/figure/zh-cn_image_0000001170187071.png "b/zh-cn/device-dev/driver/figures/GPIO\344\275\277\347\224\250\346\265\201\347\250\213\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/driver/figure/zh-cn_image_0000001170187071.png rename to "zh-cn/device-dev/driver/figures/GPIO\344\275\277\347\224\250\346\265\201\347\250\213\345\233\276.png" diff --git "a/zh-cn/device-dev/driver/figures/GPIO\346\227\240\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" "b/zh-cn/device-dev/driver/figures/GPIO\346\227\240\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" new file mode 100644 index 0000000000000000000000000000000000000000..833ff6cc89e49ed4210dd68a502e4b304ac1c273 Binary files /dev/null and "b/zh-cn/device-dev/driver/figures/GPIO\346\227\240\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" differ diff --git a/zh-cn/device-dev/driver/figure/zh-cn_image_0000001054564784.png "b/zh-cn/device-dev/driver/figures/HDF\351\251\261\345\212\250\346\250\241\345\236\213.png" old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/driver/figure/zh-cn_image_0000001054564784.png rename to "zh-cn/device-dev/driver/figures/HDF\351\251\261\345\212\250\346\250\241\345\236\213.png" diff --git "a/zh-cn/device-dev/driver/figure/I2C\347\211\251\347\220\206\350\277\236\347\272\277\347\244\272\346\204\217\345\233\276.png" "b/zh-cn/device-dev/driver/figures/I2C\347\211\251\347\220\206\350\277\236\347\272\277\347\244\272\346\204\217\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/driver/figure/I2C\347\211\251\347\220\206\350\277\236\347\272\277\347\244\272\346\204\217\345\233\276.png" rename to "zh-cn/device-dev/driver/figures/I2C\347\211\251\347\220\206\350\277\236\347\272\277\347\244\272\346\204\217\345\233\276.png" diff --git "a/zh-cn/device-dev/driver/figures/I2C\347\273\237\344\270\200\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" "b/zh-cn/device-dev/driver/figures/I2C\347\273\237\344\270\200\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" new file mode 100644 index 0000000000000000000000000000000000000000..838f9a4416d901eb29b5d203b559b3dcfe29fed9 Binary files /dev/null and "b/zh-cn/device-dev/driver/figures/I2C\347\273\237\344\270\200\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" differ diff --git a/zh-cn/device-dev/driver/figure/zh-cn_image_0000001123509750.png "b/zh-cn/device-dev/driver/figures/I2C\350\256\276\345\244\207\344\275\277\347\224\250\346\265\201\347\250\213\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/driver/figure/zh-cn_image_0000001123509750.png rename to "zh-cn/device-dev/driver/figures/I2C\350\256\276\345\244\207\344\275\277\347\224\250\346\265\201\347\250\213\345\233\276.png" diff --git a/zh-cn/device-dev/driver/figure/zh-cn_image_0000001123514210.png "b/zh-cn/device-dev/driver/figures/MIPI-DSI\344\275\277\347\224\250\346\265\201\347\250\213\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/driver/figure/zh-cn_image_0000001123514210.png rename to "zh-cn/device-dev/driver/figures/MIPI-DSI\344\275\277\347\224\250\346\265\201\347\250\213\345\233\276.png" diff --git "a/zh-cn/device-dev/driver/figure/MIPI-DSI\346\216\245\345\217\243.png" "b/zh-cn/device-dev/driver/figures/MIPI-DSI\346\216\245\345\217\243.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/driver/figure/MIPI-DSI\346\216\245\345\217\243.png" rename to "zh-cn/device-dev/driver/figures/MIPI-DSI\346\216\245\345\217\243.png" diff --git "a/zh-cn/device-dev/driver/figure/\347\213\254\347\253\213\346\234\215\345\212\241\346\250\241\345\274\217.png" "b/zh-cn/device-dev/driver/figures/MMC\347\213\254\347\253\213\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/driver/figure/\347\213\254\347\253\213\346\234\215\345\212\241\346\250\241\345\274\217.png" rename to "zh-cn/device-dev/driver/figures/MMC\347\213\254\347\253\213\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" diff --git "a/zh-cn/device-dev/driver/figures/PWM\347\213\254\347\253\213\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" "b/zh-cn/device-dev/driver/figures/PWM\347\213\254\347\253\213\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" new file mode 100644 index 0000000000000000000000000000000000000000..23324872566e5affac8baa186a30b64b3257f673 Binary files /dev/null and "b/zh-cn/device-dev/driver/figures/PWM\347\213\254\347\253\213\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" differ diff --git "a/zh-cn/device-dev/driver/figures/RTC\347\213\254\347\253\213\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" "b/zh-cn/device-dev/driver/figures/RTC\347\213\254\347\253\213\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" new file mode 100644 index 0000000000000000000000000000000000000000..23324872566e5affac8baa186a30b64b3257f673 Binary files /dev/null and "b/zh-cn/device-dev/driver/figures/RTC\347\213\254\347\253\213\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" differ diff --git a/zh-cn/device-dev/driver/figure/zh-cn_image_0000001123675706.png "b/zh-cn/device-dev/driver/figures/RTC\350\256\276\345\244\207\344\275\277\347\224\250\346\265\201\347\250\213\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/driver/figure/zh-cn_image_0000001123675706.png rename to "zh-cn/device-dev/driver/figures/RTC\350\256\276\345\244\207\344\275\277\347\224\250\346\265\201\347\250\213\345\233\276.png" diff --git a/zh-cn/device-dev/driver/figure/zh-cn_image_0000001123540984.png "b/zh-cn/device-dev/driver/figures/SDIO\344\275\277\347\224\250\346\265\201\347\250\213\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/driver/figure/zh-cn_image_0000001123540984.png rename to "zh-cn/device-dev/driver/figures/SDIO\344\275\277\347\224\250\346\265\201\347\250\213\345\233\276.png" diff --git "a/zh-cn/device-dev/driver/figures/SDIO\347\213\254\347\253\213\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" "b/zh-cn/device-dev/driver/figures/SDIO\347\213\254\347\253\213\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" new file mode 100644 index 0000000000000000000000000000000000000000..23324872566e5affac8baa186a30b64b3257f673 Binary files /dev/null and "b/zh-cn/device-dev/driver/figures/SDIO\347\213\254\347\253\213\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" differ diff --git a/zh-cn/device-dev/driver/figure/zh-cn_image_0000001054280608.png "b/zh-cn/device-dev/driver/figures/SDIO\347\232\204HOST-DEVICE\350\277\236\346\216\245\347\244\272\346\204\217\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/driver/figure/zh-cn_image_0000001054280608.png rename to "zh-cn/device-dev/driver/figures/SDIO\347\232\204HOST-DEVICE\350\277\236\346\216\245\347\244\272\346\204\217\345\233\276.png" diff --git a/zh-cn/device-dev/driver/figure/zh-cn_image_0000001123742254.png "b/zh-cn/device-dev/driver/figures/SPI\344\270\273\344\273\216\350\256\276\345\244\207\350\277\236\346\216\245\347\244\272\346\204\217\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/driver/figure/zh-cn_image_0000001123742254.png rename to "zh-cn/device-dev/driver/figures/SPI\344\270\273\344\273\216\350\256\276\345\244\207\350\277\236\346\216\245\347\244\272\346\204\217\345\233\276.png" diff --git a/zh-cn/device-dev/driver/figure/zh-cn_image_0000001123703482.png "b/zh-cn/device-dev/driver/figures/SPI\344\275\277\347\224\250\346\265\201\347\250\213\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/driver/figure/zh-cn_image_0000001123703482.png rename to "zh-cn/device-dev/driver/figures/SPI\344\275\277\347\224\250\346\265\201\347\250\213\345\233\276.png" diff --git "a/zh-cn/device-dev/driver/figures/SPI\347\213\254\347\253\213\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" "b/zh-cn/device-dev/driver/figures/SPI\347\213\254\347\253\213\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" new file mode 100644 index 0000000000000000000000000000000000000000..23324872566e5affac8baa186a30b64b3257f673 Binary files /dev/null and "b/zh-cn/device-dev/driver/figures/SPI\347\213\254\347\253\213\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" differ diff --git "a/zh-cn/device-dev/driver/figure/Sensor\351\251\261\345\212\250\346\250\241\345\236\213\345\233\276.png" "b/zh-cn/device-dev/driver/figures/Sensor\351\251\261\345\212\250\346\250\241\345\236\213\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/driver/figure/Sensor\351\251\261\345\212\250\346\250\241\345\236\213\345\233\276.png" rename to "zh-cn/device-dev/driver/figures/Sensor\351\251\261\345\212\250\346\250\241\345\236\213\345\233\276.png" diff --git "a/zh-cn/device-dev/driver/figure/TTL\346\216\245\345\217\243.png" "b/zh-cn/device-dev/driver/figures/TTL\346\216\245\345\217\243.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/driver/figure/TTL\346\216\245\345\217\243.png" rename to "zh-cn/device-dev/driver/figures/TTL\346\216\245\345\217\243.png" diff --git "a/zh-cn/device-dev/driver/figures/Touchscreen\345\231\250\344\273\266\345\270\270\347\224\250\347\256\241\350\204\232.png" "b/zh-cn/device-dev/driver/figures/Touchscreen\345\231\250\344\273\266\345\270\270\347\224\250\347\256\241\350\204\232.png" new file mode 100644 index 0000000000000000000000000000000000000000..6d33da5cc9efaa7d7d880623735e32a37f171dd8 Binary files /dev/null and "b/zh-cn/device-dev/driver/figures/Touchscreen\345\231\250\344\273\266\345\270\270\347\224\250\347\256\241\350\204\232.png" differ diff --git a/zh-cn/device-dev/driver/figure/zh-cn_image_0000001170227689.png "b/zh-cn/device-dev/driver/figures/UART\344\275\277\347\224\250\346\265\201\347\250\213\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/driver/figure/zh-cn_image_0000001170227689.png rename to "zh-cn/device-dev/driver/figures/UART\344\275\277\347\224\250\346\265\201\347\250\213\345\233\276.png" diff --git "a/zh-cn/device-dev/driver/figures/UART\347\213\254\347\253\213\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" "b/zh-cn/device-dev/driver/figures/UART\347\213\254\347\253\213\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" new file mode 100644 index 0000000000000000000000000000000000000000..23324872566e5affac8baa186a30b64b3257f673 Binary files /dev/null and "b/zh-cn/device-dev/driver/figures/UART\347\213\254\347\253\213\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" differ diff --git a/zh-cn/device-dev/driver/figure/zh-cn_image_0000001170383063.png "b/zh-cn/device-dev/driver/figures/WLAN\346\241\206\346\236\266.png" old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/driver/figure/zh-cn_image_0000001170383063.png rename to "zh-cn/device-dev/driver/figures/WLAN\346\241\206\346\236\266.png" diff --git "a/zh-cn/device-dev/driver/figure/\346\216\245\345\217\243\345\210\206\345\270\203\345\233\2764.png" "b/zh-cn/device-dev/driver/figures/WLAN\346\250\241\345\235\227\345\274\200\346\224\276\350\203\275\345\212\233\345\210\206\345\270\203\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/driver/figure/\346\216\245\345\217\243\345\210\206\345\270\203\345\233\2764.png" rename to "zh-cn/device-dev/driver/figures/WLAN\346\250\241\345\235\227\345\274\200\346\224\276\350\203\275\345\212\233\345\210\206\345\270\203\345\233\276.png" diff --git "a/zh-cn/device-dev/driver/figures/Watchdog\347\213\254\347\253\213\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" "b/zh-cn/device-dev/driver/figures/Watchdog\347\213\254\347\253\213\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" new file mode 100644 index 0000000000000000000000000000000000000000..23324872566e5affac8baa186a30b64b3257f673 Binary files /dev/null and "b/zh-cn/device-dev/driver/figures/Watchdog\347\213\254\347\253\213\346\234\215\345\212\241\346\250\241\345\274\217\347\273\223\346\236\204\345\233\276.png" differ diff --git a/zh-cn/device-dev/driver/figures/zh-cn_image_0000001206372673.png b/zh-cn/device-dev/driver/figures/zh-cn_image_0000001206372673.png new file mode 100644 index 0000000000000000000000000000000000000000..4fe8c2506c044bb280a52138a9936e8d7d2e8c01 Binary files /dev/null and b/zh-cn/device-dev/driver/figures/zh-cn_image_0000001206372673.png differ diff --git "a/zh-cn/device-dev/driver/figure/\345\237\272\344\272\216HDF\351\251\261\345\212\250\346\241\206\346\236\266\347\232\204Display\351\251\261\345\212\250\346\250\241\345\236\213.png" "b/zh-cn/device-dev/driver/figures/\345\237\272\344\272\216HDF\351\251\261\345\212\250\346\241\206\346\236\266\347\232\204Display\351\251\261\345\212\250\346\250\241\345\236\213.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/driver/figure/\345\237\272\344\272\216HDF\351\251\261\345\212\250\346\241\206\346\236\266\347\232\204Display\351\251\261\345\212\250\346\250\241\345\236\213.png" rename to "zh-cn/device-dev/driver/figures/\345\237\272\344\272\216HDF\351\251\261\345\212\250\346\241\206\346\236\266\347\232\204Display\351\251\261\345\212\250\346\250\241\345\236\213.png" diff --git "a/zh-cn/device-dev/driver/figure/\345\237\272\344\272\216HDF\351\251\261\345\212\250\346\241\206\346\236\266\347\232\204input\351\251\261\345\212\250\346\250\241\345\236\213.png" "b/zh-cn/device-dev/driver/figures/\345\237\272\344\272\216HDF\351\251\261\345\212\250\346\241\206\346\236\266\347\232\204input\351\251\261\345\212\250\346\250\241\345\236\213.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/driver/figure/\345\237\272\344\272\216HDF\351\251\261\345\212\250\346\241\206\346\236\266\347\232\204input\351\251\261\345\212\250\346\250\241\345\236\213.png" rename to "zh-cn/device-dev/driver/figures/\345\237\272\344\272\216HDF\351\251\261\345\212\250\346\241\206\346\236\266\347\232\204input\351\251\261\345\212\250\346\250\241\345\236\213.png" diff --git a/zh-cn/device-dev/driver/figure/zh-cn_image_0000001170229891.png "b/zh-cn/device-dev/driver/figures/\347\234\213\351\227\250\347\213\227\344\275\277\347\224\250\346\265\201\347\250\213\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/driver/figure/zh-cn_image_0000001170229891.png rename to "zh-cn/device-dev/driver/figures/\347\234\213\351\227\250\347\213\227\344\275\277\347\224\250\346\265\201\347\250\213\345\233\276.png" diff --git a/zh-cn/device-dev/driver/figure/zh-cn_image_0000001053405727.png "b/zh-cn/device-dev/driver/figures/\351\205\215\347\275\256\344\275\277\347\224\250\346\265\201\347\250\213\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/driver/figure/zh-cn_image_0000001053405727.png rename to "zh-cn/device-dev/driver/figures/\351\205\215\347\275\256\344\275\277\347\224\250\346\265\201\347\250\213\345\233\276.png" diff --git a/zh-cn/device-dev/get-code/sourcecode-acquire.md b/zh-cn/device-dev/get-code/sourcecode-acquire.md index 24dbe526dfc776f3e675abda9363786e70f14149..758442de39bd29a3cfe356e680138330764d7cd4 100644 --- a/zh-cn/device-dev/get-code/sourcecode-acquire.md +++ b/zh-cn/device-dev/get-code/sourcecode-acquire.md @@ -1,7 +1,7 @@ -# 源码获取 +# 获取源码 - [OpenHarmony介绍](#section6370143622110) -- [源码获取概述](#section12763342204) +- [获取源码概述](#section12763342204) - [获取方式1:从码云仓库获取](#section537312010229) - [适用场景](#section10881513459) - [前提条件](#section102871547153314) @@ -14,15 +14,16 @@ - [获取方式3:从镜像站点获取](#section1186691118430) - [获取方式4:从github镜像仓库获取\(每天UTC时间23点同步\)](#section23448418360) -- [源码目录简介](#section1072115612811) +- [源码目录](#section1072115612811) + ## OpenHarmony介绍 OpenHarmony是由开放原子开源基金会(OpenAtom Foundation)孵化及运营的开源项目,目标是面向全场景、全连接、全智能时代,搭建一个智能终端设备操作系统的框架和平台,促进万物互联产业的繁荣发展。 -开源代码仓库地址:[https://openharmony.gitee.com](https://openharmony.gitee.com) +开源代码仓库地址:[https://openharmony.gitee.com](https://openharmony.gitee.com)。 -## 源码获取概述 +## 获取源码概述 本文档将介绍如何获取OpenHarmony源码并说明OpenHarmony的源码目录结构。OpenHarmony的代码以[组件](../bundles/oem_bundle_standard_des.md)的形式开放,开发者可以通过如下其中一种方式获取: @@ -95,7 +96,7 @@ OpenHarmony是由开放原子开源基金会(OpenAtom Foundation)孵化及 - **OpenHarmony 发布版本代码获取** - OpenHarmony发布版本源码获取方式请参考版本[Release-Notes](../../release-notes/Readme.md)。 + OpenHarmony发布版本源码获取方式请参考[Release-Notes](../../release-notes/Readme.md)。 ## 获取方式2:从DevEco Marketplace获取 @@ -174,9 +175,7 @@ OpenHarmony是由开放原子开源基金会(OpenAtom Foundation)孵化及 为了获得更好的下载性能,您可以选择从以下站点的镜像库获取源码或者对应的解决方案。 ->![](../public_sys-resources/icon-note.gif) **说明:** ->- 本部分只提供OpenHarmony Master最新版本和LTS最新版本的源码获取方式, 其他版本源码获取方式以及具体版本信息请参考[Release-Notes](../../release-notes/Readme.md)。 ->- 当前Master 1.0版本已经不再维护。 +本部分只提供OpenHarmony Master最新版本和LTS最新版本的源码获取方式, 其他版本源码获取方式以及具体版本信息请参考[Release-Notes](../../release-notes/Readme.md)。 **表 1** 源码获取路径 @@ -271,56 +270,11 @@ OpenHarmony是由开放原子开源基金会(OpenAtom Foundation)孵化及

SHA256校验码

全量代码(标准系统)

-

2.0 Canary

-

站点1站点2

-

SHA256校验码

-

全量代码(轻量和小型系统)

-

1.0(不再维护)

-

站点

-

SHA256 校验码

-

Hi3861解决方案(二进制)

-

1.0(不再维护)

-

站点

-

SHA256 校验码

-

Hi3518解决方案(二进制)

-

1.0(不再维护)

-

站点

-

SHA256 校验码

-

Hi3516解决方案(二进制)

-

1.0(不再维护)

-

站点

-

SHA256 校验码

-

RELEASE-NOTES

1.0(不再维护)

+

2.2 Beta2

站点

+

站点

-

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

功能分类

+

接口名

+

描述

+

内存调测功能

+

mem_check_init

+

初始化内存检测模块。

+

watch_mem

+

获取线程级堆内存使用信息。

+

check_leak

+

检查是否有堆内存泄漏。

+

check_heap_integrity

+

检查堆内存的完整性。

+

调用栈回溯功能

+

backtrace

+

获取调用栈地址信息。

+

backtrace_symbols

+

根据地址信息获取符号信息。

+

print_trace

+

输出函数调用栈信息。

+
+ diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-user-guide-use-api.md b/zh-cn/device-dev/kernel/kernel-small-debug-user-guide-use-api.md new file mode 100644 index 0000000000000000000000000000000000000000..d5b8010de25a7b9bd4958befc77a5839322551c4 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-small-debug-user-guide-use-api.md @@ -0,0 +1,147 @@ +# 接口调用方式 + +- [示例代码](#section5490173592518) +- [编译](#section534302242515) +- [调测信息](#section1017419992515) +- [调用栈解析](#section1485163282417) + +## 示例代码 + +代码功能:显式调用调测模块的相关接口对用户代码进行内存校验。 + +``` +#include +#include +#include +#include // 包含提供内存调测接口声明的头文件 + +#define MALLOC_LEAK_SIZE 0x300 + +void func(void) { + char *ptr = malloc(MALLOC_LEAK_SIZE); + memset(ptr, '3', MALLOC_LEAK_SIZE); +} + +int main() +{ + mem_check_init(NULL); // 通过串口输出内存调测信息,必须在用户程序第一次申请堆内存之前调用(一般在main函数入口调用),否则调测信息不准确。 + // mem_check_init("/storage/mem_debug.txt"); // 内存调测信息输出到/storage/mem_debug.txt文件中,如果该文件创建失败,则信息通过串口输出。 + char *ptr = malloc(MALLOC_LEAK_SIZE); + memset(ptr, '1', MALLOC_LEAK_SIZE); + + watch_mem(); // 在当前代码逻辑处查看线程级内存统计信息。 + func(); + check_heap_integrity(); // 检查堆内存节点完整性。 + check_leak(); // 在当前代码逻辑处检查堆内存是否泄漏(一般在程序退出之前校验比较准确,若在malloc和free调用逻辑之间做校验,则结果不准确)。 + return 0; +} +``` + +## 编译 + +``` +$ clang -o mem_check mem_check.c -funwind-tables -rdynamic -g -mfloat-abi=softfp -mcpu=cortex-a7 -mfpu=neon-vfpv4 -target arm-liteos --sysroot=/home//harmony/out/hispark_taurus/ipcamera_hispark_taurus/sysroot $(clang -mfloat-abi=softfp -mcpu=cortex-a7 -mfpu=neon-vfpv4 -target arm-liteos -print-file-name=libunwind.a) +``` + +>![](../public_sys-resources/icon-note.gif) **说明:** +>- 本编译示例基于将编译器的路径写入环境变量中,即.bashrc文件中。 +>- 编译用户程序及所需的lib库时,需要添加编译选项-funwind-tables,-rdynamic,-g,用于栈回溯。 +>- -mfloat-abi=softfp,-mcpu=cortex-a7,-mfpu=neon-vfpv4编译选项用于指定具体的芯片架构、浮点数计算优化、fpu,与具体的libc库使用的编译选项保持一致,否则链接时可能出现找不到libc库文件。 +>- -target arm-liteos用于指定编译器相关库文件路径。 +>- --sysroot=/home//harmony/out/hispark\_taurus/ipcamera\_hispark\_taurus/sysroot用于指定编译器库文件搜索根目录,假设OpenHarmony工程代码存放路径为/home//harmony。其中out/hispark\_taurus/ipcamera\_hispark\_taurus路径为在编译时,hb set命令指定的具体产品,本示例选择的是ipcamera\_hispark\_taurus产品。 +>- $\(clang -mfloat-abi=softfp -mcpu=cortex-a7 -mfpu=neon-vfpv4 -target arm-liteos -print-file-name=libunwind.a\)用于指定相应的unwind库的路径。 + +## 调测信息 + +``` +OHOS # ./mem_check +OHOS # +==PID:4== Heap memory statistics(bytes): // 堆内存统计信息 + [Check point]: // check点调用栈 + #00: [0x86c] -> mem_check + #01: <(null)+0x24baf9dc>[0x219dc] -> /lib/libc.so + + [TID: 18, Used: 0x320] // 18号线程堆内存占用,当前进程仅一个线程 + +==PID:4== Total heap: 0x320 byte(s), Peak: 0x320 byte(s) + +Check heap integrity ok! // 堆内存完整性检查 + +==PID:4== Detected memory leak(s): // 内存泄漏信息及调用栈 + [Check point]: + #00: [0x2da4c] -> /lib/libc.so + #01: [0x878] -> mem_check + + [TID:18 Leak:0x320 byte(s)] Allocated from: + #00: [0x850] -> mem_check + #01: <(null)+0x24baf9dc>[0x219dc] -> /lib/libc.so + + [TID:18 Leak:0x320 byte(s)] Allocated from: + #00: [0x810] -> mem_check + #01: [0x870] -> mem_check + #02: <(null)+0x24baf9dc>[0x219dc] -> /lib/libc.so + +==PID:4== SUMMARY: 0x640 byte(s) leaked in 2 allocation(s). + +==PID:4== Detected memory leak(s): + [Check point]: + #00: [0x2da4c] -> /lib/libc.so + #01: [0x111ec] -> /lib/libc.so + + [TID:18 Leak:0x320 byte(s)] Allocated from: + #00: [0x850] -> mem_check + #01: <(null)+0x24baf9dc>[0x219dc] -> /lib/libc.so + + [TID:18 Leak:0x320 byte(s)] Allocated from: + #00: [0x810] -> mem_check + #01: [0x870] -> mem_check + #02: <(null)+0x24baf9dc>[0x219dc] -> /lib/libc.so + +==PID:4== SUMMARY: 0x640 byte(s) leaked in 2 allocation(s). + +Check heap integrity ok! +``` + +## 调用栈解析 + +提供parse\_mem\_info.sh脚本可以对调用栈进行解析,解析脚本存放的路径:kernel/liteos\_a/tools/scripts/parse\_memory/parse\_mem\_info.sh。利用脚本可以将相应的调测信息转换成具体的源码行号,如下命令所示,mem\_debug.txt保存的是内存调测信息,elf1、elf2等文件是需要解析的elf文件。 + +``` +$ ./parse_mem_info.sh mem_debug.txt elf1 elf2 elf3 ... +``` + +例如: + +``` +$ ./parse_mem_info.sh mem_debug.txt mem_check +Compiler is [gcc/llvm]: llvm +Now using addr2line ... + +==PID:4== Heap memory statistics(bytes): + [Check point]: + #00: [0x86c] at /usr1/xxx/TEST_ELF/mem_check.c:22 + #01: <(null)+0x24baf9dc>[0x219dc] -> /lib/libc.so + + [TID: 18, Used: 0x320] + +==PID:4== Total heap: 0x320 byte(s), Peak: 0x320 byte(s) + +Check heap integrity ok! + +==PID:4== Detected memory leak(s): + [Check point]: + #00: [0x2da4c] -> /lib/libc.so + #01: [0x878] at /usr1/xxx/TEST_ELF/mem_check.c:28 + + [TID:18 Leak:0x320 byte(s)] Allocated from: + #00: [0x850] at /usr1/xxx/TEST_ELF/mem_check.c:17 + #01: <(null)+0x24baf9dc>[0x219dc] -> /lib/libc.so + + [TID:18 Leak:0x320 byte(s)] Allocated from: + #00: [0x810] at /usr1/xxx/TEST_ELF/mem_check.c:9 + #01: [0x870] at /usr1/xxx/TEST_ELF/mem_check.c:24 + #02: <(null)+0x24baf9dc>[0x219dc] -> /lib/libc.so + +==PID:4== SUMMARY: 0x640 byte(s) leaked in 2 allocation(s). +``` + diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-user-guide-use-cli.md b/zh-cn/device-dev/kernel/kernel-small-debug-user-guide-use-cli.md new file mode 100644 index 0000000000000000000000000000000000000000..129757a1faba0e63fbce58035d6375a4b458bdb2 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-small-debug-user-guide-use-cli.md @@ -0,0 +1,229 @@ +# 命令行参数方式 + +- [示例代码](#section13793104782316) +- [编译](#section1676431122320) +- [使用mwatch参数命令](#section1703415132311) +- [调用栈解析](#section1880675510221) +- [使用mrecord参数命令](#section071022822210) + +对用户态进程进行内存相关的检查时,除了接口调用方式还可以通过命令行方式进行内存统计、内存泄漏或内存完整性检查。 + +``` +--mwatch:初始化内存调测功能,注册信号。内存调测信息将从串口输出; +--mrecord :初始化内存调测功能,注册信号。内存调测信息将保存至f_path文件,若f_path创建失败,则内存调测信息将从串口输出 +``` + +在待调测的进程未退出时可使用信号机制获取对应信息: + +``` +kill -35 # 查看线程级堆内存占用 +kill -36 # 检查是否存在堆内存泄漏 +kill -37 # 检查堆内存头节点是否完整 +``` + +## 示例代码 + +代码功能:构造内存问题利用命令行方式进行内存调测。 + +``` +#include +#include +#include + +#define MALLOC_LEAK_SIZE 0x300 + +void func(void) { + char *ptr = malloc(MALLOC_LEAK_SIZE); + memset(ptr, '3', MALLOC_LEAK_SIZE); +} + +int main() +{ + char *ptr = malloc(MALLOC_LEAK_SIZE); + memset(ptr, '1', MALLOC_LEAK_SIZE); + func(); + while (1); +} +``` + +## 编译 + +参考[接口调用一节](kernel-small-debug-user-guide-use-api.md#section534302242515)。 + +## 使用mwatch参数命令 + +``` +OHOS # ./mem_check --mwatch // 利用task命令可以查到mem_check进程的pid为4 +OHOS # +OHOS # kill -35 4 // 查看堆内存统计信息 +OHOS # +==PID:4== Heap memory statistics(bytes): + [Check point]: + #00: [0x58dfc] -> /lib/libc.so + + [TID: 18, Used: 0x640] + +==PID:4== Total heap: 0x640 byte(s), Peak: 0x640 byte(s) + +OHOS # kill -36 4 // 检查是否存在堆内存泄漏 +OHOS # +==PID:4== Detected memory leak(s): + [Check point]: + #00: [0x2da4c] -> /lib/libc.so + #01: [0x58dfc] -> /lib/libc.so + + [TID:18 Leak:0x320 byte(s)] Allocated from: + #00: [0x724] -> mem_check + #01: <(null)+0x2555a9dc>[0x219dc] -> /lib/libc.so + + [TID:18 Leak:0x320 byte(s)] Allocated from: + #00: [0x6ec] -> mem_check + #01: [0x740] -> mem_check + #02: <(null)+0x2555a9dc>[0x219dc] -> /lib/libc.so + +==PID:4== SUMMARY: 0x640 byte(s) leaked in 2 allocation(s). + +OHOS # kill -37 4 // 检查堆内存头节点的完整性 +OHOS # +Check heap integrity ok! +``` + +## 调用栈解析 + +将调测信息保存至test.txt文件中,利用脚本进行解析,获取内存泄漏的具体行号。 + +``` +$ ./parse_mem_info.sh test.txt mem_check +Compiler is [gcc/llvm]: llvm +Now using addr2line ... + +==PID:4== Detected memory leak(s): + [Check point]: + #00: [0x2da4c] -> /lib/libc.so + #01: [0x58dfc] -> /lib/libc.so + + [TID:18 Leak:0x320 byte(s)] Allocated from: + #00: [0x724] at /usr1/xxx/TEST_ELF/mem_check.c:14 + #01: <(null)+0x2555a9dc>[0x219dc] -> /lib/libc.so + + [TID:18 Leak:0x320 byte(s)] Allocated from: + #00: [0x6ec] at /usr1/xxx/TEST_ELF/mem_check.c:8 + #01: [0x740] at /usr1/xxx/TEST_ELF/mem_check.c:19 + #02: <(null)+0x2555a9dc>[0x219dc] -> /lib/libc.so + +==PID:4== SUMMARY: 0x640 byte(s) leaked in 2 allocation(s). +``` + +## 使用mrecord参数命令 + +1. 执行用户程序并指定记录内存调测信息的文件路径 + + ``` + OHOS # ./mem_check --mrecord /storage/check.txt + ``` + +2. 利用kill -35 统计内存信息,该信息将会输出到文件中,使用cat命令查看 + + ``` + OHOS # kill -35 4 + OHOS # Memory statistics information saved in /storage/pid(4)_check.txt + + OHOS # cat /storage/pid(4)_check.txt + + ==PID:4== Heap memory statistics(bytes): + [Check point]: + #00: [0x5973c] -> /lib/libc.so + + [TID: 18, Used: 0x640] + + ==PID:4== Total heap: 0x640 byte(s), Peak: 0x640 byte(s) + ``` + +3. 利用kill -36 校验内存完整性,该信息将会输出到文件中,使用cat命令查看 + + ``` + OHOS # kill -36 4 + OHOS # Leak check information saved in /storage/pid(4)_check.txt + + OHOS # cat /storage/pid(4)_check.txt + + ==PID:4== Heap memory statistics(bytes): + [Check point]: + #00: [0x5973c] -> /lib/libc.so + + [TID: 18, Used: 0x640] + + ==PID:4== Total heap: 0x640 byte(s), Peak: 0x640 byte(s) + + ==PID:4== Detected memory leak(s): + [Check point]: + #00: [0x2e38c] -> /lib/libc.so + #01: [0x5973c] -> /lib/libc.so + + [TID:18 Leak:0x320 byte(s)] Allocated from: + #00: [0x724] -> mem_check + #01: <(null)+0x1fdd231c>[0x2231c] -> /lib/libc.so + + [TID:18 Leak:0x320 byte(s)] Allocated from: + #00: [0x6ec] -> mem_check + #01: [0x740] -> mem_check + #02: <(null)+0x1fdd231c>[0x2231c] -> /lib/libc.so + + ==PID:4== SUMMARY: 0x640 byte(s) leaked in 2 allocation(s). + ``` + +4. 利用kill -9 杀掉当前进程,进程退出后会默认校验内存完整性,该信息将会输出到文件中,使用cat命令查看 + + ``` + OHOS # kill -9 4 + OHOS # Leak check information saved in /storage/pid(4)_check.txt + + Check heap integrity ok! + + OHOS # cat /storage/pid(4)_check.txt + OHOS # + ==PID:4== Heap memory statistics(bytes): + [Check point]: + #00: [0x5973c] -> /lib/libc.so + + [TID: 18, Used: 0x640] + + ==PID:4== Total heap: 0x640 byte(s), Peak: 0x640 byte(s) + + ==PID:4== Detected memory leak(s): + [Check point]: + #00: [0x2e38c] -> /lib/libc.so + #01: [0x5973c] -> /lib/libc.so + + [TID:18 Leak:0x320 byte(s)] Allocated from: + #00: [0x724] -> mem_check + #01: <(null)+0x1fdd231c>[0x2231c] -> /lib/libc.so + + [TID:18 Leak:0x320 byte(s)] Allocated from: + #00: [0x6ec] -> mem_check + #01: [0x740] -> mem_check + #02: <(null)+0x1fdd231c>[0x2231c] -> /lib/libc.so + + ==PID:4== SUMMARY: 0x640 byte(s) leaked in 2 allocation(s). + + ==PID:4== Detected memory leak(s): + [Check point]: + #00: [0x2e38c] -> /lib/libc.so + #01: [0x11b2c] -> /lib/libc.so + + [TID:18 Leak:0x320 byte(s)] Allocated from: + #00: [0x724] -> mem_check + #01: <(null)+0x1fdd231c>[0x2231c] -> /lib/libc.so + + [TID:18 Leak:0x320 byte(s)] Allocated from: + #00: [0x6ec] -> mem_check + #01: [0x740] -> mem_check + #02: <(null)+0x1fdd231c>[0x2231c] -> /lib/libc.so + + ==PID:4== SUMMARY: 0x640 byte(s) leaked in 2 allocation(s). + ``` + + +>![](../public_sys-resources/icon-note.gif) **说明:** +>上述连续记录的信息会逐步追加到初始化时所指定的文件中,故最后cat文件时,文件中还包含历史记录的信息内容。 + diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-user-guide-use.md b/zh-cn/device-dev/kernel/kernel-small-debug-user-guide-use.md new file mode 100644 index 0000000000000000000000000000000000000000..693255e5ed286d06891ed866b675c38997834340 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-small-debug-user-guide-use.md @@ -0,0 +1,17 @@ +# 使用说明 + +编译OpenHarmony工程时默认编译的是debug版本,即libc库已经集成内存调测相关的接口实现,用户可以根据具体需要决定是否使能内存调测功能。 + +堆内存调测功能提供两种方式供用户使用:接口调用及命令行参数。 + +- 接口调用:优点是可以较精确的检查某一段代码逻辑的堆内存相关信息,缺点是需要修改用户代码。 +- 命令行参数:优点是无需修改用户代码,缺点是无法精确的校验某一段逻辑的堆内存信息。 + +>![](../public_sys-resources/icon-note.gif) **说明:** +>内存调测功能使能后,进程退出时会默认进行一次堆内存泄漏和堆内存完整性检查。内存调测功能未使能时,堆内存统计、堆内存泄漏检查、堆内存完整性校验功能不会开启,调用相关调测接口无响应。 + +- **[接口调用方式](kernel-small-debug-user-guide-use-api.md)** + +- **[命令行参数方式](kernel-small-debug-user-guide-use-cli.md)** + + diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-user-guide.md b/zh-cn/device-dev/kernel/kernel-small-debug-user-guide.md new file mode 100644 index 0000000000000000000000000000000000000000..cd541f2cfd02c351f76a6716252266bb87a7d488 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-small-debug-user-guide.md @@ -0,0 +1,7 @@ +# 使用指导 + +- **[接口说明](kernel-small-debug-user-guide-api.md)** + +- **[使用说明](kernel-small-debug-user-guide-use.md)** + + diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-user.md b/zh-cn/device-dev/kernel/kernel-small-debug-user.md new file mode 100644 index 0000000000000000000000000000000000000000..e36276326b878149ba308f8f0a75c5b526425b0a --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-small-debug-user.md @@ -0,0 +1,17 @@ +# 用户态内存调测 + +- **[基本概念](kernel-small-debug-user-concept.md)** + +- **[运行机制](kernel-small-debug-user-function.md)** + +- **[使用指导](kernel-small-debug-user-guide.md)** + +- **[常见问题场景](kernel-small-debug-user-faqs.md)** + +- **[Linux内核概述](kernel-standard-overview.md)** + +- **[OpenHarmony开发板Patch使用指导](kernel-standard-patch.md)** + +- **[Linux内核编译与构建指导](kernel-standard-build.md)** + + diff --git a/zh-cn/device-dev/subsystems/subsys-security-sigverify.md b/zh-cn/device-dev/subsystems/subsys-security-sigverify.md index 7c46ac23f5d5892104ed36a6b7b357fb5b3d8f8d..b1a14628ca79609c129d807ba52adbecfd12a9f1 100644 --- a/zh-cn/device-dev/subsystems/subsys-security-sigverify.md +++ b/zh-cn/device-dev/subsystems/subsys-security-sigverify.md @@ -92,5 +92,5 @@ ### 生成OpenHarmony签名应用 -参考文档:https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/quick-start/%E9%85%8D%E7%BD%AEOpenHarmony%E5%BA%94%E7%94%A8%E7%AD%BE%E5%90%8D%E4%BF%A1%E6%81%AF.md +参考文档:https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/quick-start/configuring-openharmony-app-signature.md diff --git a/zh-cn/readme.md b/zh-cn/readme.md index ac183bb6a815c6346024d80a7df0dcd9636c6b4b..a8aeda8b9cf5977171b6dffec98508f3d0248110 100644 --- a/zh-cn/readme.md +++ b/zh-cn/readme.md @@ -17,6 +17,7 @@ - Security:[隐私与安全](device-dev/security/Readme-CN.md) - guide:开发示例 + - [碰一碰](device-dev/guide/device-wlan-touch.md) - [WLAN连接类产品](device-dev/guide/device-wlan.md)(LED外设控制、集成三方SDK) - [无屏摄像头类产品](device-dev/guide/device-iotcamera-control.md)(摄像头控制) - [带屏摄像头类产品](device-dev/guide/device-camera.md)(屏幕和摄像头控制、视觉应用开发)